<?php

namespace AutoAdmin\Bundle\Core\Logic;

use Symfony\Component\PropertyAccess\PropertyAccessor;

/**
 * Format mainly used in yaml config for form fields in AA admin:
 * - { if: '_.static = false AND id = 611', property: '_tr.name', label: "ConditionalName", ... }
 *
 * Only "AND" supported for the time being
 */
class LogicTester
{
    protected PropertyAccessor $pa;

    public function __construct()
    {
        $this->pa = new PropertyAccessor();
    }

    public function test(string $test, object $subject): bool
    {
        // replace this by recursion + parenthesis regex down the road to permit complex cases and "OR" conditions
        $ands = explode('AND', $test);

        $tests = [];

        foreach ($ands as $and) {
            $and = trim($and);

            // normalize to "field operator value"
            $and = str_replace('IS NULL', '= NULL', $and);
            $and = str_replace('IS NOT NULL', '!= NULL', $and);

            // space-based split
            list($field, $operator, $value) = explode(' ', $and);

            $field = str_replace('_tr.', 'currentTranslation.', $field);
            $field = str_replace('_.', '', $field);

            switch ($value) {
                case 'true':
                    $value = true;
                    break;
                case 'false':
                    $value = false;
                    break;
                case 'NULL':
                    $value = null;
                    break;
            }

            if (
                (str_starts_with($value, '"') && str_ends_with($value, '"'))
                || (str_starts_with($value, '\'') && str_ends_with($value, '\''))
            ) {
                $value = substr($value, 1, -1);
            }

            if (is_numeric($value)) {
                $value = ((int)$value == (float)$value)
                    ? (int)$value
                    : (float)$value;
            }

//            dump($field);
//            dump($operator);
//            dump($value);

            switch ($operator) {
                case '=':
                case '==':
                case '===':
                    $test = $this->pa->getValue($subject, $field) === $value;
                    break;
                case '!=':
                case '!==':
                    $test = $this->pa->getValue($subject, $field) !== $value;
                    break;
                case '>':
                    $test = $this->pa->getValue($subject, $field) > $value;
                    break;
                case '>=':
                    $test = $this->pa->getValue($subject, $field) >= $value;
                    break;
                case '<':
                    $test = $this->pa->getValue($subject, $field) < $value;
                    break;
                case '<=':
                    $test = $this->pa->getValue($subject, $field) <= $value;
                    break;
            }

            $tests[] = $test;
        }

//        dump($tests);

        $allPassed = count(array_filter($tests)) === count($tests);

//        dump($allPassed);

        return $allPassed;
    }
}
