<?php

declare(strict_types=1);

namespace App\Repository;

use App\Entity\AnneeScolaire;
use App\Entity\EcheancePaiement;
use App\Entity\Ecole;
use App\Entity\Etudiant;
use App\Entity\ParcoursEtudiant;
use App\Entity\TypeFrais;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

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

    /** @return list<EcheancePaiement> */
    public function findByEcoleAndYear(Ecole $ecole, ?AnneeScolaire $anneeScolaire): array
    {
        $qb = $this->createQueryBuilder('e')
            ->andWhere('e.ecole = :ecole')
            ->setParameter('ecole', $ecole)
            ->orderBy('e.dateEcheance', 'ASC')
            ->addOrderBy('e.id', 'ASC');

        $anneeScolaire
            ? $qb->andWhere('e.anneeScolaire = :annee')->setParameter('annee', $anneeScolaire)
            : $qb->andWhere('e.anneeScolaire IS NULL');

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

    /** @return list<EcheancePaiement> */
    public function findActiveByStudent(Etudiant $etudiant, ?AnneeScolaire $anneeScolaire = null): array
    {
        $qb = $this->createQueryBuilder('e')
            ->andWhere('e.etudiant = :etudiant')
            ->andWhere('e.actif = :actif')
            ->setParameter('etudiant', $etudiant)
            ->setParameter('actif', true)
            ->orderBy('e.dateEcheance', 'ASC')
            ->addOrderBy('e.id', 'ASC');

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

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

    /** @return list<EcheancePaiement> */
    public function findActiveByParcours(ParcoursEtudiant $parcours): array
    {
        return $this->createQueryBuilder('e')
            ->andWhere('e.parcoursEtudiant = :parcours')
            ->andWhere('e.actif = :actif')
            ->setParameter('parcours', $parcours)
            ->setParameter('actif', true)
            ->orderBy('e.dateEcheance', 'ASC')
            ->addOrderBy('e.id', 'ASC')
            ->getQuery()
            ->getResult();
    }

    public function findExisting(
        Ecole $ecole,
        Etudiant $etudiant,
        ?ParcoursEtudiant $parcours,
        TypeFrais $typeFrais,
        ?string $periode,
    ): ?EcheancePaiement {
        $qb = $this->createQueryBuilder('e')
            ->andWhere('e.ecole = :ecole')
            ->andWhere('e.etudiant = :etudiant')
            ->andWhere('e.typeFrais = :typeFrais')
            ->setParameter('ecole', $ecole)
            ->setParameter('etudiant', $etudiant)
            ->setParameter('typeFrais', $typeFrais)
            ->setMaxResults(1);

        $parcours instanceof ParcoursEtudiant
            ? $qb->andWhere('e.parcoursEtudiant = :parcours')->setParameter('parcours', $parcours)
            : $qb->andWhere('e.parcoursEtudiant IS NULL');

        $periode !== null
            ? $qb->andWhere('e.periode = :periode')->setParameter('periode', $periode)
            : $qb->andWhere('e.periode IS NULL');

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