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

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Context\GroupContext;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Twig\Components\Collection\ProductCollection as ProductCollectionComponent;
use CpCreation\VitiCore\Product\Model\Product;
use CpCreation\VitiCore\Product\Model\ProductCollection;
use CpCreation\VitiCore\Product\Model\ProductPriceGroup;
use CpCreation\VitiCore\Product\Model\ProductVariant;
use CpCreation\VitiCore\Product\Repository\ProductCollectionRepository;
use CpCreation\VitiCore\Product\Repository\ProductRepository;
use PHPUnit\Framework\TestCase;

final class ProductCollectionComponentTest extends TestCase
{
    protected function tearDown(): void
    {
        GroupContext::$groupId = null;
    }

    public function testProductsAreFilteredByActivePriceGroup(): void
    {
        $defaultGroup = new ProductPriceGroup();
        $vipGroup = new ProductPriceGroup();
        GroupContext::$groupId = $defaultGroup->getId()->toString();

        $defaultProduct = $this->createPublishedProduct($defaultGroup);
        $vipProduct = $this->createPublishedProduct($vipGroup);

        $collection = new ProductCollection();
        $collection->addProduct($defaultProduct);
        $collection->addProduct($vipProduct);

        $collectionRepository = $this->createMock(ProductCollectionRepository::class);
        $collectionRepository->method('findOneByCode')
            ->with('champagnes')
            ->willReturn($collection);

        $component = new ProductCollectionComponent(
            $collectionRepository,
            $this->createMock(ProductRepository::class),
        );
        $component->collection = 'champagnes';

        self::assertSame([$defaultProduct], $component->getProducts());
    }

    public function testAutomaticProductsAreFilteredByActivePriceGroup(): void
    {
        $defaultGroup = new ProductPriceGroup();
        GroupContext::$groupId = $defaultGroup->getId()->toString();

        $defaultProduct = $this->createPublishedProduct($defaultGroup);
        $collection = new ProductCollection();
        $collection->setMode(ProductCollection::MODE_AUTOMATIC);

        $collectionRepository = $this->createMock(ProductCollectionRepository::class);
        $collectionRepository->method('findOneByCode')
            ->with('champagnes')
            ->willReturn($collection);

        $productRepository = $this->createMock(ProductRepository::class);
        $productRepository->expects(self::once())
            ->method('findPublishedForProductCollection')
            ->with($collection, GroupContext::$groupId, false, null)
            ->willReturn([$defaultProduct]);

        $component = new ProductCollectionComponent($collectionRepository, $productRepository);
        $component->collection = 'champagnes';

        self::assertSame([$defaultProduct], $component->getProducts());
    }

    public function testFutureCollectionIsNotExposedToTheTemplate(): void
    {
        $collection = new ProductCollection();
        $collection->setPublishedAt(new \DateTimeImmutable('2100-01-01 00:00:00'));

        $collectionRepository = $this->createMock(ProductCollectionRepository::class);
        $collectionRepository->expects(self::once())
            ->method('findOneByCode')
            ->with('champagnes')
            ->willReturn($collection);

        $component = new ProductCollectionComponent(
            $collectionRepository,
            $this->createMock(ProductRepository::class),
        );
        $component->collection = 'champagnes';

        self::assertNull($component->getProductCollection());
        self::assertSame([], $component->getProducts());
    }

    private function createPublishedProduct(ProductPriceGroup $group): Product
    {
        $product = new Product();
        $product->addGroup($group);
        $product->addVariant(new ProductVariant());

        return $product;
    }
}
