<?php

declare(strict_types=1);

namespace App\Form\Finance;

use App\Entity\AnneeScolaire;
use App\Entity\Ecole;
use App\Entity\Etudiant;
use App\Entity\Paiement;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\GreaterThan;

final class PaiementType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        /** @var Ecole $ecole */
        $ecole = $options['ecole'];
        $lockedStudent = $options['locked_student'];
        $currentAnnee = $options['current_annee'];

        $yearFilter = fn (EntityRepository $er) => $er->createQueryBuilder('a')
            ->andWhere('a.ecole = :ecole')
            ->setParameter('ecole', $ecole)
            ->orderBy('a.dateDebut', 'DESC')
            ->addOrderBy('a.id', 'DESC');

        if (!$lockedStudent instanceof Etudiant) {
            $builder->add('etudiant', EntityType::class, [
                'class' => Etudiant::class,
                'choice_label' => fn (Etudiant $etudiant) => trim(sprintf('%s - %s', $etudiant->getMatricule() ?: 'Sans matricule', $etudiant->getNomComplet())),
                'label' => 'Étudiant',
                'placeholder' => 'Choisir un étudiant',
                'query_builder' => function (EntityRepository $er) use ($ecole, $currentAnnee) {
                    $qb = $er->createQueryBuilder('e')
                        ->select('DISTINCT e')
                        ->leftJoin('e.parcours', 'parcours')
                        ->andWhere('e.ecole = :ecole')
                        ->andWhere('e.actif = :active')
                        ->setParameter('ecole', $ecole)
                        ->setParameter('active', true)
                        ->orderBy('e.nom', 'ASC')
                        ->addOrderBy('e.prenom', 'ASC');

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

                    return $qb;
                },
                'attr' => [
                    'class' => 'js-student-search-select',
                    'data-search-placeholder' => 'Rechercher par nom ou matricule',
                ],
            ]);
        }

        $builder
            ->add('anneeScolaire', EntityType::class, [
                'class' => AnneeScolaire::class,
                'choice_label' => 'libelle',
                'label' => 'Année scolaire',
                'required' => false,
                'placeholder' => 'Toutes les échéances ouvertes',
                'query_builder' => $yearFilter,
                'attr' => ['data-payment-year-select' => '1'],
            ])
            ->add('datePaiement', DateType::class, [
                'label' => 'Date du paiement',
                'widget' => 'single_text',
            ])
            ->add('modePaiement', ChoiceType::class, [
                'label' => 'Mode de paiement',
                'required' => false,
                'placeholder' => 'Choisir',
                'choices' => [
                    'Espèces' => Paiement::MODE_ESPECES,
                    'Orange Money' => Paiement::MODE_ORANGE_MONEY,
                    'MTN MoMo' => Paiement::MODE_MTN_MOMO,
                    'Mobile Money' => Paiement::MODE_MOBILE_MONEY,
                    'Virement' => Paiement::MODE_VIREMENT,
                    'Autre' => Paiement::MODE_AUTRE,
                ],
            ])
            ->add('reference', TextType::class, [
                'label' => 'Référence',
                'required' => false,
            ])
            ->add('montantTotal', MoneyType::class, [
                'label' => 'Montant reçu (FCFA)',
                'currency' => false,
                'divisor' => 1,
                'constraints' => [new GreaterThan(['value' => 0, 'message' => 'Le montant doit être supérieur à 0.'])],
            ])
            ->add('observation', TextareaType::class, [
                'label' => 'Observation',
                'required' => false,
                'attr' => ['rows' => 3],
            ]);
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => Paiement::class,
            'ecole' => null,
            'locked_student' => null,
            'current_annee' => null,
        ]);
        $resolver->setRequired('ecole');
        $resolver->setAllowedTypes('ecole', [Ecole::class]);
        $resolver->setAllowedTypes('locked_student', ['null', Etudiant::class]);
        $resolver->setAllowedTypes('current_annee', ['null', AnneeScolaire::class]);
    }
}
