<?php
// api_corp/CORP_EVALUACIONES/evaluaciones_saber_pro.php

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Content-Type, Authorization");
header("Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS");
header("Content-Type: application/json; charset=utf-8");

if ($_SERVER["REQUEST_METHOD"] === "OPTIONS") { http_response_code(200); exit; }

ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);
error_reporting(E_ALL);

require_once(__DIR__ . "/../config.php");
require_once(__DIR__ . "/../auth_guard.php");

$authUser   = requireAuth($JWT_KEY);
$activeUser = requireActiveUser($mysqli, $authUser);

// ===================== HELPERS =====================
function jsonBody(): array {
    $raw  = file_get_contents("php://input");
    $data = json_decode($raw, true);
    return is_array($data) ? $data : [];
}
function ok($data = [], string $message = "OK"): void {
    echo json_encode(["success" => true, "message" => $message] + $data); exit;
}
function fail(string $message, int $code = 400): void {
    http_response_code($code);
    echo json_encode(["success" => false, "message" => $message]); exit;
}
function clean($v): string { return trim((string)$v); }
function toInt($v, int $default = 0): int {
    if ($v === null || $v === "") return $default;
    return (int)$v;
}
function bindParams(mysqli_stmt $stmt, string $types, array $values): bool {
    $refs = [$types];
    foreach ($values as $k => $v) $refs[] = &$values[$k];
    return call_user_func_array([$stmt, 'bind_param'], $refs);
}

// ── Resuelve o crea una competencia por nombre ──
function resolveCompetencia(mysqli $mysqli, ?int $idComp, ?string $nombre): ?int {
    if ($idComp > 0) return $idComp;
    $nombre = clean($nombre ?? "");
    if ($nombre === "") return null;

    $st = $mysqli->prepare(
        "SELECT ID_COMPETENCIA FROM CATALOGO_COMPETENCIAS
         WHERE NOMBRE_COMPETENCIA = ? AND ESTADO = 1 LIMIT 1"
    );
    if (!$st) throw new Exception("Error buscando competencia: " . $mysqli->error);
    $st->bind_param("s", $nombre);
    $st->execute();
    $row = $st->get_result()->fetch_assoc();
    if ($row) return (int)$row["ID_COMPETENCIA"];

    // No existe → crear
    $st2 = $mysqli->prepare(
        "INSERT INTO CATALOGO_COMPETENCIAS (NOMBRE_COMPETENCIA) VALUES (?)"
    );
    if (!$st2) throw new Exception("Error creando competencia: " . $mysqli->error);
    $st2->bind_param("s", $nombre);
    if (!$st2->execute()) throw new Exception("Error al insertar competencia: " . $st2->error);
    return (int)$mysqli->insert_id;
}

// ── Resuelve o crea una habilidad por nombre dentro de una competencia ──
function resolveHabilidad(mysqli $mysqli, ?int $idHab, ?string $nombre, ?int $idComp): ?int {
    if ($idHab > 0) return $idHab;
    $nombre = clean($nombre ?? "");
    if ($nombre === "" || !$idComp) return null;

    $st = $mysqli->prepare(
        "SELECT ID_HABILIDAD FROM CATALOGO_HABILIDADES
         WHERE NOMBRE_HABILIDAD = ? AND ID_COMPETENCIA = ? AND ESTADO = 1 LIMIT 1"
    );
    if (!$st) throw new Exception("Error buscando habilidad: " . $mysqli->error);
    $st->bind_param("si", $nombre, $idComp);
    $st->execute();
    $row = $st->get_result()->fetch_assoc();
    if ($row) return (int)$row["ID_HABILIDAD"];

    // No existe → crear
    $st2 = $mysqli->prepare(
        "INSERT INTO CATALOGO_HABILIDADES (ID_COMPETENCIA, NOMBRE_HABILIDAD) VALUES (?, ?)"
    );
    if (!$st2) throw new Exception("Error creando habilidad: " . $mysqli->error);
    $st2->bind_param("is", $idComp, $nombre);
    if (!$st2->execute()) throw new Exception("Error al insertar habilidad: " . $st2->error);
    return (int)$mysqli->insert_id;
}

