<?php

namespace App\Tests\MessageHandler;

use App\Entity\Customer;
use App\Entity\PriceAutomatic;
use App\Entity\Revendeur;
use App\Entity\User;
use App\Message\MeilisearchSyncMessage;
use App\MessageHandler\MeilisearchSyncMessageHandler;
use App\Repository\CustomerRepository;
use App\Repository\PriceAutomaticRepository;
use App\Repository\RevendeurRepository;
use App\Service\MeilisearchService;
use PHPUnit\Framework\TestCase;

class MeilisearchSyncMessageHandlerTest extends TestCase
{
    private function createHandler(
        ?MeilisearchService $meilisearch = null,
        ?CustomerRepository $customerRepo = null,
        ?RevendeurRepository $revendeurRepo = null,
        ?PriceAutomaticRepository $priceRepo = null,
    ): MeilisearchSyncMessageHandler {
        return new MeilisearchSyncMessageHandler(
            $meilisearch ?? $this->createStub(MeilisearchService::class),
            $customerRepo ?? $this->createStub(CustomerRepository::class),
            $revendeurRepo ?? $this->createStub(RevendeurRepository::class),
            $priceRepo ?? $this->createStub(PriceAutomaticRepository::class),
        );
    }

    public function testRemoveCustomer(): void
    {
        $meilisearch = $this->createMock(MeilisearchService::class);
        $meilisearch->expects($this->once())->method('removeCustomer')->with(42);

        $handler = $this->createHandler(meilisearch: $meilisearch);
        $handler(new MeilisearchSyncMessage(MeilisearchSyncMessage::TYPE_CUSTOMER, 42, 'remove'));
    }

    public function testRemoveRevendeur(): void
    {
        $meilisearch = $this->createMock(MeilisearchService::class);
        $meilisearch->expects($this->once())->method('removeRevendeur')->with(10);

        $handler = $this->createHandler(meilisearch: $meilisearch);
        $handler(new MeilisearchSyncMessage(MeilisearchSyncMessage::TYPE_REVENDEUR, 10, 'remove'));
    }

    public function testRemovePrice(): void
    {
        $meilisearch = $this->createMock(MeilisearchService::class);
        $meilisearch->expects($this->once())->method('removePrice')->with(5);

        $handler = $this->createHandler(meilisearch: $meilisearch);
        $handler(new MeilisearchSyncMessage(MeilisearchSyncMessage::TYPE_PRICE, 5, 'remove'));
    }

    public function testRemoveUnknownType(): void
    {
        $meilisearch = $this->createStub(MeilisearchService::class);
        $handler = $this->createHandler(meilisearch: $meilisearch);
        $handler(new MeilisearchSyncMessage('unknown', 1, 'remove'));
        $this->assertTrue(true);
    }

    public function testIndexCustomer(): void
    {
        $user = new User();
        $user->setEmail('t@t.com');
        $user->setFirstName('T');
        $user->setLastName('T');
        $user->setPassword('h');
        $customer = new Customer($user);

        $customerRepo = $this->createStub(CustomerRepository::class);
        $customerRepo->method('find')->willReturn($customer);

        $meilisearch = $this->createMock(MeilisearchService::class);
        $meilisearch->expects($this->once())->method('indexCustomer')->with($customer);

        $handler = $this->createHandler(meilisearch: $meilisearch, customerRepo: $customerRepo);
        $handler(new MeilisearchSyncMessage(MeilisearchSyncMessage::TYPE_CUSTOMER, 1));
    }

    public function testIndexCustomerNotFound(): void
    {
        $customerRepo = $this->createStub(CustomerRepository::class);
        $customerRepo->method('find')->willReturn(null);

        $meilisearch = $this->createMock(MeilisearchService::class);
        $meilisearch->expects($this->never())->method('indexCustomer');

        $handler = $this->createHandler(meilisearch: $meilisearch, customerRepo: $customerRepo);
        $handler(new MeilisearchSyncMessage(MeilisearchSyncMessage::TYPE_CUSTOMER, 999));
    }

    public function testIndexRevendeur(): void
    {
        $user = new User();
        $user->setEmail('r@t.com');
        $user->setFirstName('R');
        $user->setLastName('T');
        $user->setPassword('h');
        $revendeur = new Revendeur($user, 'REV-001');

        $revendeurRepo = $this->createStub(RevendeurRepository::class);
        $revendeurRepo->method('find')->willReturn($revendeur);

        $meilisearch = $this->createMock(MeilisearchService::class);
        $meilisearch->expects($this->once())->method('indexRevendeur')->with($revendeur);

        $handler = $this->createHandler(meilisearch: $meilisearch, revendeurRepo: $revendeurRepo);
        $handler(new MeilisearchSyncMessage(MeilisearchSyncMessage::TYPE_REVENDEUR, 1));
    }

    public function testIndexRevendeurNotFound(): void
    {
        $revendeurRepo = $this->createStub(RevendeurRepository::class);
        $revendeurRepo->method('find')->willReturn(null);

        $meilisearch = $this->createMock(MeilisearchService::class);
        $meilisearch->expects($this->never())->method('indexRevendeur');

        $handler = $this->createHandler(meilisearch: $meilisearch, revendeurRepo: $revendeurRepo);
        $handler(new MeilisearchSyncMessage(MeilisearchSyncMessage::TYPE_REVENDEUR, 999));
    }

    public function testIndexPrice(): void
    {
        $price = new PriceAutomatic();
        $price->setType('esyweb');
        $price->setTitle('T');
        $price->setPriceHt('1.00');

        $priceRepo = $this->createStub(PriceAutomaticRepository::class);
        $priceRepo->method('find')->willReturn($price);

        $meilisearch = $this->createMock(MeilisearchService::class);
        $meilisearch->expects($this->once())->method('indexPrice')->with($price);

        $handler = $this->createHandler(meilisearch: $meilisearch, priceRepo: $priceRepo);
        $handler(new MeilisearchSyncMessage(MeilisearchSyncMessage::TYPE_PRICE, 1));
    }

    public function testIndexPriceNotFound(): void
    {
        $priceRepo = $this->createStub(PriceAutomaticRepository::class);
        $priceRepo->method('find')->willReturn(null);

        $meilisearch = $this->createMock(MeilisearchService::class);
        $meilisearch->expects($this->never())->method('indexPrice');

        $handler = $this->createHandler(meilisearch: $meilisearch, priceRepo: $priceRepo);
        $handler(new MeilisearchSyncMessage(MeilisearchSyncMessage::TYPE_PRICE, 999));
    }

    public function testIndexUnknownType(): void
    {
        $handler = $this->createHandler();
        $handler(new MeilisearchSyncMessage('unknown', 1));
        $this->assertTrue(true);
    }
}
