<?php

namespace App\Tests\A_Unit\Cart\Preventer;

use Myvetshop\Module\Clinique\Cart\Preventer\CentravetPreventer;
use Myvetshop\Module\Clinique\Entity\MyvetshopClinique;
use Myvetshop\Module\Clinique\Repository\MyvetshopCliniqueRepository;
use Myvetshop\Module\Clinique\Stock\CentravetStockApi;
use Myvetshop\Module\Clinique\Stock\CentravetStockApiFactory;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

class CentravetPreventerTest extends TestCase
{
    /**
     * @var CentravetStockApiFactory&MockObject
     */
    protected CentravetStockApiFactory $centravetStockApiFactory;

    /**
     * @var \Db&MockObject
     */
    protected \Db $db;

    /**
     * @var MyvetshopCliniqueRepository&MockObject
     */
    protected MyvetshopCliniqueRepository $cliniqueRepository;

    protected CentravetPreventer $centravetPreventer;

    protected function setUp(): void
    {
        $this->centravetStockApiFactory = $this->getMockBuilder(CentravetStockApiFactory::class)
            ->disableOriginalConstructor()
            ->getMock();

        $this->db = $this->getMockBuilder(\Db::class)
            ->disableOriginalConstructor()
            ->getMock();

        $this->cliniqueRepository = $this->getMockBuilder(MyvetshopCliniqueRepository::class)
            ->disableOriginalConstructor()
            ->getMock();

        $this->centravetPreventer = new CentravetPreventer(
            $this->centravetStockApiFactory,
            $this->db,
            $this->cliniqueRepository
        );
    }

    public function testGetErrorMessagePrevented(): void
    {
        $clinique = new MyvetshopClinique();
        $clinique->centrale = 'centravet';
        $clinique->codeClient = '123456';
        $this->cliniqueRepository
            ->expects($this->once())
            ->method('findByGroupId')
            ->with(1)
            ->willReturn($clinique);

        $customer = $this->getMockBuilder(\Customer::class)
            ->disableOriginalConstructor()
            ->getMock();

        $customer->id_default_group = 1;

        $product = $this->getMockBuilder(\Product::class)
            ->disableOriginalConstructor()
            ->getMock();
        $product->id = 123;

        $this->db
            ->expects($this->once())
            ->method('getValue')
            ->willReturn('VET000');

        $cart = $this->getMockBuilder(\Cart::class)
            ->disableOriginalConstructor()
            ->getMock();

        $api = $this->getMockBuilder(CentravetStockApi::class)
            ->disableOriginalConstructor()
            ->getMock();

        $this->centravetStockApiFactory
            ->method('create')
            ->willReturn($api);

        $api
            ->expects($this->once())
            ->method('checkStock')
            ->with($clinique->codeClient, 'VET000', 1)
            ->willReturn(false);

        $errorMessage = $this->centravetPreventer->getErrorMessage(
            $product,
            0,
            1,
            'up',
            $customer,
            $cart,
        );

        self::assertIsString($errorMessage);
        self::assertEquals(CentravetPreventer::ERROR_MESSAGE, $errorMessage);
    }

    public function testGetErrorMessageNotPreventedInStock(): void
    {
        $clinique = new MyvetshopClinique();
        $clinique->centrale = 'centravet';
        $clinique->codeClient = '123456';
        $this->cliniqueRepository
            ->expects($this->once())
            ->method('findByGroupId')
            ->with(1)
            ->willReturn($clinique);

        $customer = $this->getMockBuilder(\Customer::class)
            ->disableOriginalConstructor()
            ->getMock();

        $customer->id_default_group = 1;

        $product = $this->getMockBuilder(\Product::class)
            ->disableOriginalConstructor()
            ->getMock();
        $product->id = 123;

        $this->db
            ->expects($this->once())
            ->method('getValue')
            ->willReturn('VET000');

        $cart = $this->getMockBuilder(\Cart::class)
            ->disableOriginalConstructor()
            ->getMock();

        $api = $this->getMockBuilder(CentravetStockApi::class)
            ->disableOriginalConstructor()
            ->getMock();

        $this->centravetStockApiFactory
            ->method('create')
            ->willReturn($api);

        $api
            ->expects($this->once())
            ->method('checkStock')
            ->with($clinique->codeClient, 'VET000', 1)
            ->willReturn(true);

        $errorMessage = $this->centravetPreventer->getErrorMessage(
            $product,
            0,
            1,
            'up',
            $customer,
            $cart
        );

        self::assertNull($errorMessage);
    }
}
