<?php
namespace App\Services;

use App\Core\Database;

final class EnrollmentEligibility
{
    /**
     * Vérifie toutes les règles bloquantes avant une inscription.
     *
     * @return array{
     *   eligible: bool,
     *   messages: array<int,string>,
     *   requires_override: bool
     * }
     */
    public static function check(
        int $memberId,
        int $workshopId,
        int $schoolYearId
    ): array {
        $pdo=Database::connection();

        $stmt=$pdo->prepare(
            "SELECT
                m.id,
                m.date_naissance,
                m.niveau_scolaire_id,
                m.niveau_scolaire_annee_id,
                ns.rang_scolaire,
                a.pole_id,
                a.discipline_id,
                a.public_cible_id,
                a.organisation_id
             FROM membres_famille m
             CROSS JOIN ateliers a
             LEFT JOIN niveaux_scolaires ns
                    ON ns.id=m.niveau_scolaire_id
             WHERE m.id=:member_id
               AND a.id=:workshop_id
               AND m.deleted_at IS NULL
               AND a.deleted_at IS NULL
             LIMIT 1"
        );
        $stmt->execute([
            'member_id'=>$memberId,
            'workshop_id'=>$workshopId,
        ]);

        $context=$stmt->fetch();

        if(!$context){
            return [
                'eligible'=>false,
                'messages'=>['Le membre ou le cours est introuvable.'],
                'requires_override'=>false,
            ];
        }

        $stmt=$pdo->prepare(
            "SELECT r.*,ns.rang_scolaire AS rang_minimum
             FROM regles_eligibilite r
             LEFT JOIN niveaux_scolaires ns
                    ON ns.id=r.niveau_scolaire_min_id
             WHERE r.organisation_id=:organisation_id
               AND r.actif=1
               AND r.bloquante=1
               AND (r.pole_id IS NULL OR r.pole_id=:pole_id)
               AND (
                    r.discipline_id IS NULL
                    OR r.discipline_id=:discipline_id
               )
               AND (
                    r.public_cible_id IS NULL
                    OR :workshop_public_is_null=1
                    OR r.public_cible_id=:public_cible_id
               )
             ORDER BY
                (r.discipline_id IS NOT NULL) DESC,
                r.id"
        );
        $stmt->execute([
            'organisation_id'=>$context['organisation_id'],
            'pole_id'=>$context['pole_id'],
            'discipline_id'=>$context['discipline_id'],
            'public_cible_id'=>$context['public_cible_id'],
            'workshop_public_is_null'=>empty($context['public_cible_id'])?1:0,
        ]);

        $messages=[];

        foreach($stmt->fetchAll() as $rule){
            if(
                $rule['type_regle']==='niveau_scolaire_minimum'
            ){
                // Une règle de niveau scolaire vise les mineurs. Elle ne doit pas
                // bloquer une inscription adulte lorsque le cours support n'a pas
                // encore de public cible explicite.
                if(!empty($context['date_naissance'])){
                    $birth=new \DateTimeImmutable((string)$context['date_naissance']);
                    $reference=self::schoolYearReferenceDate($pdo,$schoolYearId);
                    if($birth->diff($reference)->y>=18)continue;
                }
                if(
                    empty($context['niveau_scolaire_id'])
                    || (int)$context['niveau_scolaire_annee_id']
                        !== $schoolYearId
                ){
                    $messages[]=
                        'Le niveau scolaire de l’enfant doit être renseigné '
                        .'pour l’année scolaire en cours.';
                    continue;
                }

                if(
                    (int)$context['rang_scolaire']
                    < (int)$rule['rang_minimum']
                ){
                    $messages[]=(string)$rule['message_blocage'];
                }
            }
        }

        return [
            'eligible'=>$messages===[],
            'messages'=>$messages,
            'requires_override'=>$messages!==[],
        ];
    }
    private static function schoolYearReferenceDate(\PDO $pdo,int $schoolYearId): \DateTimeImmutable
    {
        $stmt=$pdo->prepare("SELECT date_debut FROM annees_scolaires WHERE id=? LIMIT 1");
        $stmt->execute([$schoolYearId]);
        $date=(string)($stmt->fetchColumn() ?: date('Y-m-d'));
        return new \DateTimeImmutable($date);
    }

}
