<?php

declare(strict_types=1);

namespace App\Repository;

use App\Entity\Ecole;
use App\Entity\Inscription;
use App\Entity\AnneeScolaire;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

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

    /** @param array{statut?: ?string, section?: ?int, type?: ?string, q?: ?string} $filters @return list<Inscription> */
    public function findForEcole(
        Ecole $ecole,
        array $filters = [],
        ?AnneeScolaire $annee = null,
        string $scope = 'current',
        ?AnneeScolaire $currentAnnee = null,
    ): array {
        $qb = $this->createQueryBuilder('inscription')
            ->leftJoin('inscription.anneeScolaire', 'annee')->addSelect('annee')
            ->leftJoin('inscription.sectionSouhaitee', 'sectionSouhaitee')->addSelect('sectionSouhaitee')
            ->leftJoin('inscription.niveauSouhaite', 'niveauSouhaite')->addSelect('niveauSouhaite')
            ->leftJoin('inscription.classeSouhaitee', 'classeSouhaitee')->addSelect('classeSouhaitee')
            ->leftJoin('inscription.classeFinale', 'classeFinale')->addSelect('classeFinale')
            ->andWhere('inscription.ecole = :ecole')
            ->setParameter('ecole', $ecole)
            ->orderBy('inscription.dateSoumission', 'DESC');

        if (!empty($filters['statut'])) {
            $qb->andWhere('inscription.statut = :statut')->setParameter('statut', $filters['statut']);
        }

        if (!empty($filters['section'])) {
            $qb->andWhere('sectionSouhaitee.id = :section')->setParameter('section', $filters['section']);
        }

        if (!empty($filters['type'])) {
            $qb->andWhere('inscription.typeCandidat = :type')->setParameter('type', $filters['type']);
        }

        if (!empty($filters['q'])) {
            $search = '%'.mb_strtolower(trim((string) $filters['q'])).'%';
            $qb
                ->andWhere('LOWER(inscription.nom) LIKE :q OR LOWER(inscription.prenom) LIKE :q OR inscription.telephonePrincipal LIKE :q OR inscription.telephoneWhatsapp LIKE :q OR inscription.numeroDossier LIKE :q')
                ->setParameter('q', $search);
        }

        if ($scope === 'archives') {
            if ($annee) {
                $qb->andWhere('inscription.anneeScolaire = :annee')->setParameter('annee', $annee);
            } elseif ($currentAnnee) {
                $qb
                    ->andWhere('inscription.anneeScolaire IS NULL OR inscription.anneeScolaire != :currentAnnee OR inscription.statut = :annulee')
                    ->setParameter('currentAnnee', $currentAnnee)
                    ->setParameter('annulee', Inscription::STATUT_ANNULEE);
            } else {
                $qb->andWhere('inscription.statut = :annulee')->setParameter('annulee', Inscription::STATUT_ANNULEE);
            }
        } elseif ($scope === 'all') {
            if ($annee) {
                $qb->andWhere('inscription.anneeScolaire = :annee')->setParameter('annee', $annee);
            }
        } else {
            if ($annee) {
                $qb->andWhere('inscription.anneeScolaire = :annee')->setParameter('annee', $annee);
            }
            $qb->andWhere('inscription.statut != :annulee')->setParameter('annulee', Inscription::STATUT_ANNULEE);
        }

        return $qb->getQuery()->getResult();
    }

    public function countForEcole(Ecole $ecole, ?string $statut = null, ?AnneeScolaire $annee = null): int
    {
        $qb = $this->createQueryBuilder('inscription')
            ->select('COUNT(inscription.id)')
            ->andWhere('inscription.ecole = :ecole')
            ->setParameter('ecole', $ecole);

        if ($statut) {
            $qb->andWhere('inscription.statut = :statut')->setParameter('statut', $statut);
        }

        if ($annee) {
            $qb->andWhere('inscription.anneeScolaire = :annee')->setParameter('annee', $annee);
        }

        return (int) $qb->getQuery()->getSingleScalarResult();
    }

    public function countDossiersForYear(Ecole $ecole, string $year): int
    {
        return (int) $this->createQueryBuilder('inscription')
            ->select('COUNT(inscription.id)')
            ->andWhere('inscription.ecole = :ecole')
            ->andWhere('inscription.numeroDossier LIKE :prefix')
            ->setParameter('ecole', $ecole)
            ->setParameter('prefix', 'DOS-'.$year.'-%')
            ->getQuery()
            ->getSingleScalarResult();
    }

    public function countTemporaryForYear(Ecole $ecole, string $year): int
    {
        return (int) $this->createQueryBuilder('inscription')
            ->select('COUNT(inscription.id)')
            ->andWhere('inscription.ecole = :ecole')
            ->andWhere('inscription.matriculeTemporaire LIKE :prefix')
            ->setParameter('ecole', $ecole)
            ->setParameter('prefix', 'TMP-'.$year.'-%')
            ->getQuery()
            ->getSingleScalarResult();
    }

    /** @return list<Inscription> */
    public function findLatestForEcole(Ecole $ecole, int $limit = 5, ?AnneeScolaire $annee = null): array
    {
        $qb = $this->createQueryBuilder('inscription')
            ->leftJoin('inscription.sectionSouhaitee', 'section')->addSelect('section')
            ->andWhere('inscription.ecole = :ecole')
            ->andWhere('inscription.statut != :annulee')
            ->setParameter('ecole', $ecole)
            ->setParameter('annulee', Inscription::STATUT_ANNULEE)
            ->orderBy('inscription.dateSoumission', 'DESC')
            ->setMaxResults($limit);

        if ($annee) {
            $qb->andWhere('inscription.anneeScolaire = :annee')->setParameter('annee', $annee);
        }

        return $qb->getQuery()->getResult();
    }
}
