<?php

namespace App\Tests\Domain\Manga\Application\QueryHandler;

use App\Domain\Manga\Application\Query\GetMangaChapters;
use App\Domain\Manga\Application\QueryHandler\GetMangaChaptersHandler;
use App\Domain\Manga\Domain\Exception\MangaNotFoundException;
use App\Domain\Manga\Domain\Model\Manga;
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\Domain\Manga\Adapter\InMemoryMangaRepository;
use PHPUnit\Framework\TestCase;

class GetMangaChaptersHandlerTest extends TestCase
{
    private InMemoryMangaRepository $repository;
    private GetMangaChaptersHandler $handler;

    protected function setUp(): void
    {
        $this->repository = new InMemoryMangaRepository();
        $this->handler = new GetMangaChaptersHandler($this->repository);
    }

    public function testHandleThrowsExceptionWhenMangaNotFound(): void
    {
        $this->expectException(MangaNotFoundException::class);
        
        $query = new GetMangaChapters('non-existent-id');
        $this->handler->handle($query);
    }

    public function testHandleReturnsEmptyListWhenNoChapters(): void
    {
        // Arrange
        $this->givenMangaExists('123');
        
        // Act
        $query = new GetMangaChapters('123');
        $response = $this->handler->handle($query);
        
        // Assert
        $this->assertEmpty($response->chapters);
        $this->assertEquals(0, $response->total);
        $this->assertEquals(1, $response->page);
        $this->assertEquals(20, $response->limit);
        $this->assertFalse($response->hasNextPage());
        $this->assertFalse($response->hasPreviousPage());
    }

    public function testHandleReturnsPaginatedChapters(): void
    {
        // Arrange
        $this->givenMangaExistsWithChapters('123', 25);
        
        // Act
        $query = new GetMangaChapters('123', page: 2, limit: 10);
        $response = $this->handler->handle($query);
    
        // Assert
        $this->assertCount(10, $response->chapters);
        $this->assertEquals(25, $response->total);
        $this->assertEquals(2, $response->page);
        $this->assertEquals(10, $response->limit);
        $this->assertTrue($response->hasNextPage());
        $this->assertTrue($response->hasPreviousPage());
    }

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

    private function givenMangaExists(string $id): void
    {
        $manga = $this->createManga($id);
        $this->repository->save($manga);
    }

    private function givenMangaExistsWithChapters(string $id, int $chapterCount): void
    {
        $this->givenMangaExists($id);
        // Note: We'll need to implement this in InMemoryMangaRepository
        $this->repository->addChaptersToManga($id, $chapterCount);
    }

    private function createManga(string $id): Manga
    {
        return new Manga(
            id: new MangaId($id),
            title: new MangaTitle('Test Manga'),
            slug: new MangaSlug('test-manga'),
            description: 'This is a test manga',
            author: 'Test Author',
            publicationYear: 2024,
            genres: ['Action', 'Adventure'],
            status: 'Ongoing',
            externalId: null,
            imageUrl: null,
            rating: null
        );
    }
} 