<?php
declare(strict_types=1);

namespace App\Filter\DoctrineFilter;

use App\Attribute\DateTimeConstraintAware;
use App\Service\Constraint\DateTimeConstraint;
use App\Tests\Filter\DoctrineFilter\DateTimeFilterTest;
use Doctrine\ORM\Query\Filter\SQLFilter;

/**
 * Classe AbstractTimeFilterUtils fournie des méthodes pour construire les requetes de contrainte de temps
 */
abstract class AbstractTimeFilter extends SQLFilter
{
    /**
     * Fonction permettant de construire la requête SQL correspondante aux contraintes
     * @param array<string, array<string, int[]>> $constraints
     * @param string $targetTableAlias
     * @param array<string, mixed> $fields
     * @return string
     */
    protected function constructQuery(array $constraints, string $targetTableAlias, array $fields): string
    {
        $queryConditionsAND = [];
        foreach ($constraints as $key => $constraint) {
            $queryConditionsOR = [];
            foreach ($constraint as $date => $conditions){
                foreach ($conditions as $condition){
                    $arithmetic = $this->getArithmeticValue($condition);
                    if(!is_null($arithmetic)) {
                        $queryConditionsOR[] = sprintf("%s.%s %s '%s'", $targetTableAlias, $fields[$key], $arithmetic, $date);
                    }
                    else {
                        $queryConditionsOR[] = sprintf("%s.%s IS NULL", $targetTableAlias, $fields[$key]);
                    }
                }
            }
            if(!empty($queryConditionsOR)) {
                $queryConditionsAND[] = sprintf("(%s)", join(' OR ', $queryConditionsOR));
            }
        }

        return implode(" AND ", $queryConditionsAND);
    }

    /**
     * Fonction retournant la valeur arithmétique correspondant à la condition de la contrainte
     * @param int $condition
     * @return string|null
     * @see DateTimeFilterTest::testGetArithmeticValue()
     */
    protected function getArithmeticValue(int $condition): ?string
    {
        return match ($condition) {
            DateTimeConstraint::INF => '<',
            DateTimeConstraint::EQUAL => '=',
            DateTimeConstraint::SUP => '>',
            DateTimeConstraint::INF + DateTimeConstraint::EQUAL => '<=',
            DateTimeConstraint::SUP + DateTimeConstraint::EQUAL => '>=',
            default => null,
        };
    }
}