<?php

/*
 * 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\EventListener;

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Context\ShopCountryContext;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\EventListener\ComponentTemplateOverrideListener;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\EventListener\ShopCountryComponentListener;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Twig\Components\Shop\Catalog;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Twig\Components\Shop\CatalogMobileBar;
use CpCreation\VitiCore\Product\Repository\ProductCategoryRepository;
use CpCreation\VitiCore\Product\Repository\ProductCollectionRepository;
use CpCreation\VitiCore\Product\Repository\ProductPriceGroupRepository;
use CpCreation\VitiCore\Product\Repository\ProductRepository;
use CpCreation\VitiCore\Shop\Repository\ShopConfigRepository;
use CpCreation\VitiCore\Shop\ShopCatalogResolver;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Symfony\UX\TwigComponent\ComponentAttributes;
use Symfony\UX\TwigComponent\ComponentMetadata;
use Symfony\UX\TwigComponent\Event\PreRenderEvent;
use Symfony\UX\TwigComponent\MountedComponent;
use Twig\Runtime\EscaperRuntime;

final class ShopCountryComponentListenerTest extends TestCase
{
    public function testBlockedCatalogUsesTheThemeAwareBlockedTemplate(): void
    {
        $event = $this->createEvent('shop:Catalog', $this->createCatalog(), '@components/shop/Catalog.html.twig');

        (new ShopCountryComponentListener())($event);
        (new ComponentTemplateOverrideListener())($event);

        self::assertSame('@components/shop/CatalogBlocked.html.twig', $event->getTemplate());
        self::assertTrue($event->getVariables()[ComponentTemplateOverrideListener::OVERRIDE_APPLIED_VARIABLE]);
    }

    public function testBlockedCatalogMobileBarUsesTheThemeAwareBlockedTemplate(): void
    {
        $event = $this->createEvent('shop:CatalogMobileBar', $this->createCatalogMobileBar(), '@components/shop/CatalogMobileBar.html.twig');

        (new ShopCountryComponentListener())($event);
        (new ComponentTemplateOverrideListener())($event);

        self::assertSame('@components/shop/CatalogMobileBarBlocked.html.twig', $event->getTemplate());
        self::assertTrue($event->getVariables()[ComponentTemplateOverrideListener::OVERRIDE_APPLIED_VARIABLE]);
    }

    private function createCatalog(): Catalog
    {
        [$resolver, $requestStack, $context] = $this->createDependencies();

        return new Catalog($resolver, $requestStack, $context);
    }

    private function createCatalogMobileBar(): CatalogMobileBar
    {
        [$resolver, $requestStack, $context] = $this->createDependencies();

        return new CatalogMobileBar($resolver, $requestStack, $context);
    }

    /**
     * @return array{ShopCatalogResolver, RequestStack, ShopCountryContext}
     */
    private function createDependencies(): array
    {
        $request = new Request();
        $session = new Session(new MockArraySessionStorage());
        $session->set('blockShop', true);
        $session->set('blockShopCountry', 'US');
        $request->setSession($session);

        $requestStack = new RequestStack();
        $requestStack->push($request);

        $resolver = new ShopCatalogResolver(
            $this->createMock(ProductCategoryRepository::class),
            $this->createMock(ProductRepository::class),
            $this->createMock(ProductCollectionRepository::class),
            $this->createMock(ProductPriceGroupRepository::class),
            $this->createMock(ShopConfigRepository::class),
        );

        return [$resolver, $requestStack, new ShopCountryContext($requestStack)];
    }

    private function createEvent(string $name, object $component, string $template): PreRenderEvent
    {
        $attributes = new ComponentAttributes([], new EscaperRuntime());
        $metadata = new ComponentMetadata([
            'key' => $name,
            'template' => $template,
            'class' => $component::class,
            'service_id' => $component::class,
        ]);
        $mounted = new MountedComponent($name, $component, $attributes);

        return new PreRenderEvent($mounted, $metadata, [
            'template' => 'shop/custom_catalog.html.twig',
        ]);
    }
}
