<?php
// api_corp/CORP_EVALUACIONES/examen.php

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

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

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

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

function ok($data = [], $message = "OK") {
    echo json_encode(array_merge(["success" => true, "message" => $message], $data)); exit;
}
function fail($message, $code = 400) {
    http_response_code($code);
    echo json_encode(["success" => false, "message" => $message]); exit;
}
function decodeJWT($token, $key) {
    $parts = explode(".", $token);
    if (count($parts) !== 3) return null;
    $payload = json_decode(base64_decode($parts[1]), true);
    $sig = base64_encode(hash_hmac("sha256", "$parts[0].$parts[1]", $key, true));
    if ($sig !== $parts[2]) return null;
    if (isset($payload["exp"]) && $payload["exp"] < time()) return null;
    return $payload;
}

// ── Auth ──────────────────────────────────────────────────────────
$authHeader = $_SERVER["HTTP_AUTHORIZATION"] ?? "";
if (!preg_match('/Bearer\s+(.+)/i', $authHeader, $m)) fail("Token requerido.", 401);
$jwtPayload = decodeJWT($m[1], $JWT_KEY);
if (!$jwtPayload) fail("Token inválido.", 401);

// ══════════════════════════════════════════════════════════════════
// GET
// ══════════════════════════════════════════════════════════════════
if ($_SERVER["REQUEST_METHOD"] === "GET") {
    $action = $_GET["action"]      ?? "";
    $idEst  = (int)($_GET["ID_ESTUDIANTE"] ?? 0);
    $idEval = (int)($_GET["ID_EVALUACION"] ?? 0);

    // ── disponibles ────────────────────────────────────────────
    if ($action === "disponibles") {
        if (!$idEst) fail("ID_ESTUDIANTE requerido.");

        /*
         * FIX: La query anterior usaba LEFT JOIN + IS NOT NULL lo cual
         * podía retornar evaluaciones de cursos donde el estudiante
         * NO está matriculado si el JOIN fallaba silenciosamente.
         *
         * Ahora usamos dos subqueries independientes con UNION para
         * separar claramente los dos casos de asignación:
         *   1) TIPO = 'CURSO'      → el estudiante debe tener matrícula activa en ese curso
         *   2) TIPO = 'ESTUDIANTE' → asignación directa al estudiante
         */
        $sql = "
            SELECT DISTINCT
                ev.ID_EVALUACION,
                ev.TITULO_EVALUACION,
                ev.DESCRIPCION_EVALUACION,
                ev.DURACION_MINUTOS,
                ev.INTENTOS_PERMITIDOS,
                ev.PUNTAJE_TOTAL,
                ev.FECHA_INICIO,
                ev.FECHA_FIN
            FROM EVALUACIONES ev
            INNER JOIN EVALUACION_ASIGNACIONES ea
                ON ea.ID_EVALUACION = ev.ID_EVALUACION
            INNER JOIN MATRICULAS m
                ON  m.ID_CURSO        = ea.ID_CURSO
                AND m.ID_ESTUDIANTE   = ?
                AND m.ESTADO_MATRICULA = 1
            WHERE ev.ESTADO_EVALUACION = 'PUBLICADA'
              AND ev.FECHA_INICIO     <= NOW()
              AND ev.FECHA_FIN        >= NOW()
              AND ea.TIPO_ASIGNACION   = 'CURSO'

            UNION

            SELECT DISTINCT
                ev.ID_EVALUACION,
                ev.TITULO_EVALUACION,
                ev.DESCRIPCION_EVALUACION,
                ev.DURACION_MINUTOS,
                ev.INTENTOS_PERMITIDOS,
                ev.PUNTAJE_TOTAL,
                ev.FECHA_INICIO,
                ev.FECHA_FIN
            FROM EVALUACIONES ev
            INNER JOIN EVALUACION_ASIGNACIONES ea
                ON  ea.ID_EVALUACION  = ev.ID_EVALUACION
                AND ea.TIPO_ASIGNACION = 'ESTUDIANTE'
                AND ea.ID_ESTUDIANTE  = ?
            WHERE ev.ESTADO_EVALUACION = 'PUBLICADA'
              AND ev.FECHA_INICIO     <= NOW()
              AND ev.FECHA_FIN        >= NOW()

            ORDER BY FECHA_FIN ASC
        ";

        $st = $mysqli->prepare($sql);
        if (!$st) fail("Error interno: " . $mysqli->error);
        $st->bind_param("ii", $idEst, $idEst);
        $st->execute();
        $rows = $st->get_result()->fetch_all(MYSQLI_ASSOC);
        ok(["data" => $rows]);
    }

    // ── intento_activo ─────────────────────────────────────────
    if ($action === "intento_activo") {
        if (!$idEval || !$idEst) fail("ID_EVALUACION e ID_ESTUDIANTE requeridos.");
        $st = $mysqli->prepare("
            SELECT * FROM EVALUACION_INTENTOS
            WHERE ID_EVALUACION = ? AND ID_ESTUDIANTE = ? AND ESTADO_INTENTO = 'EN_PROGRESO'
            ORDER BY ID_INTENTO DESC LIMIT 1
        ");
        $st->bind_param("ii", $idEval, $idEst);
        $st->execute();
        $row = $st->get_result()->fetch_assoc();
        ok(["data" => $row ?: null]);
    }

    // ── mis_intentos ───────────────────────────────────────────
    if ($action === "mis_intentos") {
        if (!$idEst) fail("ID_ESTUDIANTE requerido.");
        $st = $mysqli->prepare("
            SELECT
                i.ID_INTENTO,
                i.ID_EVALUACION,
                i.NUMERO_INTENTO,
                i.ESTADO_INTENTO,
                i.FECHA_INICIO,
                i.FECHA_ENVIO,
                i.PUNTAJE_OBTENIDO,
                i.PUNTAJE_ABIERTOS,
                i.PUNTAJE_TOTAL,
                i.TIENE_ABIERTAS,
                e.TITULO_EVALUACION,
                e.PUNTAJE_TOTAL AS PUNTAJE_MAXIMO,
                e.INTENTOS_PERMITIDOS,
                CASE
                    WHEN e.PUNTAJE_TOTAL > 0 AND i.PUNTAJE_TOTAL IS NOT NULL
                    THEN ROUND(i.PUNTAJE_TOTAL / e.PUNTAJE_TOTAL * 100, 1)
                    ELSE NULL
                END AS PORCENTAJE
            FROM EVALUACION_INTENTOS i
            INNER JOIN EVALUACIONES e ON e.ID_EVALUACION = i.ID_EVALUACION
            WHERE i.ID_ESTUDIANTE = ?
            ORDER BY i.FECHA_INICIO DESC
        ");
        $st->bind_param("i", $idEst);
        $st->execute();
        $rows = $st->get_result()->fetch_all(MYSQLI_ASSOC);
        ok(["data" => $rows]);
    }

    // ── detalle evaluación (preguntas sin ES_CORRECTA) ─────────
    if (!$action && $idEval) {
        $st = $mysqli->prepare("
            SELECT ev.*, d.NOMBRE_DOCENTE, d.APELLIDO_DOCENTE
            FROM EVALUACIONES ev
            INNER JOIN DOCENTES d ON d.ID_DOCENTE = ev.ID_DOCENTE
            WHERE ev.ID_EVALUACION = ? LIMIT 1
        ");
        $st->bind_param("i", $idEval);
        $st->execute();
        $ev = $st->get_result()->fetch_assoc();
        if (!$ev) fail("Evaluación no encontrada.", 404);

        $stP = $mysqli->prepare("
            SELECT
                p.ID_PREGUNTA,
                p.ORDEN_PREGUNTA,
                p.ENUNCIADO,
                p.TIPO_PREGUNTA,
                p.PUNTAJE_PREGUNTA,
                p.RESPUESTA_ESPERADA,
                p.IMAGEN_URL
            FROM EVALUACION_PREGUNTAS p
            WHERE p.ID_EVALUACION = ?
            ORDER BY p.ORDEN_PREGUNTA
        ");
        $stP->bind_param("i", $idEval);
        $stP->execute();
        $preguntas = $stP->get_result()->fetch_all(MYSQLI_ASSOC);

        foreach ($preguntas as &$preg) {
            $stO = $mysqli->prepare("
                SELECT ID_OPCION, ORDEN_OPCION, TEXTO_OPCION
                FROM EVALUACION_PREGUNTA_OPCIONES
                WHERE ID_PREGUNTA = ?
                ORDER BY ORDEN_OPCION
            ");
            $stO->bind_param("i", $preg["ID_PREGUNTA"]);
            $stO->execute();
            $preg["opciones"] = $stO->get_result()->fetch_all(MYSQLI_ASSOC);
        }
        unset($preg);

        $ev["preguntas"] = $preguntas;
        ok(["data" => $ev]);
    }

    fail("Acción GET no reconocida.");
}

// ══════════════════════════════════════════════════════════════════
// POST
// ══════════════════════════════════════════════════════════════════
if ($_SERVER["REQUEST_METHOD"] === "POST") {
    $body   = json_decode(file_get_contents("php://input"), true) ?: [];
    $action = $body["action"] ?? "";

    // ── iniciar ────────────────────────────────────────────────
    if ($action === "iniciar") {
        $idEval = (int)($body["ID_EVALUACION"] ?? 0);
        $idEst  = (int)($body["ID_ESTUDIANTE"] ?? 0);
        if (!$idEval || !$idEst) fail("ID_EVALUACION e ID_ESTUDIANTE requeridos.");

        // Verificar que la evaluación esté realmente asignada al estudiante
        // (misma lógica del UNION de disponibles)
        $stCheck = $mysqli->prepare("
            SELECT ev.ID_EVALUACION
            FROM EVALUACIONES ev
            INNER JOIN EVALUACION_ASIGNACIONES ea
                ON ea.ID_EVALUACION = ev.ID_EVALUACION
            INNER JOIN MATRICULAS m
                ON  m.ID_CURSO        = ea.ID_CURSO
                AND m.ID_ESTUDIANTE   = ?
                AND m.ESTADO_MATRICULA = 1
            WHERE ev.ID_EVALUACION     = ?
              AND ev.ESTADO_EVALUACION = 'PUBLICADA'
              AND ev.FECHA_INICIO     <= NOW()
              AND ev.FECHA_FIN        >= NOW()
              AND ea.TIPO_ASIGNACION   = 'CURSO'

            UNION

            SELECT ev.ID_EVALUACION
            FROM EVALUACIONES ev
            INNER JOIN EVALUACION_ASIGNACIONES ea
                ON  ea.ID_EVALUACION  = ev.ID_EVALUACION
                AND ea.TIPO_ASIGNACION = 'ESTUDIANTE'
                AND ea.ID_ESTUDIANTE  = ?
            WHERE ev.ID_EVALUACION     = ?
              AND ev.ESTADO_EVALUACION = 'PUBLICADA'
              AND ev.FECHA_INICIO     <= NOW()
              AND ev.FECHA_FIN        >= NOW()

            LIMIT 1
        ");
        $stCheck->bind_param("iiii", $idEst, $idEval, $idEst, $idEval);
        $stCheck->execute();
        if (!$stCheck->get_result()->fetch_assoc()) {
            fail("Evaluación no asignada o no disponible.", 403);
        }

        // Verificar que no haya intento activo
        $stAct = $mysqli->prepare("
            SELECT ID_INTENTO FROM EVALUACION_INTENTOS
            WHERE ID_EVALUACION = ? AND ID_ESTUDIANTE = ? AND ESTADO_INTENTO = 'EN_PROGRESO'
            LIMIT 1
        ");
        $stAct->bind_param("ii", $idEval, $idEst);
        $stAct->execute();
        $activo = $stAct->get_result()->fetch_assoc();
        if ($activo) ok(["id_intento" => (int)$activo["ID_INTENTO"]], "Intento en progreso retomado.");

        // Verificar intentos disponibles
        $stEv = $mysqli->prepare("SELECT INTENTOS_PERMITIDOS FROM EVALUACIONES WHERE ID_EVALUACION = ?");
        $stEv->bind_param("i", $idEval);
        $stEv->execute();
        $ev = $stEv->get_result()->fetch_assoc();
        if (!$ev) fail("Evaluación no encontrada.", 404);

        $stUsados = $mysqli->prepare("
            SELECT COUNT(*) AS cnt FROM EVALUACION_INTENTOS
            WHERE ID_EVALUACION = ? AND ID_ESTUDIANTE = ? AND ESTADO_INTENTO != 'EN_PROGRESO'
        ");
        $stUsados->bind_param("ii", $idEval, $idEst);
        $stUsados->execute();
        $usados = (int)$stUsados->get_result()->fetch_assoc()["cnt"];
        if ($usados >= (int)$ev["INTENTOS_PERMITIDOS"]) fail("Has agotado los intentos permitidos.");

        $numIntento = $usados + 1;
        $stIns = $mysqli->prepare("
            INSERT INTO EVALUACION_INTENTOS
                (ID_EVALUACION, ID_ESTUDIANTE, NUMERO_INTENTO, ESTADO_INTENTO, FECHA_INICIO)
            VALUES (?, ?, ?, 'EN_PROGRESO', NOW())
        ");
        $stIns->bind_param("iii", $idEval, $idEst, $numIntento);
        if (!$stIns->execute()) fail("Error creando intento.");
        ok(["id_intento" => $mysqli->insert_id], "Intento iniciado.");
    }

    // ── responder (auto-save) ──────────────────────────────────
    if ($action === "responder") {
        $idIntento  = (int)($body["ID_INTENTO"]  ?? 0);
        $idPregunta = (int)($body["ID_PREGUNTA"] ?? 0);
        if (!$idIntento || !$idPregunta) fail("ID_INTENTO e ID_PREGUNTA requeridos.");

        $idOpcion    = isset($body["ID_OPCION"])       ? (int)$body["ID_OPCION"]                                  : null;
        $idsOpciones = isset($body["IDS_OPCIONES"])    ? implode(",", array_map("intval", $body["IDS_OPCIONES"])) : null;
        $textoResp   = isset($body["TEXTO_RESPUESTA"]) ? trim($body["TEXTO_RESPUESTA"])                           : null;

        $stUp = $mysqli->prepare("
            INSERT INTO EVALUACION_RESPUESTAS
                (ID_INTENTO, ID_PREGUNTA, ID_OPCION, IDS_OPCIONES, TEXTO_RESPUESTA)
            VALUES (?, ?, ?, ?, ?)
            ON DUPLICATE KEY UPDATE
                ID_OPCION       = VALUES(ID_OPCION),
                IDS_OPCIONES    = VALUES(IDS_OPCIONES),
                TEXTO_RESPUESTA = VALUES(TEXTO_RESPUESTA),
                FECHA_RESPUESTA = NOW()
        ");
        $stUp->bind_param("iiiss", $idIntento, $idPregunta, $idOpcion, $idsOpciones, $textoResp);
        if (!$stUp->execute()) fail("Error guardando respuesta.");
        ok([], "Respuesta guardada.");
    }

    // ── enviar ─────────────────────────────────────────────────
    if ($action === "enviar") {
        $idIntento = (int)($body["ID_INTENTO"]    ?? 0);
        $idEst     = (int)($body["ID_ESTUDIANTE"] ?? 0);
        if (!$idIntento) fail("ID_INTENTO requerido.");

        $stI = $mysqli->prepare("
            SELECT i.*, e.ID_EVALUACION
            FROM EVALUACION_INTENTOS i
            INNER JOIN EVALUACIONES e ON e.ID_EVALUACION = i.ID_EVALUACION
            WHERE i.ID_INTENTO = ? LIMIT 1
        ");
        $stI->bind_param("i", $idIntento);
        $stI->execute();
        $intento = $stI->get_result()->fetch_assoc();
        if (!$intento) fail("Intento no encontrado.", 404);
        if ($intento["ESTADO_INTENTO"] !== "EN_PROGRESO") fail("Este intento ya fue enviado.");

        $idEval = (int)$intento["ID_EVALUACION"];

        $stR = $mysqli->prepare("
            SELECT r.*, p.TIPO_PREGUNTA, p.PUNTAJE_PREGUNTA
            FROM EVALUACION_RESPUESTAS r
            INNER JOIN EVALUACION_PREGUNTAS p ON p.ID_PREGUNTA = r.ID_PREGUNTA
            WHERE r.ID_INTENTO = ?
        ");
        $stR->bind_param("i", $idIntento);
        $stR->execute();
        $respuestas = $stR->get_result()->fetch_all(MYSQLI_ASSOC);

        $ptsAuto = 0.0;
        $tieneAb = false;

        foreach ($respuestas as $resp) {
            $tipo   = $resp["TIPO_PREGUNTA"];
            $ptsMax = (float)$resp["PUNTAJE_PREGUNTA"];
            $idResp = (int)$resp["ID_RESPUESTA"];
            $pts    = 0.0;
            $esCorr = 0;

            if ($tipo === "SELECCION_UNICA" || $tipo === "CON_IMAGEN") {
                if ($resp["ID_OPCION"]) {
                    $stO = $mysqli->prepare("
                        SELECT ES_CORRECTA FROM EVALUACION_PREGUNTA_OPCIONES WHERE ID_OPCION = ?
                    ");
                    $stO->bind_param("i", $resp["ID_OPCION"]);
                    $stO->execute();
                    $opc = $stO->get_result()->fetch_assoc();
                    if ($opc && $opc["ES_CORRECTA"]) { $pts = $ptsMax; $esCorr = 1; }
                }
                $stUpR = $mysqli->prepare("
                    UPDATE EVALUACION_RESPUESTAS SET ES_CORRECTA = ?, PUNTAJE_OBTENIDO = ? WHERE ID_RESPUESTA = ?
                ");
                $stUpR->bind_param("idi", $esCorr, $pts, $idResp);
                $stUpR->execute();
                $ptsAuto += $pts;

            } elseif ($tipo === "MULTIPLE") {
                $selIds = $resp["IDS_OPCIONES"]
                    ? array_map("intval", explode(",", $resp["IDS_OPCIONES"]))
                    : [];
                sort($selIds);

                $stC = $mysqli->prepare("
                    SELECT ID_OPCION FROM EVALUACION_PREGUNTA_OPCIONES
                    WHERE ID_PREGUNTA = ? AND ES_CORRECTA = 1
                    ORDER BY ID_OPCION
                ");
                $stC->bind_param("i", $resp["ID_PREGUNTA"]);
                $stC->execute();
                $corrIds = array_column($stC->get_result()->fetch_all(MYSQLI_ASSOC), "ID_OPCION");
                sort($corrIds);

                if ($selIds === $corrIds && count($selIds) > 0) { $pts = $ptsMax; $esCorr = 1; }

                $stUpR = $mysqli->prepare("
                    UPDATE EVALUACION_RESPUESTAS SET ES_CORRECTA = ?, PUNTAJE_OBTENIDO = ? WHERE ID_RESPUESTA = ?
                ");
                $stUpR->bind_param("idi", $esCorr, $pts, $idResp);
                $stUpR->execute();
                $ptsAuto += $pts;

            } elseif ($tipo === "ABIERTA") {
                $tieneAb = true;
                // No autocalificar
            }
        }

        $tieneAbInt = $tieneAb ? 1 : 0;
        $estado     = $tieneAb ? "ENVIADO" : "CALIFICADO";
        $ptsTotal   = $tieneAb ? null : $ptsAuto;
        $fechaEnvio = date("Y-m-d H:i:s");
        $fechaCal   = $tieneAb ? null : $fechaEnvio;

        $stFin = $mysqli->prepare("
            UPDATE EVALUACION_INTENTOS
            SET ESTADO_INTENTO   = ?,
                FECHA_ENVIO      = ?,
                FECHA_CALIFICADO = ?,
                PUNTAJE_OBTENIDO = ?,
                PUNTAJE_TOTAL    = ?,
                TIENE_ABIERTAS   = ?
            WHERE ID_INTENTO = ?
        ");
        $stFin->bind_param("sssddii", $estado, $fechaEnvio, $fechaCal, $ptsAuto, $ptsTotal, $tieneAbInt, $idIntento);
        $stFin->execute();

        $msg = $tieneAb
            ? "Examen enviado. Las preguntas abiertas quedan pendientes de calificación."
            : "Examen enviado y calificado. ¡Buen trabajo!";
        ok(["estado" => $estado, "puntaje_auto" => round($ptsAuto, 2)], $msg);
    }

    fail("Acción POST no reconocida.");
}

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