<?php

namespace App\Tests\A_Unit\Api\Crokit;

use Doctrine\ORM\EntityManagerInterface;
use Myvetshop\Module\Clinique\Adapter\Recommandation\RecommandationCartRuleRepository;
use Myvetshop\Module\Clinique\Api\Crokit\Dto\CrokitRecommandation;
use Myvetshop\Module\Clinique\Api\Crokit\RecommandationImporter;
use Myvetshop\Module\Clinique\Entity\Animal;
use Myvetshop\Module\Clinique\Entity\Factory\RecommandationFactory;
use Myvetshop\Module\Clinique\Entity\Recommandation;
use Myvetshop\Module\Clinique\Repository\AnimalRepository;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

class RecommandationImporterTest extends TestCase
{
    /**
     * @var AnimalRepository&MockObject
     */
    private AnimalRepository $animalRepository;

    /**
     * @var EntityManagerInterface&MockObject
     */
    private EntityManagerInterface $entityManager;

    /**
     * @var RecommandationFactory&MockObject
     */
    private RecommandationFactory $recommandationFactory;

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

    private RecommandationImporter $recommandationImporter;

    protected function setUp(): void
    {
        $this->animalRepository = $this->createMock(AnimalRepository::class);
        $this->entityManager = $this->createMock(EntityManagerInterface::class);
        $this->recommandationFactory = $this->createMock(RecommandationFactory::class);
        $this->recommandationCartRuleRepository = $this->createMock(RecommandationCartRuleRepository::class);

        $this->recommandationImporter = new RecommandationImporter(
            $this->animalRepository,
            $this->entityManager,
            $this->recommandationFactory,
            $this->recommandationCartRuleRepository
        );
    }

    public function testGetAnimal(): void
    {
        // Create a mock animal
        $animal = $this->createMock(Animal::class);

        $customer = $this->createMock(\Customer::class);
        $customer->id = 1;

        // Set the return value of repository method to the mock animal
        $this->animalRepository
            ->method('findOneBy')
            ->with([
                'id' => '1',
                'idCustomer' => 1,
            ])
            ->willReturn($animal);

        $reco = new CrokitRecommandation();
        $reco->esp = 'Chien';

        // Call the method and check the result
        $result = $this->recommandationImporter->getRecommandationAnimal(
            '1',
            $customer,
            $reco
        );
        $this->assertSame($animal, $result);
    }

    public function testGetAnimalAuto(): void
    {
        $customer = $this->createMock(\Customer::class);
        $customer->id = 1;

        $reco = new CrokitRecommandation();
        $reco->esp = 'Chien';
        $reco->petname = 'Medor';
        $reco->sex = 'Mâle castré';
        $reco->dob = '01-01-2024';
        $reco->productIDmvs1 = 10;
        $reco->qteAliment1 = 100;

        $result = $this->recommandationImporter->getRecommandationAnimal('auto', $customer, $reco);

        $this->assertEquals('Chien', $result->espece);
        $this->assertEquals('Medor', $result->nom);
        $this->assertEquals(1, $result->idCustomer);
        $this->assertEquals(1, $result->idGender);
        $this->assertNotNull($result->dateNaissance);
        $this->assertEquals('2024-01-01', $result->dateNaissance->format('Y-m-d'));
    }

    public function testCorrectRecommandationImport(): void
    {
        $crokitRecommandationMock = $this->createMock(CrokitRecommandation::class);
        $animalMock = $this->createMock(Animal::class);
        $recommandationMock = $this->getMockBuilder(Recommandation::class)->getMock();

        $this->entityManager
            ->expects($this->once())
            ->method('persist')
            ->with($recommandationMock);

        $this->entityManager
            ->expects($this->once())
            ->method('flush');

        $this->recommandationCartRuleRepository
            ->expects($this->once())
            ->method('createCartRule')
            ->with($recommandationMock);

        $this->recommandationFactory
            ->expects($this->once())
            ->method('fromDto')
            ->willReturn($recommandationMock);

        $recommandation = $this->recommandationImporter->import($crokitRecommandationMock, $animalMock);

        $this->assertEquals($recommandationMock, $recommandation);
    }
}
