<?php
declare(strict_types=1);

namespace App\Controllers;

use App\Core\Auth;
use App\Core\Controller;
use App\Core\Database;
use App\Core\Permission;
use PDO;
use Throwable;

final class DashboardController extends Controller
{
    public function index(): void
    {
        Auth::requireLogin();
        $activeSpace = Permission::activeSpace();
        if ($activeSpace !== '') {
            $this->redirect('/espaces?espace=' . rawurlencode($activeSpace));
            return;
        }
        Permission::require('dashboard.view');

        $pdo = Database::connection();

        $stats = [
            'clients' => $this->countSafe($pdo, "SELECT COUNT(*) FROM clients WHERE deleted_at IS NULL"),
            'familles' => $this->countSafe($pdo, "SELECT COUNT(*) FROM familles WHERE deleted_at IS NULL"),
            'participants' => $this->countSafe($pdo, "SELECT COUNT(*) FROM membres_famille WHERE deleted_at IS NULL AND participant_ateliers = 1"),
            'professeurs' => $this->countSafe($pdo, "SELECT COUNT(*) FROM professeurs WHERE deleted_at IS NULL"),
            'ateliers' => $this->countSafe($pdo, "SELECT COUNT(*) FROM ateliers WHERE deleted_at IS NULL"),
            'inscriptions' => $this->countSafe($pdo, "SELECT COUNT(*) FROM inscriptions WHERE deleted_at IS NULL"),
            'groupes' => $this->countSafe($pdo, "SELECT COUNT(*) FROM groupes_cours WHERE deleted_at IS NULL"),
        ];

        $capacity = $this->fetchCapacity($pdo);
        $capacityTotals = $this->capacityTotals($capacity);
        $directionTasks = Permission::canAny('demandes_inscription.validate','professeurs.disciplines.manage')
            ? $this->fetchDirectionTasks($pdo)
            : [];

        $this->view('dashboard/index', [
            'pageTitle' => 'Centre de pilotage CDA',
            'user' => Auth::user(),
            'stats' => $stats,
            'agenda' => $this->fetchAgenda($pdo),
            'recentClients' => $this->fetchRecentClients($pdo),
            'capacity' => $capacity,
            'capacityTotals' => $capacityTotals,
            'alerts' => $this->buildAlerts($stats, $capacityTotals),
            'directionTasks' => $directionTasks,
        ]);
    }

    private function fetchDirectionTasks(PDO $pdo): array
    {
        $tasks=[];
        try {
            $rows=$pdo->query(
                "SELECT p.id,p.public_token,p.nom,p.prenom,COUNT(s.id) total
                 FROM cda_professor_slots s
                 INNER JOIN professeurs p ON p.id=s.professeur_id
                 WHERE s.deleted_at IS NULL AND s.statut='brouillon' AND p.deleted_at IS NULL
                 GROUP BY p.id,p.public_token,p.nom,p.prenom ORDER BY p.nom,p.prenom"
            )->fetchAll(PDO::FETCH_ASSOC);
            foreach($rows as $row)$tasks[]=[
                'kind'=>'planning','title'=>'Planning professeur à valider',
                'text'=>$row['prenom'].' '.$row['nom'].' · '.(int)$row['total'].' créneau(x)',
                'url'=>'/public/professeurs-pro/planning?professeur='.rawurlencode((string)$row['public_token']).'&mode=direction'
            ];
        } catch (Throwable) {}
        try {
            $rows=$pdo->query(
                "SELECT rw.professeur_id,p.nom,p.prenom,COUNT(*) total
                 FROM cda_professor_remote_work rw
                 INNER JOIN professeurs p ON p.id=rw.professeur_id
                 WHERE rw.statut='envoye' AND p.deleted_at IS NULL
                 GROUP BY rw.professeur_id,p.nom,p.prenom ORDER BY MIN(rw.date_teletravail)"
            )->fetchAll(PDO::FETCH_ASSOC);
            foreach($rows as $row)$tasks[]=[
                'kind'=>'teletravail','title'=>'Télétravail à valider',
                'text'=>$row['prenom'].' '.$row['nom'].' · '.(int)$row['total'].' compte(s) rendu(s)',
                'url'=>'/public/professeurs-pro/teletravail?id='.(int)$row['professeur_id'].'&mode=direction'
            ];
        } catch (Throwable) {}
        try {
            $rows=$pdo->query(
                "SELECT r.professeur_id,p.public_token,p.nom,p.prenom,COUNT(*) total
                 FROM cda_professor_planning_move_requests r
                 INNER JOIN professeurs p ON p.id=r.professeur_id
                 WHERE r.statut='en_attente' AND p.deleted_at IS NULL
                 GROUP BY r.professeur_id,p.public_token,p.nom,p.prenom ORDER BY MIN(r.created_at)"
            )->fetchAll(PDO::FETCH_ASSOC);
            foreach($rows as $row)$tasks[]=[
                'kind'=>'deplacement','title'=>'Déplacement à décider',
                'text'=>$row['prenom'].' '.$row['nom'].' · '.(int)$row['total'].' demande(s)',
                'url'=>'/public/professeurs-pro/planning?professeur='.rawurlencode((string)$row['public_token']).'&mode=direction'
            ];
        } catch (Throwable) {}
        return $tasks;
    }

