<?php

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

use Myvetshop\Module\Clinique\Entity\ProductFood;
use Myvetshop\Module\Clinique\Entity\ProductFoodLang;
use Myvetshop\Module\Clinique\Prestashop\Hook\DisplayProductExtraContent\ProductFoodListener;
use Myvetshop\Module\Clinique\Repository\ProductFoodRepository;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use PrestaShop\PrestaShop\Adapter\LegacyContext;
use PrestaShop\PrestaShop\Core\Product\ProductExtraContent;

class ProductFoodListenerTest extends TestCase
{
    private ProductFoodListener $productFoodListener;

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

    /**
     * @var ProductFoodRepository&MockObject
     */
    private ProductFoodRepository $productFoodRepository;

    protected function setUp(): void
    {
        $this->legacyContext = $this->createMock(LegacyContext::class);
        $this->productFoodRepository = $this->createMock(ProductFoodRepository::class);

        $this->productFoodListener = new ProductFoodListener(
            $this->legacyContext,
            $this->productFoodRepository
        );
    }

    /**
     * Test displayProductExtraContent method without a context.
     */
    public function testDisplayProductExtraContentWithoutContext(): void
    {
        $this->legacyContext
            ->expects($this->once())
            ->method('getContext')
            ->willReturn(null);

        $this->assertEmpty(
            $this->productFoodListener->displayProductExtraContent($this->createMock(\Product::class))
        );
    }

    /**
     * Test displayProductExtraContent method with a non-food product.
     */
    public function testDisplayProductExtraContentWithNonFoodProduct(): void
    {
        $this->legacyContext
            ->expects($this->once())
            ->method('getContext')
            ->willReturn($this->createMock(\Context::class));

        $this->productFoodRepository
            ->expects($this->once())
            ->method('findOneBy')
            ->willReturn(null);

        $this->assertEmpty(
            $this->productFoodListener->displayProductExtraContent($this->createMock(\Product::class))
        );
    }

    /**
     * Test displayProductExtraContent method with a non-food product.
     */
    public function testDisplayProductExtraContentWithFoodProductNoLang(): void
    {
        $context = $this->createMock(\Context::class);
        $context->smarty = $this->createMock(\Smarty::class);
        $context->language = $this->createMock(\Language::class);
        $context->language->id = 1;

        $this->legacyContext
            ->expects($this->once())
            ->method('getContext')
            ->willReturn($context);

        $productFood = new ProductFood();
        $this->productFoodRepository
            ->expects($this->once())
            ->method('findOneBy')
            ->willReturn($productFood);

        $this->assertEmpty(
            $this->productFoodListener->displayProductExtraContent($this->createMock(\Product::class))
        );
    }

    /**
     * Test displayProductExtraContent method with a food product.
     */
    public function testDisplayProductExtraContentWithFoodProduct(): void
    {
        $context = $this->createMock(\Context::class);
        $context->smarty = $this->createMock(\Smarty::class);
        $context->language = $this->createMock(\Language::class);
        $context->language->id = 1;

        $this->legacyContext
            ->expects($this->once())
            ->method('getContext')
            ->willReturn($context);

        $productFood = new ProductFood();
        $productFoodLang = new ProductFoodLang();
        $productFoodLang->productFood = $productFood;
        $productFoodLang->idLang = 1;
        $productFood->addLang($productFoodLang);

        $this->productFoodRepository
            ->expects($this->once())
            ->method('findOneBy')
            ->willReturn($productFood);

        $result = $this->productFoodListener->displayProductExtraContent(
            $this->createMock(\Product::class)
        );

        $this->assertNotEmpty($result);
        $this->assertInstanceOf(ProductExtraContent::class, $result[0]);
    }
}
