<?php

declare(strict_types=1);

/*
 * This file is part of the VITICORE2 package.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CpCreation\VitiCore\Tests\Twig;

use PHPUnit\Framework\TestCase;
use Twig\Environment;
use Twig\Loader\ArrayLoader;
use Twig\Loader\ChainLoader;
use Twig\Loader\FilesystemLoader;
use Twig\TwigFunction;

final class AdminClientFilterTemplateTest extends TestCase
{
    public function testUnsetBooleanFiltersDoNotSelectNoByDefault(): void
    {
        $html = $this->render([
            'group_id' => 'partner-group',
            'marketing_opt_in_input' => null,
            'has_orders_input' => null,
            'is_verified_input' => null,
        ]);

        self::assertSame('partner-group', $this->selectedOptionValue($html, 'group_id'));
        self::assertNull($this->selectedOptionValue($html, 'marketing_opt_in'));
        self::assertNull($this->selectedOptionValue($html, 'has_orders'));
        self::assertNull($this->selectedOptionValue($html, 'is_verified'));
    }

    public function testExplicitNoBooleanFiltersRemainSelected(): void
    {
        $html = $this->render([
            'group_id' => null,
            'marketing_opt_in_input' => '0',
            'has_orders_input' => '0',
            'is_verified_input' => '0',
        ]);

        self::assertSame('0', $this->selectedOptionValue($html, 'marketing_opt_in'));
        self::assertSame('0', $this->selectedOptionValue($html, 'has_orders'));
        self::assertSame('0', $this->selectedOptionValue($html, 'is_verified'));
    }

    /**
     * @param array{
     *     group_id: ?string,
     *     marketing_opt_in_input: ?string,
     *     has_orders_input: ?string,
     *     is_verified_input: ?string
     * } $filters
     */
    private function render(array $filters): string
    {
        $viewsDirectory = \dirname(__DIR__, 2).'/src/Bridge/Symfony/Bundle/Resources/views';
        $filesystemLoader = new FilesystemLoader($viewsDirectory);
        $filesystemLoader->addPath($viewsDirectory, 'CpCreationVitiCore');
        $twig = new Environment(new ChainLoader([
            new ArrayLoader([
                '@CpCreationVitiCore/admin/base.html.twig' => '{% block content %}{% endblock %}',
            ]),
            $filesystemLoader,
        ]));
        $twig->addFunction(new TwigFunction(
            'path',
            static fn (string $route, array $parameters = []): string => '/'.$route.([] === $parameters ? '' : '?'.http_build_query($parameters)),
        ));
        $twig->addFunction(new TwigFunction('csrf_token', static fn (): string => 'token'));

        return $twig->render('admin/client/index.html.twig', [
            'items' => [],
            'filters' => [
                ...$filters,
                'search' => null,
                'query_parameters' => array_filter($filters, static fn (mixed $value): bool => null !== $value),
            ],
            'filter_options' => [
                'groups' => ['partner-group' => 'Partenaire'],
                'marketing_choices' => ['1' => 'Oui', '0' => 'Non'],
                'order_choices' => ['1' => 'Oui', '0' => 'Non'],
                'verification_choices' => ['1' => 'Oui', '0' => 'Non'],
            ],
            'users_with_orders' => [],
        ]);
    }

    private function selectedOptionValue(string $html, string $selectId): ?string
    {
        $document = new \DOMDocument();
        $previousState = libxml_use_internal_errors(true);
        $document->loadHTML($html);
        libxml_clear_errors();
        libxml_use_internal_errors($previousState);

        $xpath = new \DOMXPath($document);
        $selectedOptions = $xpath->query(sprintf('//select[@id="%s"]/option[@selected]', $selectId));

        self::assertNotFalse($selectedOptions);
        self::assertLessThanOrEqual(1, $selectedOptions->length);

        if (0 === $selectedOptions->length) {
            return null;
        }

        return $selectedOptions->item(0)?->attributes?->getNamedItem('value')?->nodeValue;
    }
}
