<?php
/**
 * SOUMISSION FINALE DE L'ÉVALUATION
 * Calcul de la note et sauvegarde définitive
 */

define('APP_ROOT', dirname(__DIR__));
require_once __DIR__ . '/config/config.php';
require_once __DIR__ . '/config/database.php';

// session_start(); // Géré par config/session.php
/**
 * Normalise une réponse mathématique (entier, fraction, décimal)
 * @param string $reponse La réponse brute de l'élève
 * @return float|false Valeur normalisée ou false si invalide
 */
function normaliser_reponse_mathematique($reponse) {
    if (empty($reponse)) return false;
    
    $reponse = trim($reponse);
    $reponse = str_replace(',', '.', $reponse); // Virgule française → point
    
    // Cas fraction (ex: "2/3", "-5/3")
    if (preg_match('/^([+-]?\d+)\s*\/\s*([+-]?\d+)$/', $reponse, $matches)) {
        $numerateur = (float)$matches[1];
        $denominateur = (float)$matches[2];
        
        if ($denominateur == 0) return false; // Division par zéro
        return $numerateur / $denominateur;
    }
    
    // Cas nombre décimal ou entier
    if (is_numeric($reponse)) {
        return (float)$reponse;
    }
    
    return false; // Format invalide
}

/**
 * Compare deux réponses mathématiques avec tolérance
 * @param float $attendue Réponse attendue (normalisée)
 * @param float $donnee Réponse de l'élève (normalisée)
 * @param float $epsilon Tolérance de comparaison
 * @return bool True si les réponses sont équivalentes
 */
function comparer_reponses_mathematiques($attendue, $donnee, $epsilon = 0.0001) {
    return abs($attendue - $donnee) < $epsilon;
}
// Vérification authentification
if (!isLoggedIn() || !isEleve()) {
    header('Location: login.php?error=access_denied');
    exit();
}

// $auth = new Auth(); // MIGRÉ vers SessionManager
$user = currentUser();
$db = Database::getInstance()->getConnection();

$id_evaluation = isset($_POST['id_evaluation']) ? (int)$_POST['id_evaluation'] : 
                 (isset($_GET['id_evaluation']) ? (int)$_GET['id_evaluation'] : 
                 (isset($_GET['id']) ? (int)$_GET['id'] : 0));
$id_tentative = isset($_POST['id_tentative']) ? (int)$_POST['id_tentative'] : 
                (isset($_GET['id_tentative']) ? (int)$_GET['id_tentative'] : 0);
$auto_submit = isset($_GET['auto']) && $_GET['auto'] == 1;

if ($id_tentative <= 0 || $id_evaluation <= 0) {
    die("Données invalides");
}

