<?php

namespace App\Domain\Manga\Application\QueryHandler;

use App\Domain\Manga\Application\Query\DownloadVolume;
use App\Domain\Manga\Application\Response\DownloadResponse;
use App\Domain\Manga\Domain\Contract\Repository\MangaRepositoryInterface;
use App\Domain\Manga\Domain\Contract\Service\FileServiceInterface;
use App\Domain\Manga\Domain\Exception\MangaNotFoundException;
use App\Domain\Manga\Domain\Exception\VolumeNotFoundException;
use App\Domain\Shared\Domain\Contract\QueryHandlerInterface;
use App\Domain\Shared\Domain\Contract\QueryInterface;
use App\Domain\Shared\Domain\Contract\ResponseInterface;

readonly class DownloadVolumeHandler implements QueryHandlerInterface
{
    public function __construct(
        private MangaRepositoryInterface $mangaRepository,
        private FileServiceInterface $fileService
    ) {
    }

    public function handle(QueryInterface $query): ResponseInterface
    {
        assert($query instanceof DownloadVolume);

        $manga = $this->mangaRepository->findById($query->mangaId);

        if (!$manga) {
            throw new MangaNotFoundException($query->mangaId);
        }

        $chapters = $this->mangaRepository->findVisibleChaptersWithPagesByMangaIdAndVolume(
            $query->mangaId,
            $query->volume
        );

        if (empty($chapters)) {
            throw new VolumeNotFoundException($query->mangaId, $query->volume);
        }

        $cbzPaths = [];
        foreach ($chapters as $chapter) {
            $cbzPaths[] = $chapter->getPagesDirectory();
        }

        $volumeName = sprintf(
            '%s_vol%d',
            $manga->getSlug()->getValue(),
            $query->volume
        );

        $httpResponse = $this->fileService->createVolumeCbz($cbzPaths, $volumeName);

        return new DownloadResponse($httpResponse);
    }
}