    private function countSafe(PDO $pdo, string $sql): int
    {
        try {
            return (int)$pdo->query($sql)->fetchColumn();
        } catch (Throwable) {
            return 0;
        }
    }

    private function fetchAgenda(PDO $pdo): array
    {
        try {
            return $pdo->query(
                "SELECT a.id, a.libelle, a.jour_semaine, a.heure_debut, a.heure_fin,
                        COALESCE(s.libelle, 'Salle non renseignée') AS salle
                 FROM ateliers a
                 LEFT JOIN salles s ON s.id = a.salle_id
                 WHERE a.deleted_at IS NULL
                   AND a.statut IN ('ouvert','complet','brouillon')
                 ORDER BY FIELD(a.jour_semaine,'lundi','mardi','mercredi','jeudi','vendredi','samedi','dimanche'), a.heure_debut
                 LIMIT 8"
            )->fetchAll(PDO::FETCH_ASSOC);
        } catch (Throwable) {
            return [];
        }
    }

    private function fetchRecentClients(PDO $pdo): array
    {
        try {
            return $pdo->query(
                "SELECT id, nom, prenom, email, created_at
                 FROM clients
                 WHERE deleted_at IS NULL
                 ORDER BY created_at DESC, id DESC
                 LIMIT 5"
            )->fetchAll(PDO::FETCH_ASSOC);
        } catch (Throwable) {
            return [];
        }
    }

    private function fetchCapacity(PDO $pdo): array
    {
        try {
            return $pdo->query(
                "SELECT a.id, a.libelle, COALESCE(a.capacite, 0) AS capacite, COUNT(i.id) AS inscrits
                 FROM ateliers a
                 LEFT JOIN inscriptions i ON i.atelier_id = a.id AND i.deleted_at IS NULL
                 WHERE a.deleted_at IS NULL
                 GROUP BY a.id, a.libelle, a.capacite
                 ORDER BY CASE WHEN COALESCE(a.capacite,0)=0 THEN 999 ELSE COUNT(i.id)/a.capacite END DESC, a.libelle
                 LIMIT 12"
            )->fetchAll(PDO::FETCH_ASSOC);
        } catch (Throwable) {
            return [];
        }
    }

    private function capacityTotals(array $rows): array
    {
        $capacity = 0;
        $registered = 0;
        $full = 0;

        foreach ($rows as $row) {
            $cap = max(0, (int)($row['capacite'] ?? 0));
            $ins = max(0, (int)($row['inscrits'] ?? 0));
            $capacity += $cap;
            $registered += $ins;
            if ($cap > 0 && $ins >= $cap) {
                $full++;
            }
        }

        return [
            'capacity' => $capacity,
            'registered' => $registered,
            'free' => max(0, $capacity - $registered),
            'full' => $full,
            'rate' => $capacity > 0 ? min(100, (int)round(($registered / $capacity) * 100)) : 0,
        ];
    }

    private function buildAlerts(array $stats, array $capacity): array
    {
        $alerts = [];
        if (($stats['ateliers'] ?? 0) === 0) {
            $alerts[] = ['level' => 'warning', 'title' => 'Aucun atelier actif', 'text' => 'Créez le premier atelier pédagogique.'];
        }
        if (($capacity['full'] ?? 0) > 0) {
            $alerts[] = ['level' => 'info', 'title' => ($capacity['full'] ?? 0) . ' atelier(s) complet(s)', 'text' => 'Contrôlez les listes d’attente et les capacités.'];
        }
        if (($stats['professeurs'] ?? 0) === 0) {
            $alerts[] = ['level' => 'warning', 'title' => 'Aucun professeur actif', 'text' => 'Ajoutez ou réactivez un intervenant.'];
        }
        if (!$alerts) {
            $alerts[] = ['level' => 'success', 'title' => 'Situation maîtrisée', 'text' => 'Aucune alerte structurelle détectée.'];
        }
        return $alerts;
    }
}
