<?php

namespace App\Domain\Scraping\Application\QueryHandler;

use App\Domain\Scraping\Application\Query\GetMangaPreferredSources;
use App\Domain\Scraping\Application\Response\GetMangaPreferredSourcesResponse;
use App\Domain\Scraping\Domain\Contract\Repository\MangaRepositoryInterface;
use App\Domain\Scraping\Domain\Contract\Repository\SourceRepositoryInterface;

readonly class GetMangaPreferredSourcesHandler
{
    public function __construct(
        private MangaRepositoryInterface $mangaRepository,
        private SourceRepositoryInterface $sourceRepository
    ) {
    }

    public function handle(GetMangaPreferredSources $query): GetMangaPreferredSourcesResponse
    {
        // 1. Vérifier que le manga existe
        $manga = $this->mangaRepository->getById($query->mangaId);
        if (!$manga) {
            throw new \InvalidArgumentException("Manga not found with ID: {$query->mangaId}");
        }

        // 2. Récupérer toutes les sources actives
        $allActiveSources = $this->sourceRepository->getAllActive();

        // 3. Si le manga a des sources préférées, les organiser par ordre de préférence
        if ($manga->hasPreferredSources()) {
            $preferredSourceIds = $manga->getPreferredSources();

            // Créer un index des sources par ID pour optimiser les performances
            $sourcesByIds = [];
            foreach ($allActiveSources as $source) {
                $sourcesByIds[$source->getId()->getValue()] = $source;
            }

            // Séparer les sources préférées et les autres
            $preferredSources = [];
            $otherSources = [];

            // D'abord, ajouter les sources préférées dans l'ordre de préférence exactement
            foreach ($preferredSourceIds as $preferredId) {
                if (isset($sourcesByIds[$preferredId])) {
                    $preferredSources[] = $sourcesByIds[$preferredId];
                }
            }

            // Ensuite, ajouter les autres sources actives qui ne sont pas dans les préférées
            foreach ($allActiveSources as $source) {
                if (!in_array($source->getId()->getValue(), $preferredSourceIds, true)) {
                    $otherSources[] = $source;
                }
            }

            // Combiner les sources : préférées en premier, puis les autres
            $orderedSources = array_merge($preferredSources, $otherSources);

            return new GetMangaPreferredSourcesResponse(
                $query->mangaId,
                $orderedSources,
                true
            );
        }

        // 4. Si pas de sources préférées, retourner toutes les sources active
        return new GetMangaPreferredSourcesResponse(
            $query->mangaId,
            $allActiveSources,
            false
        );
    }
}
