<?php

namespace App\Controller;

use App\Repository\MangaRepository;
use App\Service\CbzService;
use App\Service\NotificationService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

class ReaderController extends AbstractController
{
    public function __construct(
        private readonly MangaRepository     $mangaRepository,
        private readonly CbzService          $cbzService,
        private readonly NotificationService $notificationService,
    ) {
    }

    #[Route('/read/{mangaSlug}/{chapterNumber}', name: 'app_reader')]
    public function read(string $mangaSlug, float $chapterNumber): Response
    {
        $manga = $this->mangaRepository->findOneBy(['slug' => $mangaSlug]);
        if (!$manga) {
            throw $this->createNotFoundException("Le manga demandé n'existe pas.");
        }

        $chapter = $manga->getChapterByNumber($chapterNumber);
        if (!$chapter) {
            throw $this->createNotFoundException("Le chapitre demandé n'existe pas.");
        }

        if (is_null($chapter->getCbzPath())) {
            $this->notificationService->sendUpdate([
                'status' => 'error',
                'message' => 'Le chapitre demandé n\'est pas encore disponible.',
            ]);
            return $this->redirectToRoute('app_manga_show', ['mangaSlug' => $mangaSlug]);
        }

        $totalPages = $this->cbzService->getPageCount($chapter->getCbzPath());

        return $this->render('reader/index.html.twig', [
            'manga' => $manga,
            'chapter' => $chapter,
            'totalPages' => $totalPages,
        ]);
    }

    #[Route('/api/read/{mangaSlug}/{chapterNumber}/{pageNumber}', name: 'app_reader_page')]
    public function getPage(string $mangaSlug, float $chapterNumber, int $pageNumber): Response
    {
        $manga = $this->mangaRepository->findOneBy(['slug' => $mangaSlug]);
        if (!$manga) {
            throw $this->createNotFoundException("Le manga demandé n'existe pas.");
        }

        $chapter = $manga->getChapterByNumber($chapterNumber);
        if (!$chapter) {
            throw $this->createNotFoundException("Le chapitre demandé n'existe pas.");
        }

        $pageContent = $this->cbzService->getPageContent($chapter->getCbzPath(), $pageNumber);
        if (!$pageContent) {
            throw $this->createNotFoundException("La page demandée n'existe pas.");
        }

        return new Response(base64_encode($pageContent), 200, ['Content-Type' => 'text/plain']);
    }

    #[Route('/api/chapters/{mangaSlug}', name: 'app_reader_chapters')]
    public function getChapters(string $mangaSlug): JsonResponse
    {
        $manga = $this->mangaRepository->findOneBy(['slug' => $mangaSlug]);
        if (!$manga) {
            throw $this->createNotFoundException("Le manga demandé n'existe pas.");
        }

        $chapters = $manga->getChapters()
            ->filter(fn ($chapter) => $chapter->isVisible() && !is_null($chapter->getCbzPath()))
            ->toArray();

        usort($chapters, fn ($a, $b) => $b->getNumber() <=> $a->getNumber());

        $chapters = array_values(array_map(fn ($chapter) => [
            'number' => $chapter->getNumber(),
            'title' => $chapter->getTitle(),
        ], $chapters));

        return $this->json($chapters);
    }

    #[Route('/api/previous-chapter/{mangaSlug}/{currentChapterNumber}', name: 'app_reader_previous_chapter')]
    public function getPreviousChapter(string $mangaSlug, float $currentChapterNumber): JsonResponse
    {
        $manga = $this->mangaRepository->findOneBy(['slug' => $mangaSlug]);
        if (!$manga) {
            throw $this->createNotFoundException("Le manga demandé n'existe pas.");
        }

        $chapters = $manga->getChapters()
            ->filter(fn ($chapter) => $chapter->isVisible() && $chapter->getNumber() < $currentChapterNumber)
            ->toArray();

        usort($chapters, fn ($a, $b) => $b->getNumber() <=> $a->getNumber());

        $previousChapter = reset($chapters) ?: null;

        return $this->json($previousChapter ? [
            'number' => $previousChapter->getNumber(),
            'title' => $previousChapter->getTitle(),
        ] : null);
    }

    #[Route('/api/next-chapter/{mangaSlug}/{currentChapterNumber}', name: 'app_reader_next_chapter')]
    public function getNextChapter(string $mangaSlug, float $currentChapterNumber): JsonResponse
    {
        $manga = $this->mangaRepository->findOneBy(['slug' => $mangaSlug]);
        if (!$manga) {
            throw $this->createNotFoundException("Le manga demandé n'existe pas.");
        }

        $nextChapter = $manga->getChapters()
            ->filter(fn ($chapter) => $chapter->isVisible() && $chapter->getNumber() > $currentChapterNumber)
            ->toArray();

        usort($nextChapter, fn ($a, $b) => $a->getNumber() <=> $b->getNumber());

        $nextChapter = reset($nextChapter) ?: null;

        return $this->json($nextChapter ? [
            'number' => $nextChapter->getNumber(),
            'title' => $nextChapter->getTitle(),
        ] : null);
    }
}
