<?php

namespace App\Repository;

use App\Entity\Concession;
use App\Service\StockImporter;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

/**
 * @extends ServiceEntityRepository<Concession>
 */
class ConcessionRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Concession::class);
    }

    /**
     * Map externalId => nom, triée par nom.
     *
     * @return array<string, string>
     */
    public function allByExternalId(): array
    {
        /** @var list<array{externalId: string, name: string}> $rows */
        $rows = $this->createQueryBuilder('c')
            ->select('c.externalId', 'c.name')
            ->orderBy('c.name', 'ASC')
            ->getQuery()
            ->getArrayResult();

        $map = [];
        foreach ($rows as $r) {
            $map[(string) $r['externalId']] = (string) $r['name'];
        }

        return $map;
    }

    /**
     * Map nom normalisé (casse/accents ignorés) => externalId, pour migrer
     * les anciennes données stockées par nom vers les IDs.
     *
     * @return array<string, string>
     */
    public function normalizedNameToId(): array
    {
        $map = [];
        foreach ($this->allByExternalId() as $id => $name) {
            $map[StockImporter::normalize($name)] = $id;
        }

        return $map;
    }

    public function count(array $criteria = []): int
    {
        return parent::count($criteria);
    }

    /**
     * Remplace l'intégralité du référentiel (dédupliqué par ID externe).
     *
     * @param list<array{id: string, name: string}> $pairs
     *
     * @return int Nombre de concessions enregistrées
     */
    public function replaceAll(array $pairs): int
    {
        $em = $this->getEntityManager();

        // Transaction : si un persist/flush échoue, le vidage de la table est annulé
        // (sinon le référentiel des concessions serait perdu).
        return $em->wrapInTransaction(function () use ($em, $pairs): int {
            $this->createQueryBuilder('c')->delete()->getQuery()->execute();

            $seen = [];
            $count = 0;
            foreach ($pairs as $pair) {
                $id = trim($pair['id']);
                $name = trim($pair['name']);
                if ('' === $id || '' === $name || isset($seen[$id])) {
                    continue;
                }
                $seen[$id] = true;
                $em->persist(new Concession($id, $name));
                ++$count;
            }

            $em->flush();

            return $count;
        });
    }
}
