<?php

namespace App\Tests\A_Unit\Prestashop\Hook\DisplayFooterProduct;

use Myvetshop\Module\Clinique\Adapter\Recommandation\RecommandationCartRuleRepository;
use Myvetshop\Module\Clinique\Adapter\Recommandation\RecommandationProductCombinationSelector;
use Myvetshop\Module\Clinique\Prestashop\Hook\CrokitCartRuleFooterBandListener;
use Myvetshop\Module\Clinique\Prestashop\Product\ProductPriceComputer;
use Myvetshop\Module\Clinique\Repository\RecommandationRepository;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use PrestaShop\PrestaShop\Adapter\LegacyContext;

class CrokitCartRuleFooterBandListenerTest extends TestCase
{
    /**
     * @var \Context&MockObject
     */
    private \Context $context;

    /**
     * @var CrokitCartRuleFooterBandListener&MockObject
     */
    private CrokitCartRuleFooterBandListener $listener;

    /**
     * @var LegacyContext&MockObject
     */
    private LegacyContext $legacyContext;

    /**
     * @var ProductPriceComputer&MockObject
     */
    private ProductPriceComputer $productPriceComputer;

    /**
     * @var RecommandationCartRuleRepository&MockObject
     */
    private RecommandationCartRuleRepository $recommandationCartRuleRepository;

    /**
     * @var RecommandationProductCombinationSelector&MockObject
     */
    private RecommandationProductCombinationSelector $recommandationProductCombinationSelector;

    /**
     * @var RecommandationRepository&MockObject
     */
    private RecommandationRepository $recommandationRepository;

    /**
     * @var \Smarty&MockObject
     */
    private \Smarty $smarty;

    protected function setUp(): void
    {
        $this->legacyContext = $this->createMock(LegacyContext::class);
        $this->productPriceComputer = $this->createMock(ProductPriceComputer::class);
        $this->recommandationCartRuleRepository = $this->createMock(RecommandationCartRuleRepository::class);
        $this->recommandationProductCombinationSelector = $this->createMock(RecommandationProductCombinationSelector::class);
        $this->recommandationRepository = $this->createMock(RecommandationRepository::class);
        $this->smarty = $this->createMock(\Smarty::class);

        $this->context = $this->createMock(\Context::class);
        $this->context->smarty = $this->smarty;

        $this->legacyContext
            ->expects($this->any())
            ->method('getContext')
            ->will($this->returnValue($this->context));

        $this->listener = $this->getMockBuilder(CrokitCartRuleFooterBandListener::class)
            ->onlyMethods(['getToken', 'getGroup'])
            ->setConstructorArgs([
                $this->legacyContext,
                $this->productPriceComputer,
                $this->recommandationCartRuleRepository,
                $this->recommandationProductCombinationSelector,
                $this->recommandationRepository,
                $this->smarty,
            ])
            ->getMock();

        $this->listener
            ->method('getToken')
            ->willReturn('prestashop-token');
    }

    public function testDisplayFooterProductCustomerNotLogged(): void
    {
        $this->context->customer = $this->createMock(\Customer::class);
        $this->context->customer->method('isLogged')->willReturn(false);

        $result = $this->listener->displayFooterProduct(
            $this->createMock(\Category::class),
            $this->createMock(\Product::class),
        );

        $this->assertSame('', $result);
    }

    public function testDisplayFooterProductNoCartRule(): void
    {
        $this->context->customer = $this->createMock(\Customer::class);
        $this->context->customer->method('isLogged')->willReturn(true);

        $this->recommandationCartRuleRepository
            ->expects($this->any())
            ->method('getCartRuleForCustomerAndProduct')
            ->will($this->returnValue(null));

        $result = $this->listener->displayFooterProduct(
            $this->createMock(\Category::class),
            $this->createMock(\Product::class),
        );

        $this->assertSame('', $result);
    }

    public function testDisplayFooterProductWithCartRule(): void
    {
        $this->context->customer = $this->createMock(\Customer::class);
        $this->context->customer->method('isLogged')->willReturn(true);

        $cartRule = $this->createMock(\CartRule::class);

        $this->recommandationCartRuleRepository
            ->expects($this->any())
            ->method('getCartRuleForCustomerAndProduct')
            ->will($this->returnValue($cartRule));

        $this->smarty
            ->expects($this->once())
            ->method('fetch')
            ->willReturn('<markup>');

        $result = $this->listener->displayFooterProduct(
            $this->createMock(\Category::class),
            $this->createMock(\Product::class),
        );

        $this->assertEquals('<markup>', $result);
    }
}
