<?php

namespace App\Domain\Scraping\Infrastructure\Persistence;

use App\Domain\Scraping\Domain\Contract\Repository\SourceRepositoryInterface;
use App\Domain\Scraping\Domain\Exception\SourceNotFoundException;
use App\Domain\Scraping\Domain\Model\Source;
use App\Domain\Scraping\Domain\Model\ValueObject\SourceId;
use App\Entity\ContentSource;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;

readonly class LegacySourceRepository implements SourceRepositoryInterface
{
    public function __construct(
        private EntityManagerInterface $entityManager
    ) {
    }

    public function getById(string $id): ?Source
    {
        /** @var ContentSource|null $source */
        $source = $this->entityManager->getRepository(ContentSource::class)->find($id);

        if (!$source) {
            return null;
        }

        return $this->convertEntityToModel($source);
    }

    /**
     * @return Source[]
     */
    public function getAll(): array
    {
        /** @var ContentSource[] $sourceEntities */
        $sourceEntities = $this->entityManager->getRepository(ContentSource::class)->findAll();

        $sources = [];
        foreach ($sourceEntities as $sourceEntity) {
            $sources[] = $this->convertEntityToModel($sourceEntity);
        }

        return $sources;
    }

    public function validateSourcesExist(array $sourceIds): bool
    {
        if (empty($sourceIds)) {
            return true;
        }

        // Compter le nombre de sources qui existent réellement
        $existingCount = $this->entityManager->getRepository(ContentSource::class)
            ->createQueryBuilder('c')
            ->select('COUNT(c.id)')
            ->where('c.id IN (:ids)')
            ->setParameter('ids', $sourceIds)
            ->getQuery()
            ->getSingleScalarResult();

        // Vérifier que toutes les sources demandées existent
        return $existingCount === count($sourceIds);
    }

    /**
     * @return Source[]
     */
    public function getByIds(array $sourceIds): array
    {
        if (empty($sourceIds)) {
            return [];
        }

        /** @var ContentSource[] $sourceEntities */
        $sourceEntities = $this->entityManager->getRepository(ContentSource::class)->findBy(['id' => $sourceIds]);

        // Maintenir l'ordre des IDs fournis
        $sourcesMap = [];
        foreach ($sourceEntities as $sourceEntity) {
            $sourcesMap[$sourceEntity->getId()] = $this->convertEntityToModel($sourceEntity);
        }

        $orderedSources = [];
        foreach ($sourceIds as $sourceId) {
            if (isset($sourcesMap[$sourceId])) {
                $orderedSources[] = $sourcesMap[$sourceId];
            }
        }

        return $orderedSources;
    }

    /**
     * @return Source[]
     */
    public function getAllActive(): array
    {
        // Pour le moment, toutes les sources sont considérées comme actives
        // dans le système legacy
        return $this->getAll();
    }

    /**
     * Convertit une entité ContentSource en modèle Source
     */
    private function convertEntityToModel(ContentSource $source): Source
    {
        return new Source(
            id: new SourceId((string) $source->getId()),
            name: $source->getCleanBaseUrl(),
            description: 'Legacy Source: ' . $source->getBaseUrl(),
            baseUrl: $source->getBaseUrl(),
            scrappingParameters: [
                'imageSelector' => $source->getImageSelector(),
                'nextPageSelector' => $source->getNextPageSelector(),
                'chapterUrlFormat' => $source->getChapterUrlFormat(),
                'scrapingType' => $source->getScrapingType(),
                'chapterSelector' => $source->getChapterSelector()
            ],
            isActive: true,
            createdAt: new DateTimeImmutable(),
            updatedAt: new DateTimeImmutable()
        );
    }
}
