<?php

namespace App\Domain\Scraping\Infrastructure\EventSubscriber;

use App\Domain\Scraping\Domain\Event\ChapterScraped;
use App\Domain\Scraping\Domain\Event\ChapterScrapingFailed;
use App\Domain\Scraping\Domain\Contract\Repository\ChapterRepositoryInterface;
use App\Domain\Shared\Domain\Contract\JobRepositoryInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Mercure\HubInterface;
use Symfony\Component\Mercure\Update;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;

class ScrapingEventSubscriber implements EventSubscriberInterface
{
    public function __construct(
        private readonly HubInterface $hub,
        private readonly ChapterRepositoryInterface $chapterRepository,
        private readonly JobRepositoryInterface $jobRepository,
        private readonly LoggerInterface $logger
    ) {
    }

    public static function getSubscribedEvents(): array
    {
        return [
            // Les événements sont capturés via le système de message handlers
        ];
    }

    #[AsMessageHandler]
    public function onChapterScraped(ChapterScraped $event): void
    {
        $jobId = $event->getJobId();
        $this->logger->info('ChapterScraped reçu pour le job: ' . $jobId);

        $job = $this->jobRepository->get($jobId);

        if (!$job) {
            $this->logger->warning('Job non trouvé pour l\'ID: ' . $jobId);
            return;
        }

        // Récupérer le chapitre associé au job
        $chapterId = $job->context['chapterId'] ?? null;
        $this->logger->info('ChapterId extrait du job: ' . $chapterId);

        $chapter = $this->chapterRepository->getById($chapterId);

        if (!$chapter) {
            $this->logger->warning('Chapitre non trouvé pour l\'ID: ' . $chapterId);
            return;
        }

        $this->logger->info('Chapitre trouvé - ID: ' . $chapter->id . ', MangaId: ' . $chapter->mangaId . ', Number: ' . $chapter->chapterNumber);

        // Préparer les données à envoyer au front
        $data = [
            'type' => 'chapter.scraped',
            'chapterId' => $chapter->id,
            'mangaId' => $chapter->mangaId,
            'chapterNumber' => $chapter->chapterNumber,
            'isAvailable' => true,
            'timestamp' => (new \DateTimeImmutable())->format('c')
        ];

        $this->logger->info('Données préparées pour Mercure: ' . json_encode($data));

        // Publier une mise à jour sur le hub Mercure
        $topics = [
            'manga/chapter/' . $chapter->id,             // Topic spécifique au chapitre
            'manga/' . $chapter->mangaId . '/chapters',  // Topic pour tous les chapitres d'un manga
            'scraping/status'                            // Topic général pour les événements de scraping
        ];

        $this->logger->info('Topics Mercure: ' . implode(', ', $topics));

        $update = new Update($topics, json_encode($data));
        $this->hub->publish($update);

        $this->logger->info('Mise à jour publiée sur Mercure');
    }

    #[AsMessageHandler]
    public function onChapterScrapingFailed(ChapterScrapingFailed $event): void
    {
        $this->logger->info('ChapterScrapingFailed reçu pour mangaId: ' . $event->getMangaId() . ', chapter: ' . $event->getChapterNumber());

        // Préparer les données à envoyer au front
        $data = [
            'type' => 'chapter.scraping.failed',
            'mangaId' => $event->getMangaId(),
            'chapterNumber' => $event->getChapterNumber(),
            'reason' => $event->getReason(),
            'timestamp' => (new \DateTimeImmutable())->format('c')
        ];

        $this->logger->info('Données préparées pour Mercure: ' . json_encode($data));

        // Publier une mise à jour sur le hub Mercure
        $topics = [
            'manga/' . $event->getMangaId() . '/chapters', // Topic pour tous les chapitres d'un manga
            'scraping/status'                             // Topic général pour les événements de scraping
        ];

        $this->logger->info('Topics Mercure: ' . implode(', ', $topics));

        $update = new Update($topics, json_encode($data));
        $this->hub->publish($update);

        $this->logger->info('Mise à jour publiée sur Mercure');
    }
}
