<?php

namespace App\Service;

use App\Entity\Chapter;
use App\Entity\Manga;
use App\Manager\FileSystemManager;
use App\Repository\ChapterRepository;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use Symfony\Component\String\Slugger\SluggerInterface;

readonly class MangaImportService
{
    public function __construct(
        private FileSystemManager      $fileSystemManager,
        private EntityManagerInterface $entityManager,
        private ChapterRepository      $chapterRepository,
        private SluggerInterface       $slugger
    ) {
    }

    /**
     * @throws Exception
     */
    public function importFile(Manga $manga, ?int $volume, ?Chapter $chapter, string $tempFilePath): void
    {
        if ($chapter !== null) {
            $this->importChapter($manga, $chapter, $tempFilePath);
        } elseif ($volume !== null) {
            $this->importVolume($manga, $volume, $tempFilePath);
        } else {
            throw new \RuntimeException("Impossible de déterminer s'il s'agit d'un volume ou d'un chapitre.");
        }
    }

    /**
     * @throws Exception
     */
    private function importVolume(Manga $manga, int $volume, string $tempFilePath): void
    {
        $permanentFileName = $this->createPermanentFileName($manga, $volume);
        $mangaDirectory = $this->fileSystemManager->createMangaDirectory($manga->getSlug(), $manga->getPublicationYear());
        $volumeDirectory = $this->fileSystemManager->createVolumeDirectory($mangaDirectory, $volume);
        $permanentFilePath = $volumeDirectory . '/' . $permanentFileName;

        if ($this->fileSystemManager->fileExists($permanentFilePath)) {
            throw new \RuntimeException("Un fichier pour ce volume existe déjà.");
        }

        $this->fileSystemManager->moveFile($tempFilePath, $permanentFilePath);

        $this->updateVolumeChapters($manga, $volume, $permanentFilePath);
        $this->entityManager->flush();
    }

    /**
     * @throws Exception
     */
    private function importChapter(Manga $manga, Chapter $chapter, string $tempFilePath): void
    {
        $volume = $chapter->getVolume();
        $permanentFileName = $this->createPermanentFileName($manga, $volume, $chapter->getNumber());
        $mangaDirectory = $this->fileSystemManager->createMangaDirectory($manga->getSlug(), $manga->getPublicationYear());
        $volumeDirectory = $this->fileSystemManager->createVolumeDirectory($mangaDirectory, $chapter->getVolume());
        $permanentFilePath = $volumeDirectory . '/' . $permanentFileName;

        if ($this->fileSystemManager->fileExists($permanentFilePath)) {
            throw new \RuntimeException("Un fichier pour ce chapitre existe déjà.");
        }

        $this->fileSystemManager->moveFile($tempFilePath, $permanentFilePath);

        $chapter->setCbzPath($permanentFilePath);

        $this->entityManager->flush();
    }

    private function createPermanentFileName(Manga $manga, int $volume, ?float $chapterNumber = null): string
    {
        $baseFileName = $this->slugger->slug($manga->getTitle()) . '_vol' . sprintf('%02d', $volume);
        if ($chapterNumber !== null) {
            $baseFileName .= '_ch' . $chapterNumber;
        }
        return $baseFileName . '.cbz';
    }

    private function updateVolumeChapters(Manga $manga, int $volume, string $cbzPath): void
    {
        $chapters = $this->chapterRepository->findBy([
            'manga' => $manga,
            'volume' => $volume
        ]);

        if (empty($chapters)) {
            throw new \RuntimeException("Aucun chapitre trouvé pour le volume $volume en base de données.");
        }

        foreach ($chapters as $chapter) {
            $chapter->setCbzPath($cbzPath);
        }
    }
}
