<?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\Controller;

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Controller\Site\ShopIndexController;
use CpCreation\VitiCore\Product\Model\ProductCategory;
use CpCreation\VitiCore\Product\Model\Translation\ProductCategoryTranslation;
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\Model\ShopConfig;
use CpCreation\VitiCore\Shop\Repository\ShopConfigRepository;
use CpCreation\VitiCore\Shop\ShopCatalogResolver;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Yaml\Yaml;
use Twig\Environment;

final class ShopIndexControllerTest extends TestCase
{
    public function testShopRouteValidatesTheCatalogBeforeRendering(): void
    {
        $routes = Yaml::parseFile(__DIR__.'/../../src/Bridge/Symfony/Bundle/Resources/config/routes/site_shop.yaml');

        self::assertSame(ShopIndexController::class, $routes['shop']['controller']);
    }

    public function testInvisibleCategoryIsRejectedBeforeTemplateRendering(): void
    {
        $categoryRepository = $this->createMock(ProductCategoryRepository::class);
        $categoryRepository->expects(self::once())
            ->method('findOnlyShop')
            ->willReturn([]);

        $priceGroupRepository = $this->createMock(ProductPriceGroupRepository::class);
        $priceGroupRepository->expects(self::once())
            ->method('getGroupByDefault')
            ->willReturn(null);

        $configRepository = $this->createMock(ShopConfigRepository::class);
        $configRepository->expects(self::once())
            ->method('findOne')
            ->willReturn(new ShopConfig());

        $resolver = new ShopCatalogResolver(
            $categoryRepository,
            $this->createMock(ProductRepository::class),
            $this->createMock(ProductCollectionRepository::class),
            $priceGroupRepository,
            $configRepository,
        );
        $controller = new ShopIndexController($resolver);

        $this->expectException(NotFoundHttpException::class);

        $controller('categorie-invisible');
    }

    public function testResolvedCategoryIsExposedToTheShopTemplate(): void
    {
        $category = new ProductCategory();
        $category->setCurrentLocale('fr');
        $translation = $category->translate('fr');
        self::assertInstanceOf(ProductCategoryTranslation::class, $translation);
        $translation->setSlug('champagne');

        $categoryRepository = $this->createMock(ProductCategoryRepository::class);
        $categoryRepository->expects(self::once())
            ->method('findOnlyShop')
            ->with(null)
            ->willReturn([$category]);

        $productRepository = $this->createMock(ProductRepository::class);
        $productRepository->expects(self::once())
            ->method('findOnlyShop')
            ->with(null, $category)
            ->willReturn([]);

        $priceGroupRepository = $this->createMock(ProductPriceGroupRepository::class);
        $priceGroupRepository->expects(self::once())
            ->method('getGroupByDefault')
            ->willReturn(null);

        $configRepository = $this->createMock(ShopConfigRepository::class);
        $configRepository->expects(self::once())
            ->method('findOne')
            ->willReturn(new ShopConfig());

        $resolver = new ShopCatalogResolver(
            $categoryRepository,
            $productRepository,
            $this->createMock(ProductCollectionRepository::class),
            $priceGroupRepository,
            $configRepository,
        );

        $twig = $this->createMock(Environment::class);
        $twig->expects(self::once())
            ->method('render')
            ->with('shop/index.html.twig', self::callback(
                static fn (array $context): bool => $category === ($context['category'] ?? null),
            ))
            ->willReturn('catalogue');

        $container = new Container();
        $container->set('twig', $twig);

        $controller = new ShopIndexController($resolver);
        $controller->setContainer($container);

        self::assertSame('catalogue', $controller('champagne')->getContent());
    }
}