// Vérifier que la tentative appartient à l'élève
$stmt = $db->prepare("
    SELECT * FROM tentatives_eleves 
    WHERE id_tentative = ? 
    AND id_eleve = ? 
    AND statut = 'en_cours'
");
$stmt->execute([$id_tentative, $user['id_utilisateur']]);
$tentative = $stmt->fetch(PDO::FETCH_ASSOC);

if (!$tentative) {
    die("Tentative introuvable ou déjà terminée");
}

// Récupérer les réponses finales si soumission manuelle
if (!$auto_submit && $_SERVER['REQUEST_METHOD'] === 'POST') {
    $reponses = [];
    foreach ($_POST as $key => $value) {
        if (strpos($key, 'reponse_') === 0) {
            $id_question = str_replace('reponse_', '', $key);
            $reponses[$id_question] = $value;
        }
    }
    
    // Mettre à jour les réponses finales
    $reponses_json = json_encode($reponses, JSON_UNESCAPED_UNICODE);
    $stmt = $db->prepare("
        UPDATE tentatives_eleves 
        SET reponses_json = ? 
        WHERE id_tentative = ?
    ");
    $stmt->execute([$reponses_json, $id_tentative]);
    
    // Recharger la tentative avec les nouvelles réponses
    $stmt = $db->prepare("SELECT * FROM tentatives_eleves WHERE id_tentative = ?");
    $stmt->execute([$id_tentative]);
    $tentative = $stmt->fetch(PDO::FETCH_ASSOC);
}

// Récupérer toutes les questions de l'évaluation
$stmt = $db->prepare("
    SELECT * FROM questions 
    WHERE id_evaluation = ? 
    ORDER BY ordre ASC
");
$stmt->execute([$id_evaluation]);
$questions = $stmt->fetchAll(PDO::FETCH_ASSOC);

// Décoder les réponses de l'élève
$reponses_eleve = json_decode($tentative['reponses_json'], true) ?: [];

// CALCUL DE LA NOTE
$points_obtenus = 0;
$points_totaux = 0;

foreach ($questions as $question) {
    $id_question = $question['id_question'];
    $points_question = (float)$question['points'];
    $points_totaux += $points_question;
    
    // Récupérer la réponse de l'élève
    $reponse_eleve = $reponses_eleve[$id_question] ?? null;
    
    // Récupérer les options et la réponse correcte de la question
    $options = json_decode($question['options_json'], true);
    $reponse_correcte_data = json_decode($question['reponse_correcte_json'], true);
    
    // Vérifier la réponse selon le type
    switch ($question['type_question']) {
                
        case 'checkbox':
    // Trouver toutes les réponses correctes
    $reponses_correctes = [];
    if (isset($options['reponses'])) {
        foreach ($options['reponses'] as $rep) {
            if (isset($rep['est_correcte']) && $rep['est_correcte'] === true) {
                $reponses_correctes[] = $rep['texte'];
            }
        }
    }
    
    $reponses_eleve_array = is_array($reponse_eleve) ? $reponse_eleve : [];
    
    // Toutes correctes = points complets
    sort($reponses_correctes);
    sort($reponses_eleve_array);
    
    if ($reponses_correctes === $reponses_eleve_array) {
        $points_obtenus += $points_question;
    } else {
        // Points partiels selon le nombre de bonnes réponses
        $nb_correctes = count($reponses_correctes);
        if ($nb_correctes > 0) {
            $nb_bonnes = count(array_intersect($reponses_correctes, $reponses_eleve_array));
            $nb_mauvaises = count(array_diff($reponses_eleve_array, $reponses_correctes));
            
            $points_partiels = max(0, ($nb_bonnes - $nb_mauvaises) / $nb_correctes * $points_question);
            $points_obtenus += $points_partiels;
        }
    }
    break;
          case 'qcm':
    // Trouver la réponse correcte dans le tableau reponses
    $reponse_correcte = null;
    if (isset($options['reponses'])) {
        foreach ($options['reponses'] as $rep) {
            if (isset($rep['est_correcte']) && $rep['est_correcte'] === true) {
                $reponse_correcte = $rep['texte'];
                break;
            }
        }
    }
    if ($reponse_eleve === $reponse_correcte) {
        $points_obtenus += $points_question;
    }
    break;  
case 'number':
    // La réponse correcte est dans reponse_correcte_json: {"reponse": "18"}
    $reponse_correcte = $reponse_correcte_data['reponse'] ?? null;
    
    // Normaliser les deux réponses (gère entiers, fractions, décimaux)
    $valeur_eleve = normaliser_reponse_mathematique($reponse_eleve);
    $valeur_attendue = normaliser_reponse_mathematique($reponse_correcte);
    
    // Comparer avec tolérance
    if ($valeur_eleve !== false && $valeur_attendue !== false) {
        if (comparer_reponses_mathematiques($valeur_attendue, $valeur_eleve)) {
            $points_obtenus += $points_question;
        }
    }
    break;
            
        case 'text':
            // Pour les questions texte, nécessite correction manuelle
            // On compte 0 point automatiquement, à corriger manuellement
            break;
            
        case 'select':
    // La réponse correcte est dans reponse_correcte_json: {"id": "opt2"}
    // Les options sont dans options_json: {"options": [{"id": "opt1", "texte": "...", "est_correcte": false}, ...]}
    $id_reponse_correcte = $reponse_correcte_data['id'] ?? null;
    
    // L'élève peut avoir répondu avec l'ID ou le texte, on vérifie les deux
    $est_correct = false;
    if ($id_reponse_correcte && isset($options['options'])) {
        // Trouver le texte correspondant à l'ID correct
        $texte_correct = null;
        foreach ($options['options'] as $opt) {
            if (($opt['id'] ?? '') === $id_reponse_correcte) {
                $texte_correct = $opt['texte'] ?? null;
                break;
            }
        }
        
        // Vérifier si la réponse de l'élève correspond (ID ou texte)
        if ($reponse_eleve === $id_reponse_correcte || $reponse_eleve === $texte_correct) {
            $est_correct = true;
        }
    }
    
    if ($est_correct) {
        $points_obtenus += $points_question;
    }
    break;
            
        case 'text_trous':
            $trous = $options['trous'] ?? [];
            $reponses_eleve_trous = is_array($reponse_eleve) ? $reponse_eleve : [];
            $nb_trous = count($trous);
            $nb_corrects = 0;
            
            foreach ($trous as $trou) {
                $trou_id = $trou['id'];
                $reponse_correcte = $trou['reponse_correcte'];
                $reponse_eleve_trou = $reponses_eleve_trous[$trou_id] ?? '';
                
                if (trim(strtolower($reponse_eleve_trou)) === trim(strtolower($reponse_correcte))) {
                    $nb_corrects++;
                }
            }
            
            $points_obtenus += ($nb_corrects / $nb_trous) * $points_question;
            break;
    }
}

// Calculer le pourcentage
$pourcentage = $points_totaux > 0 ? ($points_obtenus / $points_totaux) * 100 : 0;

// Récupérer la note totale de l'évaluation
$stmt = $db->prepare("SELECT note_totale FROM evaluations WHERE id_evaluation = ?");
$stmt->execute([$id_evaluation]);
$eval = $stmt->fetch(PDO::FETCH_ASSOC);
$note_sur = $eval['note_totale'] ?? 20;

// Calculer la note finale
$note_finale = ($pourcentage / 100) * $note_sur;

// Calculer le temps passé
$date_debut = new DateTime($tentative['date_debut']);
$date_fin = new DateTime();
$temps_passe = $date_fin->getTimestamp() - $date_debut->getTimestamp();

// Mettre à jour la tentative
try {
    $stmt = $db->prepare("
        UPDATE tentatives_eleves 
        SET statut = 'terminee',
            note = ?,
            note_sur = ?,
            pourcentage = ?,
            temps_passe = ?,
            date_fin = NOW()
        WHERE id_tentative = ?
    ");
    
    $stmt->execute([
        round($note_finale, 2),
        $note_sur,
        round($pourcentage, 2),
        $temps_passe,
        $id_tentative
    ]);
    
    // Redirection vers la page de résultat
    header('Location: resultat_evaluation.php?id=' . $id_evaluation);
    exit();
    
} catch (Exception $e) {
    error_log("Erreur soumission évaluation: " . $e->getMessage());
    die("Erreur lors de la soumission de l'évaluation");
}
?>
