<?php

namespace App\Domain\Manga\Application\CommandHandler;

use App\Domain\Manga\Application\Command\ImportChapter;
use App\Domain\Manga\Domain\Contract\Repository\ChapterRepositoryInterface;
use App\Domain\Manga\Domain\Contract\Repository\MangaRepositoryInterface;
use App\Domain\Manga\Domain\Exception\MangaNotFoundException;
use App\Domain\Manga\Domain\Exception\ChapterNotFoundException;
use App\Domain\Manga\Domain\Model\Chapter;
use App\Domain\Manga\Domain\Model\ValueObject\ChapterId;
use App\Domain\Shared\Domain\Contract\MangaPathManagerInterface;
use Ramsey\Uuid\Uuid;

readonly class ImportChapterHandler
{
    public function __construct(
        private MangaRepositoryInterface $mangaRepository,
        private ChapterRepositoryInterface $chapterRepository,
        private MangaPathManagerInterface $pathManager
    ) {}

    public function handle(ImportChapter $command): void
    {
        // 1. Validate that the manga exists
        $manga = $this->mangaRepository->findById($command->mangaId);
        if (!$manga) {
            throw new MangaNotFoundException($command->mangaId);
        }

        // 2. Validate that the file is a valid CBZ
        if (!$this->isValidCbzFile($command->fileBinary)) {
            throw new \InvalidArgumentException('The provided file is not a valid CBZ file');
        }

        // 3. Check if chapter exists
        $existingChapter = $this->chapterRepository->findByMangaIdAndChapterNumber(
            $command->mangaId,
            $command->chapterNumber
        );

        if (!$existingChapter) {
            throw new ChapterNotFoundException("Chapter {$command->chapterNumber} not found for manga {$command->mangaId}");
        }

        // 4. Save the CBZ file to storage using the path manager
        $cbzPath = $this->saveCbzFile($command, $manga, $existingChapter);

        // 5. Update existing chapter with new CBZ path
        $updatedChapter = new Chapter(
            id: new ChapterId($existingChapter->getId()),
            mangaId: $existingChapter->getMangaId(),
            number: $existingChapter->getNumber(),
            title: $existingChapter->getTitle(),
            volume: $existingChapter->getVolume(),
            isVisible: $existingChapter->isVisible(),
            cbzPath: $cbzPath,
            createdAt: $existingChapter->getCreatedAt()
        );
        $this->chapterRepository->save($updatedChapter);
    }

    /**
     * Validate that the binary data is a valid CBZ (ZIP) file
     */
    private function isValidCbzFile(string $fileBinary): bool
    {
        // CBZ files are ZIP archives, check for ZIP magic number
        $zipMagicNumber = "\x50\x4b\x03\x04"; // PK\x03\x04

        return strpos($fileBinary, $zipMagicNumber) === 0;
    }

    /**
     * Save the CBZ file to storage and return the path
     */
    private function saveCbzFile(ImportChapter $command, \App\Domain\Manga\Domain\Model\Manga $manga, Chapter $chapter): string
    {
        // Build the final CBZ path using the path manager (creates directories)
        $volumeNumber = $chapter->getVolume() ?? 0;
        $cbzPath = $this->pathManager->buildChapterCbzPath(
            $manga->getTitle()->getValue(),
            (string)$manga->getPublicationYear(),
            $volumeNumber,
            (string)$command->chapterNumber
        );

        // Write the binary content directly to the CBZ path
        if (!file_put_contents($cbzPath, $command->fileBinary)) {
            throw new \RuntimeException('Failed to save CBZ file');
        }

        return $cbzPath;
    }
}
