<?php

namespace App\Repository;

use App\Entity\InseeRef;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

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

    public function fetchInseeData(array $params): array
    {
        // Récupération des paramètres
        $label = $params['label'] ?? null;
        $birthDate = !empty($params['BirthDate']) ? new \DateTime($params['BirthDate']) : null;

        // Si pas de label ou vide → on retourne immédiatement
        if (!$label || strlen($label) < 1) {
            return [
                'data' => [],
                'total' => 0
            ];
        }

        $results = [];

        // -----------------------------------------------
        // Recherche FULLTEXT si le label contient >= 3 caractères
        // -----------------------------------------------
        if (strlen($label) >= 3) {
            $qb = $this->createQueryBuilder('i');

            // Filtre sur la date de municipalité si fourni
            if ($birthDate) {
                $qb->andWhere('i.municipalityStartDate <= :birthDate')
                    ->andWhere('(i.municipalityEndDate IS NULL OR i.municipalityEndDate >= :birthDate)')
                    ->setParameter('birthDate', $birthDate);
            }

            // FULLTEXT sur la colonne inseeCodeName
            $qb->andWhere("MATCH(i.inseeCodeName) AGAINST (:label IN BOOLEAN MODE)")
                ->setParameter('label', $label . '*');

            try {
                $results = $qb->getQuery()->getArrayResult(); // récupérer les résultats
            } catch (\Exception $e) {
                // Si FULLTEXT non supporté ou erreur → fallback sur LIKE
            }
        }

        // -----------------------------------------------
        // Fallback LIKE si FULLTEXT vide ou erreur
        // -----------------------------------------------
        if (empty($results)) {
            $qb = $this->createQueryBuilder('i');

            // Filtre sur la date si fourni
            if ($birthDate) {
                $qb->andWhere('i.municipalityStartDate <= :birthDate')
                    ->andWhere('(i.municipalityEndDate IS NULL OR i.municipalityEndDate > :birthDate)')
                    ->setParameter('birthDate', $birthDate);
            }

            // LIKE classique pour les labels plus courts ou si FULLTEXT échoue
            $qb->andWhere('i.inseeCodeName LIKE :label')
                ->setParameter('label', '%' . $label . '%');

            $results = $qb->getQuery()->getArrayResult();
        }

        // -----------------------------------------------
        // Application de l'algorithme client pour réduire à 10 résultats max
        // -----------------------------------------------
        $filtered = $this->fetchingData($results, $label);

        // Retour final pour le frontend
        return [
            'data' => $filtered,           // tableau des résultats filtrés
            'total' => count($filtered)    // nombre total après filtrage
        ];
    }

    /**
     * Algorithme client exact : réduit la liste à 10 résultats
     *
     * @param array $results Résultats bruts SQL
     * @param string $input Texte saisi par l'utilisateur
     * @return array Liste filtrée max 10 éléments
     */
    private function fetchingData(array $results, string $input): array
    {
        $n = strlen($input);

        // Si peu de résultats, retourner directement
        if (count($results) <= 10) {
            return $results;
        }

        // Construire L = liste associant chaque résultat à sa longueur
        $L = [];
        foreach ($results as $r) {
            $L[] = [
                'item' => $r,                   // ligne SQL originale
                'len' => mb_strlen($r['inseeCodeName']) // longueur du nom
            ];
        }

        // m = valeur maximale de (longueur - n)
        $m = max(array_map(fn($x) => $x['len'] - $n, $L));

        $R = $L; // liste initiale

        // Tant que plus de 10 résultats, on réduit progressivement
        while (count($R) > 10 && $m >= -100) { // sécurité pour éviter boucle infinie
            $R2 = [];

            foreach ($R as $i) {
                if (($i['len'] - $n) < $m) {
                    $R2[] = $i; // on garde les résultats proches en longueur
                }
            }

            if (empty($R2)) break; // éviter liste vide

            $R = $R2;
            $m--; // décrémenter pour réduire progressivement
        }

        // Ne garder que les lignes SQL originales et limiter à 8 résultats
        return array_slice(array_map(fn($x) => $x['item'], $R), 0, 8);
    }


    // public function fetchInseeData(array $params): array
    // {
    //     $qb = $this->createQueryBuilder('i');

    //     // Filtre date : BirthDate entre start et end
    //     if (!empty($params['BirthDate'])) {
    //         try {
    //             $birthDate = new \DateTime($params['BirthDate']);

    //             $qb->andWhere('i.municipalityStartDate <= :birthDate')
    //                 ->andWhere('(i.municipalityEndDate IS NULL OR i.municipalityEndDate > :birthDate)')
    //                 ->setParameter('birthDate', $birthDate);
    //         } catch (\Exception $e) {
    //             // Si la date n'est pas valide, on ignore le filtre
    //         }
    //     }

    //     if (!empty($params['label'])) {
    //         $qb->andWhere('i.inseeCodeName LIKE :label')
    //             ->setParameter('label', '%' . $params['label'] . '%');
    //     }

    //     // Comptage total
    //     $totalQb = clone $qb;
    //     $total = (int) $totalQb->select('COUNT(i.id)')->getQuery()->getSingleScalarResult();

    //     // Pagination
    //     $page = $params['page'] ?? 1;
    //     $itemsPerPage = $params['itemsPerPage'] ?? 10;
    //     $offset = ($page - 1) * $itemsPerPage;

    //     $qb->setFirstResult($offset)
    //         ->setMaxResults($itemsPerPage);

    //      $data = $qb->getQuery()->getArrayResult();

    //     return [
    //         'data' => $data,
    //         'total' => $total
    //     ];
    // }



    //    /**
    //     * @return Insee[] Returns an array of Insee objects
    //     */
    //    public function findByExampleField($value): array
    //    {
    //        return $this->createQueryBuilder('i')
    //            ->andWhere('i.exampleField = :val')
    //            ->setParameter('val', $value)
    //            ->orderBy('i.id', 'ASC')
    //            ->setMaxResults(10)
    //            ->getQuery()
    //            ->getResult()
    //        ;
    //    }

    //    public function findOneBySomeField($value): ?Insee
    //    {
    //        return $this->createQueryBuilder('i')
    //            ->andWhere('i.exampleField = :val')
    //            ->setParameter('val', $value)
    //            ->getQuery()
    //            ->getOneOrNullResult()
    //        ;
    //    }
}
