<?php

namespace App\Tests\Feature\Manga;

use App\Domain\Manga\Application\Command\FetchMangaChapters;
use App\Domain\Manga\Domain\Model\Manga;
use App\Domain\Manga\Domain\Model\ValueObject\ExternalId;
use App\Domain\Manga\Domain\Model\ValueObject\MangaId;
use App\Domain\Manga\Domain\Model\ValueObject\MangaSlug;
use App\Domain\Manga\Domain\Model\ValueObject\MangaTitle;
use App\Tests\Feature\AbstractApiTestCase;
use App\Tests\Shared\Adapter\InMemoryMessageBus;
use Symfony\Component\Messenger\MessageBusInterface;
use Zenstruck\Foundry\Test\ResetDatabase;

class FetchMangaChaptersTest extends AbstractApiTestCase
{
    use ResetDatabase;

    private InMemoryMessageBus $messageBus;

    protected function setUp(): void
    {
        parent::setUp();

        $this->messageBus = new InMemoryMessageBus();
        $this->container->set(MessageBusInterface::class, $this->messageBus);
        $this->messageBus->clear();
    }

    public function testFetchChaptersForExistingManga(): void
    {
        $mangaId = 'manga-id';
        $externalId = 'manga-123';
        $manga = new Manga(
            new MangaId($mangaId),
            new MangaTitle('Test Manga'),
            new MangaSlug('test-manga'),
            'Description',
            'Author',
            2024,
            [],
            'ongoing',
            new ExternalId($externalId)
        );

        $this->entityManager->persist($this->toEntity($manga));
        $this->entityManager->flush();

        static::createClient()->request('POST', '/api/manga/chapters/fetch', [
            'json' => [
                'mangaId' => $mangaId
            ]
        ]);

        $this->assertResponseStatusCodeSame(202);

        $messages = $this->messageBus->getDispatchedMessages();
        $this->assertCount(1, $messages);
        $this->assertInstanceOf(FetchMangaChapters::class, $messages[0]);
        $this->assertEquals(new MangaId($mangaId), $messages[0]->mangaId);
    }

    public function testFetchChaptersWithInvalidMangaId(): void
    {
        $response = static::createClient()->request('POST', '/api/manga/chapters/fetch', [
            'json' => [
                'mangaId' => ''
            ]
        ]);

        $this->assertResponseStatusCodeSame(422);
        $this->assertJsonContains([
            'violations' => [
                [
                    'propertyPath' => 'mangaId',
                    'message' => 'L\'identifiant du manga est obligatoire'
                ]
            ]
        ]);
    }

    private function toEntity(Manga $manga): \App\Entity\Manga
    {
        $entity = new \App\Entity\Manga();
        $entity->setTitle($manga->getTitle()->getValue())
            ->setSlug($manga->getSlug()->getValue())
            ->setDescription($manga->getDescription())
            ->setAuthor($manga->getAuthor())
            ->setPublicationYear($manga->getPublicationYear())
            ->setGenres($manga->getGenres())
            ->setStatus($manga->getStatus())
            ->setExternalId($manga->getExternalId()->getValue())
            ->setMonitored(false);

        return $entity;
    }

    protected function tearDown(): void
    {
        parent::tearDown();
        $this->messageBus->clear();
    }
}