// ── Inserta preguntas y opciones; retorna puntaje total ──
function insertPreguntasSaberPro(mysqli $mysqli, int $idEvaluacion, array $preguntas): float {
    $puntajeTotal = 0.0;

    $stPreg = $mysqli->prepare("
        INSERT INTO EVALUACION_PREGUNTAS
            (ID_EVALUACION, ORDEN_PREGUNTA, ENUNCIADO, TIPO_PREGUNTA,
             PUNTAJE_PREGUNTA, ID_COMPETENCIA, ID_HABILIDAD, RESPUESTA_ESPERADA, IMAGEN_URL)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
    ");
    if (!$stPreg) throw new Exception("Error preparando INSERT preguntas: " . $mysqli->error);

    $stOpc = $mysqli->prepare("
        INSERT INTO EVALUACION_PREGUNTA_OPCIONES (ID_PREGUNTA, ORDEN_OPCION, TEXTO_OPCION, ES_CORRECTA)
        VALUES (?, ?, ?, ?)
    ");
    if (!$stOpc) throw new Exception("Error preparando INSERT opciones: " . $mysqli->error);

    $tiposValidos = ["ABIERTA", "SELECCION_UNICA", "MULTIPLE", "CON_IMAGEN"];

    foreach ($preguntas as $orden => $preg) {
        $enunciado    = clean($preg["ENUNCIADO"]          ?? "");
        $tipo         = clean($preg["TIPO_PREGUNTA"]      ?? "");
        $puntaje      = (float)($preg["PUNTAJE_PREGUNTA"] ?? 0);
        $respEsperada = clean($preg["RESPUESTA_ESPERADA"] ?? "") ?: null;
        $imagenUrl    = clean($preg["IMAGEN_URL"]         ?? "") ?: null;
        $opciones     = $preg["opciones"] ?? [];
        $ordenNum     = $orden + 1;

        // ── Resolver competencia y habilidad por nombre o ID ──
        $nombreComp = clean($preg["NOMBRE_COMPETENCIA"] ?? "");
        $nombreHab  = clean($preg["NOMBRE_HABILIDAD"]   ?? "");
        $idCompRaw  = toInt($preg["ID_COMPETENCIA"]     ?? 0);
        $idHabRaw   = toInt($preg["ID_HABILIDAD"]       ?? 0);

        $idComp = resolveCompetencia($mysqli, $idCompRaw, $nombreComp ?: null);
        $idHab  = resolveHabilidad($mysqli,   $idHabRaw,  $nombreHab  ?: null, $idComp);

        if ($enunciado === "") throw new Exception("La pregunta #$ordenNum no tiene enunciado.");
        if (!in_array($tipo, $tiposValidos))
            throw new Exception("Tipo inválido en pregunta #$ordenNum: '$tipo'.");

        $esAbierta = $tipo === "ABIERTA" || ($tipo === "CON_IMAGEN" && count($opciones) === 0);
        if (!$esAbierta && count($opciones) < 2)
            throw new Exception("La pregunta #$ordenNum necesita al menos 2 opciones.");

        bindParams($stPreg, "iissdiiss", [
            $idEvaluacion, $ordenNum, $enunciado, $tipo,
            $puntaje, $idComp, $idHab, $respEsperada, $imagenUrl,
        ]);
        if (!$stPreg->execute())
            throw new Exception("Error al guardar pregunta #$ordenNum: " . $stPreg->error);

        $idPregunta    = $mysqli->insert_id;
        $puntajeTotal += $puntaje;

        foreach ($opciones as $oi => $opc) {
            $textoOpc   = clean($opc["TEXTO_OPCION"] ?? "");
            $esCorrecta = (int)(bool)($opc["ES_CORRECTA"] ?? 0);
            $ordenOpc   = $oi + 1;
            if ($textoOpc === "")
                throw new Exception("Opción vacía en pregunta #$ordenNum, opción #" . ($oi + 1) . ".");
            $stOpc->bind_param("iisi", $idPregunta, $ordenOpc, $textoOpc, $esCorrecta);
            if (!$stOpc->execute())
                throw new Exception("Error al guardar opción en pregunta #$ordenNum: " . $stOpc->error);
        }
    }

    return $puntajeTotal;
}

$method = $_SERVER["REQUEST_METHOD"];

// ===================== GET =====================
if ($method === "GET") {

    // GET por ID → detalle completo con preguntas y opciones
    if (isset($_GET["ID_EVALUACION"])) {
        $idEval = (int)$_GET["ID_EVALUACION"];

        $stmt = $mysqli->prepare("
            SELECT E.ID_EVALUACION, E.ID_DOCENTE,
                CONCAT(D.NOMBRE_DOCENTE, ' ', D.APELLIDO_DOCENTE) AS NOMBRE_DOCENTE,
                E.ID_ASIGNACION, E.TITULO_EVALUACION, E.DESCRIPCION_EVALUACION,
                E.TIPO_COMPETENCIA,
                E.ID_COMPETENCIA_GLOBAL,
                CC.NOMBRE_COMPETENCIA AS NOMBRE_COMPETENCIA_GLOBAL,
                E.ID_HABILIDAD_GLOBAL,
                CH.NOMBRE_HABILIDAD AS NOMBRE_HABILIDAD_GLOBAL,
                E.ESTADO_EVALUACION, E.FECHA_INICIO, E.FECHA_FIN,
                E.DURACION_MINUTOS, E.INTENTOS_PERMITIDOS, E.PUNTAJE_TOTAL, E.FECHA_CREACION
            FROM EVALUACIONES E
            INNER JOIN DOCENTES D ON D.ID_DOCENTE = E.ID_DOCENTE
            LEFT JOIN CATALOGO_COMPETENCIAS CC ON CC.ID_COMPETENCIA = E.ID_COMPETENCIA_GLOBAL
            LEFT JOIN CATALOGO_HABILIDADES  CH ON CH.ID_HABILIDAD   = E.ID_HABILIDAD_GLOBAL
            WHERE E.ID_EVALUACION = ? AND E.TIPO_COMPETENCIA = 'SABER_PRO' LIMIT 1
        ");
        if (!$stmt) fail("Error preparando consulta: " . $mysqli->error);
        $stmt->bind_param("i", $idEval);
        $stmt->execute();
        $eval = $stmt->get_result()->fetch_assoc();
        if (!$eval) fail("La evaluación Saber Pro no existe.", 404);

        // Preguntas
        $stmt2 = $mysqli->prepare("
            SELECT P.ID_PREGUNTA, P.ORDEN_PREGUNTA, P.ENUNCIADO, P.TIPO_PREGUNTA,
                P.PUNTAJE_PREGUNTA,
                P.ID_COMPETENCIA,  CC.NOMBRE_COMPETENCIA,
                P.ID_HABILIDAD,    CH.NOMBRE_HABILIDAD,
                P.RESPUESTA_ESPERADA, P.IMAGEN_URL
            FROM EVALUACION_PREGUNTAS P
            LEFT JOIN CATALOGO_COMPETENCIAS CC ON CC.ID_COMPETENCIA = P.ID_COMPETENCIA
            LEFT JOIN CATALOGO_HABILIDADES  CH ON CH.ID_HABILIDAD   = P.ID_HABILIDAD
            WHERE P.ID_EVALUACION = ? ORDER BY P.ORDEN_PREGUNTA ASC
        ");
        if (!$stmt2) fail("Error preparando preguntas: " . $mysqli->error);
        $stmt2->bind_param("i", $idEval);
        $stmt2->execute();
        $resPreg   = $stmt2->get_result();
        $preguntas = [];

        while ($p = $resPreg->fetch_assoc()) {
            $stmt3 = $mysqli->prepare("
                SELECT ID_OPCION, ORDEN_OPCION, TEXTO_OPCION, ES_CORRECTA
                FROM EVALUACION_PREGUNTA_OPCIONES
                WHERE ID_PREGUNTA = ? ORDER BY ORDEN_OPCION ASC
            ");
            if (!$stmt3) fail("Error preparando opciones: " . $mysqli->error);
            $stmt3->bind_param("i", $p["ID_PREGUNTA"]);
            $stmt3->execute();
            $opciones = [];
            while ($o = $stmt3->get_result()->fetch_assoc()) $opciones[] = $o;
            $p["opciones"] = $opciones;
            $preguntas[]   = $p;
        }

        $eval["preguntas"] = $preguntas;
        ok(["data" => $eval], "Evaluación Saber Pro encontrada");
    }

    // GET listado — filtrar por docente opcionalmente
    $idDocente = isset($_GET["ID_DOCENTE"]) ? (int)$_GET["ID_DOCENTE"] : 0;
    $sql = "
        SELECT E.ID_EVALUACION, E.TITULO_EVALUACION, E.ESTADO_EVALUACION, E.TIPO_COMPETENCIA,
            E.FECHA_INICIO, E.FECHA_FIN, E.DURACION_MINUTOS, E.INTENTOS_PERMITIDOS,
            E.PUNTAJE_TOTAL, E.FECHA_CREACION, E.ID_DOCENTE,
            CONCAT(D.NOMBRE_DOCENTE, ' ', D.APELLIDO_DOCENTE) AS NOMBRE_DOCENTE,
            D.CORREO_DOCENTE,
            COUNT(P.ID_PREGUNTA) AS TOTAL_PREGUNTAS,
            CC.NOMBRE_COMPETENCIA AS NOMBRE_COMPETENCIA_GLOBAL,
            CH.NOMBRE_HABILIDAD   AS NOMBRE_HABILIDAD_GLOBAL
        FROM EVALUACIONES E
        INNER JOIN DOCENTES D ON D.ID_DOCENTE = E.ID_DOCENTE
        LEFT JOIN EVALUACION_PREGUNTAS P ON P.ID_EVALUACION = E.ID_EVALUACION
        LEFT JOIN CATALOGO_COMPETENCIAS CC ON CC.ID_COMPETENCIA = E.ID_COMPETENCIA_GLOBAL
        LEFT JOIN CATALOGO_HABILIDADES  CH ON CH.ID_HABILIDAD   = E.ID_HABILIDAD_GLOBAL
        WHERE E.TIPO_COMPETENCIA = 'SABER_PRO'
    ";
    if ($idDocente > 0) $sql .= " AND E.ID_DOCENTE = $idDocente ";
    $sql .= " GROUP BY E.ID_EVALUACION ORDER BY E.ID_EVALUACION DESC";

    $result = $mysqli->query($sql);
    if (!$result) fail("Error en listado: " . $mysqli->error);
    $rows = [];
    while ($r = $result->fetch_assoc()) $rows[] = $r;
    ok(["data" => $rows], "Listado de evaluaciones Saber Pro");
}

// ===================== POST =====================
if ($method === "POST") {
    $b = jsonBody();

    $idDocente    = toInt($b["ID_DOCENTE"]            ?? 0);
    $idAsignacion = toInt($b["ID_ASIGNACION"]          ?? 0) ?: null;
    $titulo       = clean($b["TITULO_EVALUACION"]      ?? "");
    $descripcion  = clean($b["DESCRIPCION_EVALUACION"] ?? "") ?: null;
    $estado       = clean($b["ESTADO_EVALUACION"]      ?? "BORRADOR");
    $fechaInicio  = clean($b["FECHA_INICIO"]           ?? "") ?: null;
    $fechaFin     = clean($b["FECHA_FIN"]              ?? "") ?: null;
    $duracion     = toInt($b["DURACION_MINUTOS"]       ?? 0) ?: null;
    $intentos     = toInt($b["INTENTOS_PERMITIDOS"]    ?? 1, 1);
    $preguntas    = $b["preguntas"] ?? [];

    // Competencia global (por nombre o ID)
    $nombreCompGlobal = clean($b["NOMBRE_COMPETENCIA_GLOBAL"] ?? "");
    $nombreHabGlobal  = clean($b["NOMBRE_HABILIDAD_GLOBAL"]   ?? "");
    $idCompGlobalRaw  = toInt($b["ID_COMPETENCIA_GLOBAL"]     ?? 0);
    $idHabGlobalRaw   = toInt($b["ID_HABILIDAD_GLOBAL"]       ?? 0);

    if ($idDocente <= 0)  fail("ID_DOCENTE es requerido.");
    if ($titulo === "")   fail("TITULO_EVALUACION es requerido.");
    if (!in_array($estado, ["BORRADOR","PUBLICADA","CERRADA","ANULADA"])) $estado = "BORRADOR";
    if (!is_array($preguntas) || count($preguntas) === 0)
        fail("Debe incluir al menos una pregunta.");

    // Verificar docente
    $stDoc = $mysqli->prepare("SELECT ID_DOCENTE FROM DOCENTES WHERE ID_DOCENTE = ? LIMIT 1");
    if (!$stDoc) fail("Error verificando docente: " . $mysqli->error);
    $stDoc->bind_param("i", $idDocente);
    $stDoc->execute();
    if (!$stDoc->get_result()->fetch_assoc()) fail("El docente no existe.");

    $mysqli->begin_transaction();
    try {
        // Resolver competencia/habilidad global
        $idCompGlobal = resolveCompetencia($mysqli, $idCompGlobalRaw, $nombreCompGlobal ?: null);
        $idHabGlobal  = resolveHabilidad($mysqli, $idHabGlobalRaw, $nombreHabGlobal ?: null, $idCompGlobal);

        $stEval = $mysqli->prepare("
            INSERT INTO EVALUACIONES
                (ID_DOCENTE, ID_ASIGNACION, TITULO_EVALUACION, DESCRIPCION_EVALUACION,
                 TIPO_COMPETENCIA, ID_COMPETENCIA_GLOBAL, ID_HABILIDAD_GLOBAL,
                 ESTADO_EVALUACION, FECHA_INICIO, FECHA_FIN, DURACION_MINUTOS, INTENTOS_PERMITIDOS)
            VALUES (?, ?, ?, ?, 'SABER_PRO', ?, ?, ?, ?, ?, ?, ?)
        ");
        if (!$stEval) throw new Exception("Error preparando INSERT evaluación: " . $mysqli->error);
        bindParams($stEval, "iissiisssii", [
            $idDocente, $idAsignacion, $titulo, $descripcion,
            $idCompGlobal, $idHabGlobal,
            $estado, $fechaInicio, $fechaFin, $duracion, $intentos,
        ]);
        if (!$stEval->execute())
            throw new Exception("Error al guardar la evaluación: " . $stEval->error);

        $idEvaluacion = $mysqli->insert_id;
        $puntajeTotal = insertPreguntasSaberPro($mysqli, $idEvaluacion, $preguntas);

        // Actualizar puntaje total
        $stPuntaje = $mysqli->prepare(
            "UPDATE EVALUACIONES SET PUNTAJE_TOTAL = ? WHERE ID_EVALUACION = ?"
        );
        if (!$stPuntaje) throw new Exception("Error preparando UPDATE puntaje: " . $mysqli->error);
        $stPuntaje->bind_param("di", $puntajeTotal, $idEvaluacion);
        if (!$stPuntaje->execute())
            throw new Exception("Error al actualizar puntaje: " . $stPuntaje->error);

        $mysqli->commit();
        ok(["id" => $idEvaluacion, "puntaje_total" => $puntajeTotal], "Evaluación Saber Pro guardada correctamente");

    } catch (Exception $e) { $mysqli->rollback(); fail($e->getMessage()); }
}

// ===================== PUT =====================
if ($method === "PUT") {
    $b = jsonBody();

    $idEval       = toInt($b["ID_EVALUACION"]          ?? 0);
    $idDocente    = toInt($b["ID_DOCENTE"]              ?? 0);
    $idAsignacion = toInt($b["ID_ASIGNACION"]           ?? 0) ?: null;
    $titulo       = clean($b["TITULO_EVALUACION"]       ?? "");
    $descripcion  = clean($b["DESCRIPCION_EVALUACION"]  ?? "") ?: null;
    $estado       = clean($b["ESTADO_EVALUACION"]       ?? "BORRADOR");
    $fechaInicio  = clean($b["FECHA_INICIO"]            ?? "") ?: null;
    $fechaFin     = clean($b["FECHA_FIN"]               ?? "") ?: null;
    $duracion     = toInt($b["DURACION_MINUTOS"]        ?? 0) ?: null;
    $intentos     = toInt($b["INTENTOS_PERMITIDOS"]     ?? 1, 1);
    $preguntas    = $b["preguntas"] ?? [];

    $nombreCompGlobal = clean($b["NOMBRE_COMPETENCIA_GLOBAL"] ?? "");
    $nombreHabGlobal  = clean($b["NOMBRE_HABILIDAD_GLOBAL"]   ?? "");
    $idCompGlobalRaw  = toInt($b["ID_COMPETENCIA_GLOBAL"]     ?? 0);
    $idHabGlobalRaw   = toInt($b["ID_HABILIDAD_GLOBAL"]       ?? 0);

    if ($idEval    <= 0) fail("ID_EVALUACION es requerido.");
    if ($idDocente <= 0) fail("ID_DOCENTE es requerido.");
    if ($titulo === "")  fail("TITULO_EVALUACION es requerido.");
    if (!in_array($estado, ["BORRADOR","PUBLICADA","CERRADA","ANULADA"])) $estado = "BORRADOR";
    if (!is_array($preguntas) || count($preguntas) === 0)
        fail("Debe incluir al menos una pregunta.");

    // Verificar que pertenece al docente y es SABER_PRO
    $stChk = $mysqli->prepare("
        SELECT ID_EVALUACION FROM EVALUACIONES
        WHERE ID_EVALUACION = ? AND ID_DOCENTE = ? AND TIPO_COMPETENCIA = 'SABER_PRO' LIMIT 1
    ");
    if (!$stChk) fail("Error verificando evaluación: " . $mysqli->error);
    $stChk->bind_param("ii", $idEval, $idDocente);
    $stChk->execute();
    if (!$stChk->get_result()->fetch_assoc())
        fail("La evaluación no existe, no pertenece al docente o no es Saber Pro.", 403);

    $mysqli->begin_transaction();
    try {
        $idCompGlobal = resolveCompetencia($mysqli, $idCompGlobalRaw, $nombreCompGlobal ?: null);
        $idHabGlobal  = resolveHabilidad($mysqli, $idHabGlobalRaw, $nombreHabGlobal ?: null, $idCompGlobal);

        $stUpdate = $mysqli->prepare("
            UPDATE EVALUACIONES SET
                ID_ASIGNACION=?, TITULO_EVALUACION=?, DESCRIPCION_EVALUACION=?,
                ID_COMPETENCIA_GLOBAL=?, ID_HABILIDAD_GLOBAL=?,
                ESTADO_EVALUACION=?, FECHA_INICIO=?, FECHA_FIN=?,
                DURACION_MINUTOS=?, INTENTOS_PERMITIDOS=?
            WHERE ID_EVALUACION=? AND TIPO_COMPETENCIA='SABER_PRO' LIMIT 1
        ");
        if (!$stUpdate) throw new Exception("Error preparando UPDATE: " . $mysqli->error);
        bindParams($stUpdate, "issiisssiii", [
            $idAsignacion, $titulo, $descripcion,
            $idCompGlobal, $idHabGlobal,
            $estado, $fechaInicio, $fechaFin,
            $duracion, $intentos, $idEval,
        ]);
        if (!$stUpdate->execute())
            throw new Exception("Error al actualizar cabecera: " . $stUpdate->error);

        // Borrar opciones y preguntas anteriores
        $stDelOpc = $mysqli->prepare("
            DELETE O FROM EVALUACION_PREGUNTA_OPCIONES O
            INNER JOIN EVALUACION_PREGUNTAS P ON P.ID_PREGUNTA = O.ID_PREGUNTA
            WHERE P.ID_EVALUACION = ?
        ");
        if (!$stDelOpc) throw new Exception("Error preparando DELETE opciones: " . $mysqli->error);
        $stDelOpc->bind_param("i", $idEval);
        if (!$stDelOpc->execute())
            throw new Exception("Error al eliminar opciones anteriores: " . $stDelOpc->error);

        $stDelPreg = $mysqli->prepare(
            "DELETE FROM EVALUACION_PREGUNTAS WHERE ID_EVALUACION = ?"
        );
        if (!$stDelPreg) throw new Exception("Error preparando DELETE preguntas: " . $mysqli->error);
        $stDelPreg->bind_param("i", $idEval);
        if (!$stDelPreg->execute())
            throw new Exception("Error al eliminar preguntas anteriores: " . $stDelPreg->error);

        $puntajeTotal = insertPreguntasSaberPro($mysqli, $idEval, $preguntas);

        $stPuntaje = $mysqli->prepare(
            "UPDATE EVALUACIONES SET PUNTAJE_TOTAL = ? WHERE ID_EVALUACION = ?"
        );
        if (!$stPuntaje) throw new Exception("Error preparando UPDATE puntaje: " . $mysqli->error);
        $stPuntaje->bind_param("di", $puntajeTotal, $idEval);
        if (!$stPuntaje->execute())
            throw new Exception("Error al actualizar puntaje: " . $stPuntaje->error);

        $mysqli->commit();
        ok(["id" => $idEval, "puntaje_total" => $puntajeTotal], "Evaluación Saber Pro actualizada correctamente");

    } catch (Exception $e) { $mysqli->rollback(); fail($e->getMessage()); }
}

// ===================== PATCH: cambiar estado + campos de publicación =====================
if ($method === "PATCH") {
    $b         = jsonBody();
    $idEval    = toInt($b["ID_EVALUACION"]       ?? 0);
    $idDocente = toInt($b["ID_DOCENTE"]           ?? 0);
    $estado    = clean($b["ESTADO_EVALUACION"]    ?? "");

    $fechaInicio = array_key_exists("FECHA_INICIO",        $b) ? (clean($b["FECHA_INICIO"])        ?: null) : false;
    $fechaFin    = array_key_exists("FECHA_FIN",           $b) ? (clean($b["FECHA_FIN"])           ?: null) : false;
    $duracion    = array_key_exists("DURACION_MINUTOS",    $b) ? (toInt($b["DURACION_MINUTOS"])    ?: null) : false;
    $intentos    = array_key_exists("INTENTOS_PERMITIDOS", $b) ? (toInt($b["INTENTOS_PERMITIDOS"]) ?: null) : false;

    if ($idEval    <= 0) fail("ID_EVALUACION es requerido.");
    if ($idDocente <= 0) fail("ID_DOCENTE es requerido.");
    if (!in_array($estado, ["BORRADOR","PUBLICADA","CERRADA","ANULADA"]))
        fail("ESTADO_EVALUACION inválido. Valores permitidos: BORRADOR, PUBLICADA, CERRADA, ANULADA.");

    if ($estado === "PUBLICADA") {
        if ($fechaInicio === false || !$fechaInicio) fail("FECHA_INICIO es requerida para publicar.");
        if ($fechaFin    === false || !$fechaFin)    fail("FECHA_FIN es requerida para publicar.");
        if ($duracion    === false || !$duracion)    fail("DURACION_MINUTOS es requerida para publicar.");
        if ($intentos    === false || !$intentos)    fail("INTENTOS_PERMITIDOS es requerido para publicar.");
        if (strtotime($fechaFin) <= strtotime($fechaInicio))
            fail("FECHA_FIN debe ser posterior a FECHA_INICIO.");
    }

    $stChk = $mysqli->prepare("
        SELECT ID_EVALUACION FROM EVALUACIONES
        WHERE ID_EVALUACION = ? AND ID_DOCENTE = ? AND TIPO_COMPETENCIA = 'SABER_PRO' LIMIT 1
    ");
    if (!$stChk) fail("Error verificando evaluación: " . $mysqli->error);
    $stChk->bind_param("ii", $idEval, $idDocente);
    $stChk->execute();
    if (!$stChk->get_result()->fetch_assoc())
        fail("La evaluación no existe, no pertenece al docente o no es Saber Pro.", 403);

    $setClauses = ["ESTADO_EVALUACION = ?"];
    $types      = "s";
    $values     = [$estado];

    if ($fechaInicio !== false) { $setClauses[] = "FECHA_INICIO = ?";        $types .= "s"; $values[] = $fechaInicio; }
    if ($fechaFin    !== false) { $setClauses[] = "FECHA_FIN = ?";           $types .= "s"; $values[] = $fechaFin;    }
    if ($duracion    !== false) { $setClauses[] = "DURACION_MINUTOS = ?";    $types .= "i"; $values[] = $duracion;    }
    if ($intentos    !== false) { $setClauses[] = "INTENTOS_PERMITIDOS = ?"; $types .= "i"; $values[] = $intentos;    }

    $types   .= "i";
    $values[] = $idEval;

    $sql = "UPDATE EVALUACIONES SET " . implode(", ", $setClauses) . " WHERE ID_EVALUACION = ? LIMIT 1";
    $st  = $mysqli->prepare($sql);
    if (!$st) fail("Error preparando UPDATE: " . $mysqli->error);
    bindParams($st, $types, $values);
    if (!$st->execute()) fail("Error al actualizar: " . $st->error);

    ok([], "Estado actualizado a $estado");
}

// ===================== DELETE (soft: ANULADA) =====================
if ($method === "DELETE") {
    $id        = isset($_GET["id"])         ? (int)$_GET["id"]         : 0;
    $idDocente = isset($_GET["ID_DOCENTE"]) ? (int)$_GET["ID_DOCENTE"] : 0;

    if ($id        <= 0) fail("Parámetro id es requerido.");
    if ($idDocente <= 0) fail("Parámetro ID_DOCENTE es requerido.");

    $stChk = $mysqli->prepare("
        SELECT ID_EVALUACION FROM EVALUACIONES
        WHERE ID_EVALUACION = ? AND ID_DOCENTE = ? AND TIPO_COMPETENCIA = 'SABER_PRO' LIMIT 1
    ");
    if (!$stChk) fail("Error verificando evaluación: " . $mysqli->error);
    $stChk->bind_param("ii", $id, $idDocente);
    $stChk->execute();
    if (!$stChk->get_result()->fetch_assoc())
        fail("La evaluación no existe, no pertenece al docente o no es Saber Pro.", 403);

    $stmt = $mysqli->prepare(
        "UPDATE EVALUACIONES SET ESTADO_EVALUACION = 'ANULADA' WHERE ID_EVALUACION = ? LIMIT 1"
    );
    if (!$stmt) fail("Error preparando anulación: " . $mysqli->error);
    $stmt->bind_param("i", $id);
    if (!$stmt->execute()) fail("Error al anular la evaluación: " . $stmt->error);

    ok([], "Evaluación Saber Pro anulada");
}

fail("Método no permitido.", 405);