<?php

namespace App\Domain\Manga\Application\CommandHandler;

use App\Domain\Manga\Application\Command\ImportVolume;
use App\Domain\Manga\Domain\Contract\Repository\MangaRepositoryInterface;
use App\Domain\Manga\Domain\Exception\MangaNotFoundException;
use App\Domain\Shared\Domain\Contract\ImageStorageInterface;

readonly class ImportVolumeHandler
{
    public function __construct(
        private MangaRepositoryInterface $mangaRepository,
        private ImageStorageInterface $imageStorage
    ) {
    }

    public function handle(ImportVolume $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. Get all chapters for this volume
        $chapters = $this->mangaRepository->findChaptersByMangaIdAndVolume(
            $command->mangaId,
            $command->volumeNumber
        );

        if (empty($chapters)) {
            throw new \InvalidArgumentException(
                "No chapters found for manga {$command->mangaId} in volume {$command->volumeNumber}"
            );
        }

        // 4. Extract CBZ into individual images storage (shared directory for all volume chapters)
        $volumeDirectoryId = sprintf('volume_%s_%d', $command->mangaId, $command->volumeNumber);
        $pagesDirectory = $this->imageStorage->extractFromCbz($volumeDirectoryId, $command->fileBinary);
        $pageCount = $this->imageStorage->countCbzImages($command->fileBinary);

        // 5. Update all chapters with the volume path through the aggregate
        foreach ($chapters as $chapter) {
            $manga->updateChapterPages($chapter, $pagesDirectory, $pageCount);
        }
        $this->mangaRepository->save($manga);
    }

    private function isValidCbzFile(string $fileBinary): bool
    {
        $zipMagicNumber = "\x50\x4b\x03\x04"; // PK\x03\x04

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