<?php

declare(strict_types=1);

namespace App\Filter;

use ApiPlatform\Doctrine\Orm\Filter\AbstractFilter;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\Operation;
use Doctrine\ORM\QueryBuilder;

final class MultiSearchFilter extends AbstractFilter
{
    public function getDescription(string $resourceClass): array
    {
        return [
            'search' => [
                'property'    => null,
                'type'        => 'string',
                'required'    => false,
                'description' => 'Search across: '.implode(', ', array_keys($this->properties ?? [])),
                'openapi'     => [
                    'allowEmptyValue' => true,
                ],
            ],
        ];
    }

    protected function filterProperty(string $property, mixed $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, ?Operation $operation = null, array $context = []): void
    {
        if ('search' !== $property || !$value) {
            return;
        }

        $fields = $this->properties ?? [];
        if (empty($fields)) {
            return;
        }

        $alias        = $queryBuilder->getRootAliases()[0];
        $orConditions = [];

        foreach (array_keys($fields) as $field) {
            $paramName      = $queryNameGenerator->generateParameterName($field);
            $orConditions[] = sprintf('LOWER(%s.%s) LIKE LOWER(:%s)', $alias, $field, $paramName);
            $queryBuilder->setParameter($paramName, '%'.$value.'%');
        }

        $queryBuilder->andWhere(implode(' OR ', $orConditions));
    }
}
