<?php
declare(strict_types=1);
namespace App\Services;

use App\Core\Database;

final class EnrollmentAiAssistant
{
    public static function suggestions(int $organisationId): array
    {
        $pdo=Database::connection();
        $rq=$pdo->prepare("SELECT r.id,r.discipline_id,r.disponibilites,r.created_at,CONCAT(m.prenom,' ',m.nom) membre_nom,d.libelle discipline_libelle FROM demandes_inscription r INNER JOIN membres_famille m ON m.id=r.membre_id INNER JOIN disciplines d ON d.id=r.discipline_id WHERE r.organisation_id=? AND r.deleted_at IS NULL AND r.statut IN('file_attente','a_etudier','creneau_propose') AND NOT EXISTS(SELECT 1 FROM cda_slot_assignment_proposals ap WHERE ap.demande_inscription_id=r.id AND ap.statut='en_attente') ORDER BY r.created_at,r.id");
        $rq->execute([$organisationId]);$requests=$rq->fetchAll()?:[];
        $sq=$pdo->prepare("SELECT ps.id,ps.discipline_id,ps.professeur_id,ps.jour_semaine,ps.heure_debut,ps.heure_fin,ps.capacite_max,CONCAT(p.prenom,' ',p.nom) professeur_nom,s.libelle salle_libelle,(SELECT COUNT(*) FROM cda_slot_enrollments e WHERE e.slot_id=ps.id AND e.statut='active' AND e.deleted_at IS NULL)+(SELECT COUNT(*) FROM cda_slot_assignment_proposals ap WHERE ap.slot_id=ps.id AND ap.statut='en_attente') occupation FROM cda_professor_slots ps INNER JOIN professeurs p ON p.id=ps.professeur_id LEFT JOIN salles s ON s.id=ps.salle_id WHERE ps.organisation_id=? AND ps.statut='valide' AND ps.deleted_at IS NULL ORDER BY ps.jour_semaine,ps.heure_debut");
        $sq->execute([$organisationId]);$slots=$sq->fetchAll()?:[];
        $out=[];
        foreach($requests as $r){
            $best=null;
            foreach($slots as $s){
                if((int)$s['discipline_id']!==(int)$r['discipline_id'] || (int)$s['occupation']>=(int)$s['capacite_max'])continue;
                $score=55;$reasons=['discipline compatible'];
                $availability=self::norm((string)($r['disponibilites']??''));
                $day=self::norm((string)$s['jour_semaine']);
                if($availability!=='' && str_contains($availability,$day)){$score+=25;$reasons[]='jour déclaré disponible';}
                elseif($availability===''){$score+=8;$reasons[]='aucune contrainte déclarée';}
                else{$score-=12;$reasons[]='jour non détecté dans les disponibilités';}
                $fill=(int)$s['capacite_max']>0?(int)$s['occupation']/(int)$s['capacite_max']:1;
                $score+=(int)round((1-$fill)*15);$reasons[]='équilibrage du remplissage';
                $ageDays=max(0,(int)floor((time()-strtotime((string)$r['created_at']))/86400));
                $score+=min(10,(int)floor($ageDays/7));
                if($ageDays>=7)$reasons[]='ancienneté de la demande';
                $candidate=['request_id'=>(int)$r['id'],'slot_id'=>(int)$s['id'],'professeur_id'=>(int)$s['professeur_id'],'membre_nom'=>$r['membre_nom'],'discipline_libelle'=>$r['discipline_libelle'],'jour_semaine'=>$s['jour_semaine'],'heure_debut'=>$s['heure_debut'],'heure_fin'=>$s['heure_fin'],'professeur_nom'=>$s['professeur_nom'],'salle_libelle'=>$s['salle_libelle']?:'Non renseignée','occupation'=>(int)$s['occupation'],'capacite'=>(int)$s['capacite_max'],'score'=>max(0,min(100,$score)),'reasons'=>$reasons];
                if($best===null||$candidate['score']>$best['score'])$best=$candidate;
            }
            $out[]=$best?:['request_id'=>(int)$r['id'],'membre_nom'=>$r['membre_nom'],'discipline_libelle'=>$r['discipline_libelle'],'score'=>0,'reasons'=>['aucun créneau compatible disponible']];
        }
        usort($out,static fn($a,$b)=>$b['score']<=>$a['score']);return $out;
    }
    private static function norm(string $v):string{$v=mb_strtolower($v,'UTF-8');$v=strtr($v,['é'=>'e','è'=>'e','ê'=>'e','ë'=>'e','à'=>'a','â'=>'a','ä'=>'a','î'=>'i','ï'=>'i','ô'=>'o','ö'=>'o','ù'=>'u','û'=>'u','ü'=>'u']);return $v;}
}
