<?php
// concurso_nobel/participantes.php
// Pre-registro de participantes con padrón general tipo RENIEC local.
// Flujo DNI:
// 1) Buscar en personas_general.
// 2) Si no existe, consultar API RENIEC mediante includes/personas_general_helper.php.
// 3) Si API responde, guardar en personas_general.
// 4) Registrar participante en concurso_participantes vinculado con id_persona.

declare(strict_types=1);

session_start();

require_once __DIR__ . '/includes/db.php';
require_once __DIR__ . '/includes/concurso_contexto.php';
require_once __DIR__ . '/includes/personas_general_helper.php';

function p_upper(string $valor): string
{
    $valor = trim($valor);
    return function_exists('mb_strtoupper') ? mb_strtoupper($valor, 'UTF-8') : strtoupper($valor);
}

function p_strlen(string $valor): int
{
    return function_exists('mb_strlen') ? mb_strlen($valor, 'UTF-8') : strlen($valor);
}

function p_tipo_valido(string $tipo): bool
{
    return in_array($tipo, ['PUBLICA', 'PRIVADA'], true);
}

function p_json(array $payload): void
{
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($payload, JSON_UNESCAPED_UNICODE);
    exit;
}

function p_get(string $key, string $default = ''): string
{
    return trim((string)($_GET[$key] ?? $default));
}

function p_post(string $key, string $default = ''): string
{
    return trim((string)($_POST[$key] ?? $default));
}

function p_stmt_bind(mysqli_stmt $stmt, string $types, array $params): bool
{
    $refs = [];
    $refs[] = $stmt;
    $refs[] = $types;

    foreach ($params as $key => $value) {
        $refs[] = &$params[$key];
    }

    return (bool)call_user_func_array('mysqli_stmt_bind_param', $refs);
}

function p_tabla_existe(mysqli $conn, string $tabla): bool
{
    $tablaEscapada = mysqli_real_escape_string($conn, $tabla);
    $res = mysqli_query($conn, "SHOW TABLES LIKE '{$tablaEscapada}'");

    if (!$res) {
        return false;
    }

    $existe = mysqli_num_rows($res) > 0;
    mysqli_free_result($res);

    return $existe;
}

function p_columna_existe(mysqli $conn, string $tabla, string $columna): bool
{
    $tablaEscapada = mysqli_real_escape_string($conn, $tabla);
    $columnaEscapada = mysqli_real_escape_string($conn, $columna);
    $res = mysqli_query($conn, "SHOW COLUMNS FROM `{$tablaEscapada}` LIKE '{$columnaEscapada}'");

    if (!$res) {
        return false;
    }

    $existe = mysqli_num_rows($res) > 0;
    mysqli_free_result($res);

    return $existe;
}

function p_obtener_institucion(mysqli $conn, int $idInstitucion): ?array
{
    if ($idInstitucion <= 0 || !p_tabla_existe($conn, 'concurso_instituciones')) {
        return null;
    }

    $stmt = mysqli_prepare($conn, "
        SELECT
            id_institucion,
            nombre_institucion,
            gestion,
            departamento,
            provincia,
            distrito,
            niveles_detectados
        FROM concurso_instituciones
        WHERE id_institucion = ?
          AND estado = 1
        LIMIT 1
    ");

    if (!$stmt) {
        return null;
    }

    mysqli_stmt_bind_param($stmt, 'i', $idInstitucion);
    mysqli_stmt_execute($stmt);
    $res = mysqli_stmt_get_result($stmt);
    $row = $res ? mysqli_fetch_assoc($res) : null;
    mysqli_stmt_close($stmt);

    return $row ?: null;
}

function p_nivel_filtro_modular(string $nivel): string
{
    $nivel = p_upper($nivel);

    if (strpos($nivel, 'INICIAL') !== false) {
        return 'INICIAL';
    }

    if (strpos($nivel, 'PRIMARIA') !== false) {
        return 'PRIMARIA';
    }

    if (strpos($nivel, 'SECUNDARIA') !== false) {
        return 'SECUNDARIA';
    }

    return $nivel;
}

function p_obtener_nivel_grupo(mysqli $conn, int $idConcurso, int $idGrupo): string
{
    if ($idGrupo <= 0) {
        return '';
    }

    $stmt = mysqli_prepare($conn, "
        SELECT nivel, nombre
        FROM concurso_grupos
        WHERE id_concurso = ?
          AND id_grupo = ?
        LIMIT 1
    ");

    if (!$stmt) {
        return '';
    }

    mysqli_stmt_bind_param($stmt, 'ii', $idConcurso, $idGrupo);
    mysqli_stmt_execute($stmt);
    $res = mysqli_stmt_get_result($stmt);
    $row = $res ? mysqli_fetch_assoc($res) : null;
    mysqli_stmt_close($stmt);

    if (!$row) {
        return '';
    }

    return p_nivel_filtro_modular((string)($row['nivel'] ?: $row['nombre'] ?: ''));
}

function p_obtener_modular_institucion_grupo(mysqli $conn, int $idConcurso, int $idInstitucion, int $idGrupo): ?array
{
    if ($idInstitucion <= 0 || $idGrupo <= 0) {
        return null;
    }

    if (!p_tabla_existe($conn, 'concurso_institucion_modulares')) {
        return null;
    }

    $nivelFiltro = p_obtener_nivel_grupo($conn, $idConcurso, $idGrupo);

    if ($nivelFiltro === '') {
        return null;
    }

    $likeNivel = '%' . $nivelFiltro . '%';

    $stmt = mysqli_prepare($conn, "
        SELECT
            id_modular,
            id_institucion,
            codigo_modular,
            nivel_modalidad
        FROM concurso_institucion_modulares
        WHERE id_institucion = ?
          AND nivel_modalidad LIKE ?
        ORDER BY
            CASE
                WHEN nivel_modalidad = ? THEN 0
                WHEN nivel_modalidad LIKE CONCAT(?, '%') THEN 1
                ELSE 2
            END,
            codigo_modular ASC
        LIMIT 1
    ");

    if (!$stmt) {
        return null;
    }

    mysqli_stmt_bind_param($stmt, 'isss', $idInstitucion, $likeNivel, $nivelFiltro, $nivelFiltro);
    mysqli_stmt_execute($stmt);
    $res = mysqli_stmt_get_result($stmt);
    $row = $res ? mysqli_fetch_assoc($res) : null;
    mysqli_stmt_close($stmt);

    return $row ?: null;
}

function p_obtener_modular_por_codigo(mysqli $conn, int $idInstitucion, string $codigoModular): ?array
{
    $codigoModular = trim($codigoModular);

    if ($idInstitucion <= 0 || $codigoModular === '') {
        return null;
    }

    if (!p_tabla_existe($conn, 'concurso_institucion_modulares')) {
        return null;
    }

    $stmt = mysqli_prepare($conn, "
        SELECT
            id_modular,
            id_institucion,
            codigo_modular,
            nivel_modalidad
        FROM concurso_institucion_modulares
        WHERE id_institucion = ?
          AND codigo_modular = ?
        LIMIT 1
    ");

    if (!$stmt) {
        return null;
    }

    mysqli_stmt_bind_param($stmt, 'is', $idInstitucion, $codigoModular);
    mysqli_stmt_execute($stmt);
    $res = mysqli_stmt_get_result($stmt);
    $row = $res ? mysqli_fetch_assoc($res) : null;
    mysqli_stmt_close($stmt);

    return $row ?: null;
}

function p_generar_codigo_participante(mysqli $conn): string
{
    for ($i = 0; $i < 20; $i++) {
        $codigo = 'NOBEX-' . date('Y') . '-' . str_pad((string)random_int(1, 99999), 5, '0', STR_PAD_LEFT);

        $stmt = mysqli_prepare($conn, "
            SELECT id_participante
            FROM concurso_participantes
            WHERE codigo_participante = ?
            LIMIT 1
        ");

        if (!$stmt) {
            return $codigo;
        }

        mysqli_stmt_bind_param($stmt, 's', $codigo);
        mysqli_stmt_execute($stmt);
        $res = mysqli_stmt_get_result($stmt);
        $existe = $res ? mysqli_fetch_assoc($res) : null;
        mysqli_stmt_close($stmt);

        if (!$existe) {
            return $codigo;
        }
    }

    return 'NOBEX-' . date('YmdHis') . '-' . random_int(100, 999);
}

function p_generar_documento_alfanumerico(mysqli $conn, int $idConcurso): string
{
    $caracteres = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
    $max = strlen($caracteres) - 1;

    for ($intento = 0; $intento < 80; $intento++) {
        $codigo = '';

        for ($i = 0; $i < 8; $i++) {
            $codigo .= $caracteres[random_int(0, $max)];
        }

        $stmt = mysqli_prepare($conn, "
            SELECT id_participante
            FROM concurso_participantes
            WHERE id_concurso = ?
              AND documento = ?
              AND estado = 'ACTIVO'
            LIMIT 1
        ");

        if (!$stmt) {
            return $codigo;
        }

        mysqli_stmt_bind_param($stmt, 'is', $idConcurso, $codigo);
        mysqli_stmt_execute($stmt);
        $res = mysqli_stmt_get_result($stmt);
        $existe = $res ? mysqli_fetch_assoc($res) : null;
        mysqli_stmt_close($stmt);

        if (!$existe) {
            return $codigo;
        }
    }

    return strtoupper(substr(bin2hex(random_bytes(4)), 0, 8));
}

function p_boolean_fulltext(string $valor): string
{
    $valor = p_upper($valor);
    $valor = preg_replace('/[^\p{L}\p{N}\s]+/u', ' ', $valor);
    $partes = preg_split('/\s+/u', (string)$valor, -1, PREG_SPLIT_NO_EMPTY);

    if (!is_array($partes)) {
        return '';
    }

    $tokens = [];

    foreach ($partes as $parte) {
        $parte = trim((string)$parte);

        if ($parte === '') {
            continue;
        }

        if (p_strlen($parte) < 2) {
            continue;
        }

        $tokens[] = '+' . $parte . '*';

        if (count($tokens) >= 8) {
            break;
        }
    }

    return implode(' ', $tokens);
}

function p_like_busqueda(string $valor): string
{
    $valor = p_upper($valor);
    $valor = preg_replace('/[^\p{L}\p{N}\s]+/u', ' ', $valor);
    $valor = trim(preg_replace('/\s+/u', ' ', (string)$valor));

    if ($valor === '') {
        return '%';
    }

    return '%' . str_replace(' ', '%', $valor) . '%';
}

function p_persona_json(?array $persona): array
{
    if (!$persona) {
        return [];
    }

    $apellidoPaterno = p_upper((string)($persona['apellido_paterno'] ?? ''));
    $apellidoMaterno = p_upper((string)($persona['apellido_materno'] ?? ''));
    $nombres = p_upper((string)($persona['nombres'] ?? ''));
    $nombreCompleto = p_upper((string)($persona['nombre_completo'] ?? ''));

    if ($nombreCompleto === '') {
        $nombreCompleto = trim($apellidoPaterno . ' ' . $apellidoMaterno . ' ' . $nombres);
    }

    return [
        'id_persona' => (int)($persona['id_persona'] ?? 0),
        'tipo_documento' => (string)($persona['tipo_documento'] ?? 'DNI'),
        'numero_documento' => (string)($persona['numero_documento'] ?? ''),
        'documento' => (string)($persona['numero_documento'] ?? ''),
        'apellido_paterno' => $apellidoPaterno,
        'apellido_materno' => $apellidoMaterno,
        'nombres' => $nombres,
        'nombre_completo' => $nombreCompleto,
        'apellidos_nombres' => $nombreCompleto,
        'fuente_registro' => (string)($persona['fuente_registro'] ?? ''),
        'estado_verificacion' => (string)($persona['estado_verificacion'] ?? '')
    ];
}

function p_buscar_participante_concurso_actual(mysqli $conn, int $idConcurso, string $documento): ?array
{
    $documento = trim($documento);

    if ($idConcurso <= 0 || $documento === '') {
        return null;
    }

    $selectExtra = '';

    if (p_columna_existe($conn, 'concurso_participantes', 'id_persona')) {
        $selectExtra .= ", p.id_persona ";
    }

    if (p_columna_existe($conn, 'concurso_participantes', 'apellido_paterno')) {
        $selectExtra .= ", p.apellido_paterno ";
    }

    if (p_columna_existe($conn, 'concurso_participantes', 'apellido_materno')) {
        $selectExtra .= ", p.apellido_materno ";
    }

    if (p_columna_existe($conn, 'concurso_participantes', 'nombres')) {
        $selectExtra .= ", p.nombres ";
    }

    if (p_columna_existe($conn, 'concurso_participantes', 'codigo_modular_ie')) {
        $selectExtra .= ", p.codigo_modular_ie ";
    }

    if (p_columna_existe($conn, 'concurso_participantes', 'nivel_modalidad_ie')) {
        $selectExtra .= ", p.nivel_modalidad_ie ";
    }

    if (p_columna_existe($conn, 'concurso_participantes', 'id_institucion')) {
        $selectExtra .= ", p.id_institucion ";
    }

    $sql = "
        SELECT
            p.id_participante,
            p.codigo_participante,
            p.apellidos_nombres,
            p.institucion_educativa,
            p.tipo_institucion,
            p.documento,
            p.id_grupo,
            p.id_salon
            {$selectExtra},
            g.nombre AS grupo,
            s.nombre_salon
        FROM concurso_participantes p
        LEFT JOIN concurso_grupos g ON g.id_grupo = p.id_grupo
        LEFT JOIN concurso_salones s ON s.id_salon = p.id_salon
        WHERE p.id_concurso = ?
          AND p.documento = ?
          AND p.estado = 'ACTIVO'
        ORDER BY p.id_participante DESC
        LIMIT 1
    ";

    $stmt = mysqli_prepare($conn, $sql);

    if (!$stmt) {
        return null;
    }

    mysqli_stmt_bind_param($stmt, 'is', $idConcurso, $documento);
    mysqli_stmt_execute($stmt);
    $res = mysqli_stmt_get_result($stmt);
    $row = $res ? mysqli_fetch_assoc($res) : null;
    mysqli_stmt_close($stmt);

    return $row ?: null;
}

function p_guardar_persona_institucion(
    mysqli $conn,
    int $idPersona,
    int $idInstitucionCatalogo,
    string $institucionEducativa,
    string $tipoInstitucion,
    string $codigoModular,
    string $nivelModalidad,
    string $fuenteRegistro = 'CONCURSO_PARTICIPANTES'
): bool {
    if ($idPersona <= 0) {
        return false;
    }

    if (!p_tabla_existe($conn, 'personas_instituciones')) {
        return false;
    }

    if (!p_columna_existe($conn, 'personas_instituciones', 'id_persona')) {
        return false;
    }

    $anio = (int)date('Y');

    $yaExiste = false;

    if (
        p_columna_existe($conn, 'personas_instituciones', 'codigo_modular_ie') &&
        p_columna_existe($conn, 'personas_instituciones', 'anio')
    ) {
        $stmtCheck = mysqli_prepare($conn, "
            SELECT id_persona
            FROM personas_instituciones
            WHERE id_persona = ?
              AND codigo_modular_ie = ?
              AND anio = ?
              AND estado = 1
            LIMIT 1
        ");

        if ($stmtCheck) {
            mysqli_stmt_bind_param($stmtCheck, 'isi', $idPersona, $codigoModular, $anio);
            mysqli_stmt_execute($stmtCheck);
            $resCheck = mysqli_stmt_get_result($stmtCheck);
            $yaExiste = $resCheck && mysqli_fetch_assoc($resCheck) ? true : false;
            mysqli_stmt_close($stmtCheck);
        }
    }

    if ($yaExiste) {
        return true;
    }

    $mapa = [
        'id_persona' => ['i', $idPersona],
        'id_institucion' => ['i', $idInstitucionCatalogo],
        'institucion_educativa' => ['s', $institucionEducativa],
        'tipo_institucion' => ['s', $tipoInstitucion],
        'codigo_modular_ie' => ['s', $codigoModular],
        'nivel_modalidad_ie' => ['s', $nivelModalidad],
        'anio' => ['i', $anio],
        'fuente_registro' => ['s', $fuenteRegistro],
        'estado' => ['i', 1],
        'created_at' => ['RAW', 'NOW()'],
        'creado_en' => ['RAW', 'NOW()']
    ];

    $columnas = [];
    $placeholders = [];
    $types = '';
    $params = [];

    foreach ($mapa as $campo => $def) {
        if (!p_columna_existe($conn, 'personas_instituciones', $campo)) {
            continue;
        }

        $columnas[] = $campo;

        if ($def[0] === 'RAW') {
            $placeholders[] = $def[1];
            continue;
        }

        $placeholders[] = '?';
        $types .= $def[0];
        $params[] = $def[1];
    }

    if (empty($columnas)) {
        return false;
    }

    $sql = "
        INSERT INTO personas_instituciones
            (" . implode(', ', $columnas) . ")
        VALUES
            (" . implode(', ', $placeholders) . ")
    ";

    $stmt = mysqli_prepare($conn, $sql);

    if (!$stmt) {
        return false;
    }

    if ($types !== '') {
        p_stmt_bind($stmt, $types, $params);
    }

    $ok = mysqli_stmt_execute($stmt);
    mysqli_stmt_close($stmt);

    return $ok;
}

function p_ajax_ubicaciones(mysqli $conn): void
{
    if (!p_tabla_existe($conn, 'concurso_instituciones')) {
        p_json([
            'success' => false,
            'items' => [],
            'message' => 'La tabla concurso_instituciones no existe.'
        ]);
    }

    $tipo = strtolower(p_get('tipo'));
    $gestion = strtoupper(p_get('gestion', 'PRIVADA'));
    $departamento = p_upper(p_get('departamento'));
    $provincia = p_upper(p_get('provincia'));

    if (!p_tipo_valido($gestion)) {
        p_json([
            'success' => false,
            'items' => [],
            'message' => 'Tipo de institución inválido.'
        ]);
    }

    $sql = '';
    $params = [];
    $types = '';

    if ($tipo === 'departamentos') {
        $sql = "
            SELECT DISTINCT departamento AS nombre
            FROM concurso_instituciones
            WHERE estado = 1
              AND gestion = ?
              AND departamento <> ''
            ORDER BY departamento ASC
        ";
        $params = [$gestion];
        $types = 's';
    } elseif ($tipo === 'provincias') {
        if ($departamento === '') {
            p_json(['success' => true, 'items' => []]);
        }

        $sql = "
            SELECT DISTINCT provincia AS nombre
            FROM concurso_instituciones
            WHERE estado = 1
              AND gestion = ?
              AND departamento = ?
              AND provincia <> ''
            ORDER BY provincia ASC
        ";
        $params = [$gestion, $departamento];
        $types = 'ss';
    } elseif ($tipo === 'distritos') {
        if ($departamento === '' || $provincia === '') {
            p_json(['success' => true, 'items' => []]);
        }

        $sql = "
            SELECT DISTINCT distrito AS nombre
            FROM concurso_instituciones
            WHERE estado = 1
              AND gestion = ?
              AND departamento = ?
              AND provincia = ?
              AND distrito <> ''
            ORDER BY distrito ASC
        ";
        $params = [$gestion, $departamento, $provincia];
        $types = 'sss';
    } else {
        p_json([
            'success' => false,
            'items' => [],
            'message' => 'Tipo de ubicación inválido.'
        ]);
    }

    $stmt = mysqli_prepare($conn, $sql);

    if (!$stmt) {
        p_json([
            'success' => false,
            'items' => [],
            'message' => 'No se pudo preparar la consulta de ubicación.'
        ]);
    }

    p_stmt_bind($stmt, $types, $params);

    if (!mysqli_stmt_execute($stmt)) {
        mysqli_stmt_close($stmt);
        p_json([
            'success' => false,
            'items' => [],
            'message' => 'No se pudo consultar la ubicación.'
        ]);
    }

    $res = mysqli_stmt_get_result($stmt);
    $items = [];

    if ($res) {
        while ($row = mysqli_fetch_assoc($res)) {
            $nombre = trim((string)($row['nombre'] ?? ''));

            if ($nombre !== '') {
                $items[] = $nombre;
            }
        }
    }

    mysqli_stmt_close($stmt);

    p_json([
        'success' => true,
        'items' => $items
    ]);
}

function p_ajax_buscar_ie(mysqli $conn): void
{
    if (!p_tabla_existe($conn, 'concurso_instituciones')) {
        p_json([
            'success' => false,
            'items' => [],
            'message' => 'La tabla concurso_instituciones no existe.'
        ]);
    }

    if (!p_tabla_existe($conn, 'concurso_institucion_modulares')) {
        p_json([
            'success' => false,
            'items' => [],
            'message' => 'La tabla concurso_institucion_modulares no existe.'
        ]);
    }

    $q = p_upper(p_get('q'));
    $gestion = strtoupper(p_get('gestion', 'PRIVADA'));
    $departamento = p_upper(p_get('departamento'));
    $provincia = p_upper(p_get('provincia'));
    $distrito = p_upper(p_get('distrito'));

    if (!p_tipo_valido($gestion)) {
        p_json([
            'success' => false,
            'items' => [],
            'message' => 'Selecciona si la institución es pública o privada.'
        ]);
    }

    if (p_strlen($q) < 2) {
        p_json([
            'success' => true,
            'items' => [],
            'message' => 'Escribe mínimo 2 caracteres para buscar.'
        ]);
    }

    $boolean = p_boolean_fulltext($q);
    $like = p_like_busqueda($q);

    if ($boolean === '') {
        p_json([
            'success' => true,
            'items' => [],
            'message' => 'Escribe un nombre válido para buscar.'
        ]);
    }

    $sql = "
        SELECT
            i.id_institucion,
            i.nombre_institucion,
            i.gestion,
            i.departamento,
            i.provincia,
            i.distrito,
            i.niveles_detectados,
            m.id_modular,
            m.codigo_modular,
            m.nivel_modalidad
        FROM concurso_instituciones i
        INNER JOIN concurso_institucion_modulares m
            ON m.id_institucion = i.id_institucion
        WHERE i.estado = 1
          AND i.gestion = ?
          AND (
                MATCH(i.nombre_busqueda) AGAINST (? IN BOOLEAN MODE)
                OR i.nombre_busqueda LIKE ?
          )
    ";

    $params = [$gestion, $boolean, $like];
    $types = 'sss';

    if ($departamento !== '') {
        $sql .= " AND i.departamento = ? ";
        $params[] = $departamento;
        $types .= 's';
    }

    if ($provincia !== '') {
        $sql .= " AND i.provincia = ? ";
        $params[] = $provincia;
        $types .= 's';
    }

    if ($distrito !== '') {
        $sql .= " AND i.distrito = ? ";
        $params[] = $distrito;
        $types .= 's';
    }

    $sql .= "
        ORDER BY
            CASE
                WHEN i.nombre_institucion = ? THEN 0
                WHEN i.nombre_institucion LIKE CONCAT(?, '%') THEN 1
                ELSE 2
            END,
            i.nombre_institucion ASC,
            i.departamento ASC,
            i.provincia ASC,
            i.distrito ASC,
            CASE
                WHEN m.nivel_modalidad LIKE 'INICIAL%' THEN 1
                WHEN m.nivel_modalidad LIKE 'PRIMARIA%' THEN 2
                WHEN m.nivel_modalidad LIKE 'SECUNDARIA%' THEN 3
                ELSE 4
            END,
            m.codigo_modular ASC
        LIMIT 50
    ";

    $params[] = $q;
    $params[] = $q;
    $types .= 'ss';

    $stmt = mysqli_prepare($conn, $sql);

    if (!$stmt) {
        p_json([
            'success' => false,
            'items' => [],
            'message' => 'No se pudo preparar la búsqueda de instituciones.'
        ]);
    }

    p_stmt_bind($stmt, $types, $params);

    if (!mysqli_stmt_execute($stmt)) {
        $error = mysqli_stmt_error($stmt);
        mysqli_stmt_close($stmt);

        p_json([
            'success' => false,
            'items' => [],
            'message' => 'No se pudo buscar instituciones. ' . $error
        ]);
    }

    $res = mysqli_stmt_get_result($stmt);
    $items = [];

    if ($res) {
        while ($row = mysqli_fetch_assoc($res)) {
            $nombre = trim((string)($row['nombre_institucion'] ?? ''));
            $gestionRow = trim((string)($row['gestion'] ?? ''));
            $dep = trim((string)($row['departamento'] ?? ''));
            $prov = trim((string)($row['provincia'] ?? ''));
            $dist = trim((string)($row['distrito'] ?? ''));
            $niveles = trim((string)($row['niveles_detectados'] ?? ''));
            $codigoModular = trim((string)($row['codigo_modular'] ?? ''));
            $nivelModalidad = trim((string)($row['nivel_modalidad'] ?? ''));
            $nivelBase = p_nivel_filtro_modular($nivelModalidad);

            if ($nombre === '' || $codigoModular === '') {
                continue;
            }

            $label = $nombre . ' | ' . $nivelBase . ' | Código modular: ' . $codigoModular . ' | ' . $gestionRow . ' | ' . $dep . ' / ' . $prov . ' / ' . $dist;

            $items[] = [
                'id_institucion' => (int)$row['id_institucion'],
                'id_modular' => (int)$row['id_modular'],
                'codigo_modular' => $codigoModular,
                'nivel_modalidad' => $nivelBase,
                'nivel_modalidad_original' => $nivelModalidad,
                'nivel_base' => $nivelBase,
                'nombre_institucion' => $nombre,
                'gestion' => $gestionRow,
                'departamento' => $dep,
                'provincia' => $prov,
                'distrito' => $dist,
                'niveles_detectados' => $niveles,
                'label' => $label
            ];
        }
    }

    mysqli_stmt_close($stmt);

    p_json([
        'success' => true,
        'items' => $items,
        'message' => empty($items) ? 'No se encontraron instituciones con códigos modulares para esos filtros.' : ''
    ]);
}

$acceso = cn_validar_acceso($conn, 'index.php');

if ((int)$acceso['puede_registrar_participantes'] !== 1 && !cn_es_admin($acceso)) {
    http_response_code(403);
    die('Tu código no tiene permiso para registrar participantes.');
}

$esAdmin = cn_es_admin($acceso);
$idConcurso = cn_concurso_trabajo($conn, $acceso);

if ($idConcurso <= 0) {
    http_response_code(500);
    die('No hay concurso activo disponible.');
}

$concursoTrabajo = cn_datos_concurso($conn, $idConcurso);
$concursosActivos = $esAdmin ? cn_concursos_activos($conn) : [];
$idGrupoFijo = $esAdmin ? 0 : cn_id_grupo_fijo($acceso);
$idSalonFijo = $esAdmin ? 0 : cn_id_salon_fijo($acceso);

if (isset($_GET['ajax']) && $_GET['ajax'] === 'ubicaciones_ie') {
    p_ajax_ubicaciones($conn);
}

if (isset($_GET['ajax']) && $_GET['ajax'] === 'buscar_ie') {
    p_ajax_buscar_ie($conn);
}

if (isset($_GET['ajax']) && $_GET['ajax'] === 'modular_ie') {
    $idInstitucionAjax = (int)p_get('id_institucion');
    $idGrupoAjax = $idGrupoFijo > 0 ? $idGrupoFijo : (int)p_get('id_grupo');

    $modularAjax = p_obtener_modular_institucion_grupo($conn, $idConcurso, $idInstitucionAjax, $idGrupoAjax);

    if ($modularAjax) {
        p_json([
            'success' => true,
            'codigo_modular' => (string)$modularAjax['codigo_modular'],
            'nivel_modalidad' => p_nivel_filtro_modular((string)$modularAjax['nivel_modalidad'])
        ]);
    }

    p_json([
        'success' => false,
        'codigo_modular' => '',
        'nivel_modalidad' => '',
        'message' => 'No se encontró código modular para esa I.E. en el grado seleccionado.'
    ]);
}

if (isset($_GET['ajax']) && $_GET['ajax'] === 'buscar_documento') {
    $documentoAjax = pg_normalizar_dni((string)($_GET['documento'] ?? ''));

    if ($documentoAjax === '') {
        p_json([
            'success' => false,
            'exists' => false,
            'found' => false,
            'message' => 'Documento vacío.'
        ]);
    }

    if (!pg_dni_valido($documentoAjax)) {
        p_json([
            'success' => false,
            'exists' => false,
            'found' => false,
            'message' => 'El DNI debe tener 8 dígitos.'
        ]);
    }

    // 1) Buscar primero en personas_general.
    $personaLocal = pg_buscar_persona_general_por_dni($conn, $documentoAjax);
    $personaData = $personaLocal ? p_persona_json($personaLocal) : [];
    $origenPersona = $personaLocal ? 'PERSONAS_GENERAL' : '';

    // 2) Validar si ya está registrado en este concurso para bloquear duplicado.
    $participanteActual = p_buscar_participante_concurso_actual($conn, $idConcurso, $documentoAjax);

    if ($participanteActual) {
        if (!$personaLocal) {
            $personaDesdeParticipante = pg_persona_desde_participante($participanteActual);
            $guardarPersona = pg_guardar_persona_general($conn, $personaDesdeParticipante);

            if (!empty($guardarPersona['ok']) && !empty($guardarPersona['persona'])) {
                $personaData = p_persona_json($guardarPersona['persona']);
                $origenPersona = 'CONCURSO_PARTICIPANTES';

                if (
                    p_columna_existe($conn, 'concurso_participantes', 'id_persona') &&
                    isset($participanteActual['id_participante']) &&
                    !empty($guardarPersona['id_persona'])
                ) {
                    pg_vincular_participante_con_persona(
                        $conn,
                        (int)$participanteActual['id_participante'],
                        (int)$guardarPersona['id_persona']
                    );

                    $participanteActual['id_persona'] = (int)$guardarPersona['id_persona'];
                }
            }
        }

        if (empty($personaData)) {
            $personaData = [
                'apellido_paterno' => p_upper((string)($participanteActual['apellido_paterno'] ?? '')),
                'apellido_materno' => p_upper((string)($participanteActual['apellido_materno'] ?? '')),
                'nombres' => p_upper((string)($participanteActual['nombres'] ?? '')),
                'nombre_completo' => p_upper((string)($participanteActual['apellidos_nombres'] ?? '')),
                'apellidos_nombres' => p_upper((string)($participanteActual['apellidos_nombres'] ?? '')),
                'documento' => $documentoAjax,
                'numero_documento' => $documentoAjax
            ];
        }

        $salonTexto = !empty($participanteActual['nombre_salon']) ? $participanteActual['nombre_salon'] : 'Pendiente de asignación';

        $data = array_merge($participanteActual, $personaData);

        p_json([
            'success' => true,
            'exists' => true,
            'found' => true,
            'origen' => $origenPersona ?: 'CONCURSO_PARTICIPANTES',
            'message' => 'Este participante ya está registrado: ' . $participanteActual['apellidos_nombres'] . ' | ' . $participanteActual['tipo_institucion'] . ' | ' . ($participanteActual['grupo'] ?: 'Grado pendiente') . ' | Salón: ' . $salonTexto,
            'data' => $data
        ]);
    }

    // 3) Si no está registrado y existe en personas_general, autocompletar rápido.
    if ($personaLocal) {
        p_json([
            'success' => true,
            'exists' => false,
            'found' => true,
            'origen' => 'PERSONAS_GENERAL',
            'message' => 'DNI encontrado en padrón general local.',
            'data' => $personaData
        ]);
    }

    // 4) Si no existe en personas_general, recién consultar API RENIEC.
    $resolverApi = pg_resolver_persona_por_dni($conn, $documentoAjax, true);

    if (!empty($resolverApi['ok']) && !empty($resolverApi['encontrado']) && !empty($resolverApi['persona'])) {
        p_json([
            'success' => true,
            'exists' => false,
            'found' => true,
            'origen' => (string)($resolverApi['origen'] ?? 'API_RENIEC'),
            'message' => 'DNI encontrado por API y guardado en padrón general.',
            'data' => p_persona_json($resolverApi['persona'])
        ]);
    }

    p_json([
        'success' => true,
        'exists' => false,
        'found' => false,
        'origen' => 'NO_ENCONTRADO',
        'message' => 'No se encontró el DNI en padrón general ni en API. Puedes completar manualmente.',
        'data' => []
    ]);
}

if (empty($_SESSION['csrf_participantes_nobex'])) {
    $_SESSION['csrf_participantes_nobex'] = bin2hex(random_bytes(32));
}

$csrf = (string)$_SESSION['csrf_participantes_nobex'];
$mensajeOk = '';
$mensajeError = '';

$grupos = cn_grupos_concurso($conn, $idConcurso, $idGrupoFijo);

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $csrfPost = (string)($_POST['csrf_token'] ?? '');

    if (!hash_equals($csrf, $csrfPost)) {
        $mensajeError = 'Solicitud no válida. Recarga la página.';
    } else {
        $idGrupo = null;
        $documento = trim((string)($_POST['documento'] ?? ''));

        if ($documento !== '') {
            $documento = preg_replace('/\D+/', '', $documento);
        }

        $apellidoPaterno = p_upper((string)($_POST['apellido_paterno'] ?? ''));
        $apellidoMaterno = p_upper((string)($_POST['apellido_materno'] ?? ''));
        $nombresParticipante = p_upper((string)($_POST['nombres'] ?? ''));

        $apellidosNombres = trim(
            preg_replace(
                '/\s+/u',
                ' ',
                $apellidoPaterno . ' ' . $apellidoMaterno . ' ' . $nombresParticipante
            )
        );

        $tipoInstitucion = strtoupper(trim((string)($_POST['tipo_institucion'] ?? 'PRIVADA')));
        $institucionEducativa = p_upper((string)($_POST['institucion_educativa'] ?? ''));
        $idInstitucionCatalogo = (int)($_POST['id_institucion_catalogo'] ?? 0);
        $codigoModularSeleccionado = trim((string)($_POST['codigo_modular_ie'] ?? ''));
        $nivelModalidadSeleccionada = p_upper((string)($_POST['nivel_modalidad_ie'] ?? ''));
        $institucionCatalogo = $idInstitucionCatalogo > 0 ? p_obtener_institucion($conn, $idInstitucionCatalogo) : null;
        $modularCatalogo = $codigoModularSeleccionado !== '' ? p_obtener_modular_por_codigo($conn, $idInstitucionCatalogo, $codigoModularSeleccionado) : null;
        $observacion = trim((string)($_POST['observacion'] ?? ''));
        $documentoGeneradoAutomaticamente = false;
        $idPersona = null;

        if ($documento === '') {
            $documento = p_generar_documento_alfanumerico($conn, $idConcurso);
            $documentoGeneradoAutomaticamente = true;

            $observacion = trim(
                $observacion . "
CÓDIGO TEMPORAL GENERADO AUTOMÁTICAMENTE POR NO PRESENTAR DNI."
            );
        }

        if (!p_tipo_valido($tipoInstitucion)) {
            $mensajeError = 'Selecciona si la institución es pública o privada.';
        } elseif ($documento !== '' && !preg_match('/^[0-9A-Za-z\-]{4,30}$/', $documento)) {
            $mensajeError = 'El DNI o código solo debe contener letras, números o guiones.';
        } elseif (!$documentoGeneradoAutomaticamente && preg_match('/^\d+$/', $documento) && strlen($documento) !== 8) {
            $mensajeError = 'El DNI debe tener 8 dígitos.';
        } elseif ($apellidoPaterno === '') {
            $mensajeError = 'Ingresa el apellido paterno.';
        } elseif ($apellidoMaterno === '') {
            $mensajeError = 'Ingresa el apellido materno.';
        } elseif ($nombresParticipante === '') {
            $mensajeError = 'Ingresa los nombres.';
        } elseif ($institucionEducativa === '') {
            $mensajeError = 'Ingresa la I.E.';
        } elseif ($idInstitucionCatalogo <= 0) {
            $mensajeError = 'Selecciona la I.E. desde el catálogo.';
        } elseif ($codigoModularSeleccionado === '') {
            $mensajeError = 'Selecciona la I.E. exacta para detectar el código modular.';
        } elseif (!$institucionCatalogo) {
            $mensajeError = 'La I.E. seleccionada no existe o está inactiva en el catálogo.';
        } elseif (!$modularCatalogo) {
            $mensajeError = 'El código modular seleccionado no pertenece a la I.E. elegida.';
        } elseif (p_upper((string)$institucionCatalogo['gestion']) !== $tipoInstitucion) {
            $mensajeError = 'La I.E. seleccionada no corresponde al tipo de institución elegido.';
        } else {
            $institucionEducativa = p_upper((string)$institucionCatalogo['nombre_institucion']);
            $tipoInstitucion = p_upper((string)$institucionCatalogo['gestion']);
            $idInstitucionCatalogo = (int)$institucionCatalogo['id_institucion'];
            $codigoModularSeleccionado = (string)$modularCatalogo['codigo_modular'];

            $nivelModalidadOriginal = p_upper((string)$modularCatalogo['nivel_modalidad']);
            $nivelModalidadSeleccionada = p_nivel_filtro_modular($nivelModalidadOriginal);

            if (!in_array($nivelModalidadSeleccionada, ['INICIAL', 'PRIMARIA', 'SECUNDARIA'], true)) {
                $mensajeError = 'El código modular seleccionado no permite identificar si corresponde a Inicial, Primaria o Secundaria.';
            }

            if ($mensajeError === '' && $documento !== '') {
                $dup = p_buscar_participante_concurso_actual($conn, $idConcurso, $documento);

                if ($dup) {
                    $mensajeError = 'Este participante ya está registrado en este concurso: ' . $dup['apellidos_nombres'] . ' | ' . $dup['tipo_institucion'] . ' | ' . ($dup['grupo'] ?: 'Grado pendiente') . ' | ' . ($dup['nombre_salon'] ?: 'Salón pendiente') . '.';
                }
            }

            if ($mensajeError === '' && !$documentoGeneradoAutomaticamente && pg_dni_valido($documento)) {
                // POST rápido:
                // Primero buscar en personas_general. Si no existe, guardar con los datos del formulario.
                // La API se consulta por AJAX al escribir/blur del DNI, para que el guardado no se vuelva lento.
                $personaLocal = pg_buscar_persona_general_por_dni($conn, $documento);

                if ($personaLocal && !empty($personaLocal['id_persona'])) {
                    $idPersona = (int)$personaLocal['id_persona'];
                } else {
                    $guardarPersona = pg_guardar_persona_general($conn, [
                        'numero_documento' => $documento,
                        'apellido_paterno' => $apellidoPaterno,
                        'apellido_materno' => $apellidoMaterno,
                        'nombres' => $nombresParticipante,
                        'nombre_completo' => $apellidosNombres,
                        'fuente_registro' => 'FORMULARIO_PARTICIPANTES',
                        'estado_verificacion' => 'SIN_VERIFICAR'
                    ]);

                    if (!empty($guardarPersona['ok']) && !empty($guardarPersona['id_persona'])) {
                        $idPersona = (int)$guardarPersona['id_persona'];
                    }
                }
            }

            if ($mensajeError === '') {
                $codigoParticipante = p_generar_codigo_participante($conn);
                $idAcceso = (int)$acceso['id_acceso'];

                $columnas = [
                    'id_concurso',
                    'id_grupo',
                    'id_acceso_registro',
                    'codigo_participante',
                    'apellidos_nombres',
                    'institucion_educativa',
                    'tipo_institucion'
                ];

                $placeholders = ['?', '?', '?', '?', '?', '?', '?'];
                $types = 'iiissss';
                $params = [
                    $idConcurso,
                    $idGrupo,
                    $idAcceso,
                    $codigoParticipante,
                    $apellidosNombres,
                    $institucionEducativa,
                    $tipoInstitucion
                ];

                if (p_columna_existe($conn, 'concurso_participantes', 'id_persona')) {
                    $columnas[] = 'id_persona';
                    $placeholders[] = '?';
                    $types .= 'i';
                    $params[] = $idPersona;
                }

                if (p_columna_existe($conn, 'concurso_participantes', 'id_salon')) {
                    $idSalonPendiente = null;
                    $columnas[] = 'id_salon';
                    $placeholders[] = '?';
                    $types .= 'i';
                    $params[] = $idSalonPendiente;
                }

                if (p_columna_existe($conn, 'concurso_participantes', 'id_institucion')) {
                    $columnas[] = 'id_institucion';
                    $placeholders[] = '?';
                    $types .= 'i';
                    $params[] = $idInstitucionCatalogo;
                }

                if (p_columna_existe($conn, 'concurso_participantes', 'codigo_modular_ie')) {
                    $columnas[] = 'codigo_modular_ie';
                    $placeholders[] = '?';
                    $types .= 's';
                    $params[] = $codigoModularSeleccionado;
                }

                if (p_columna_existe($conn, 'concurso_participantes', 'nivel_modalidad_ie')) {
                    $columnas[] = 'nivel_modalidad_ie';
                    $placeholders[] = '?';
                    $types .= 's';
                    $params[] = $nivelModalidadSeleccionada;
                }

                if (p_columna_existe($conn, 'concurso_participantes', 'apellido_paterno')) {
                    $columnas[] = 'apellido_paterno';
                    $placeholders[] = '?';
                    $types .= 's';
                    $params[] = $apellidoPaterno;
                }

                if (p_columna_existe($conn, 'concurso_participantes', 'apellido_materno')) {
                    $columnas[] = 'apellido_materno';
                    $placeholders[] = '?';
                    $types .= 's';
                    $params[] = $apellidoMaterno;
                }

                if (p_columna_existe($conn, 'concurso_participantes', 'nombres')) {
                    $columnas[] = 'nombres';
                    $placeholders[] = '?';
                    $types .= 's';
                    $params[] = $nombresParticipante;
                }

                $columnas[] = 'documento';
                $placeholders[] = '?';
                $types .= 's';
                $params[] = $documento;

                $columnas[] = 'observacion';
                $placeholders[] = '?';
                $types .= 's';
                $params[] = $observacion;

                $columnas[] = 'estado';
                $placeholders[] = "'ACTIVO'";

                $columnas[] = 'created_at';
                $placeholders[] = 'NOW()';

                $stmtInsert = mysqli_prepare($conn, "
                    INSERT INTO concurso_participantes
                        (" . implode(', ', $columnas) . ")
                    VALUES
                        (" . implode(', ', $placeholders) . ")
                ");

                if (!$stmtInsert) {
                    $mensajeError = 'No se pudo preparar el pre-registro: ' . mysqli_error($conn);
                } else {
                    p_stmt_bind($stmtInsert, $types, $params);

                    if (mysqli_stmt_execute($stmtInsert)) {
                        $idParticipante = mysqli_insert_id($conn);

                        if ($idPersona !== null && $idPersona > 0) {
                            p_guardar_persona_institucion(
                                $conn,
                                $idPersona,
                                $idInstitucionCatalogo,
                                $institucionEducativa,
                                $tipoInstitucion,
                                $codigoModularSeleccionado,
                                $nivelModalidadSeleccionada,
                                'CONCURSO_PARTICIPANTES'
                            );
                        }

                        $mensajeOk = 'Participante registrado correctamente. Código: ' . $codigoParticipante . ' | Documento: ' . $documento . ' | Nivel: ' . $nivelModalidadSeleccionada . ' | Código modular: ' . $codigoModularSeleccionado . '.';

                        if ($idPersona !== null && $idPersona > 0) {
                            $mensajeOk .= ' Vinculado al padrón general con ID persona: ' . $idPersona . '.';
                        }

                        if ($documentoGeneradoAutomaticamente) {
                            $mensajeOk .= ' Se generó código alfanumérico temporal de 8 caracteres porque el estudiante no presentó DNI.';
                        }

                        cn_auditar($conn, $idConcurso, null, $idAcceso, $idParticipante, 'PARTICIPANTE_PREREGISTRADO', $mensajeOk);

                        $_SESSION['csrf_participantes_nobex'] = bin2hex(random_bytes(32));
                        $csrf = (string)$_SESSION['csrf_participantes_nobex'];
                    } else {
                        $mensajeError = 'No se pudo pre-registrar el participante: ' . mysqli_stmt_error($stmtInsert);
                    }

                    mysqli_stmt_close($stmtInsert);
                }
            }
        }
    }
}

$participantes = [];

$selectListaExtra = '';

if (p_columna_existe($conn, 'concurso_participantes', 'codigo_modular_ie')) {
    $selectListaExtra .= ", p.codigo_modular_ie ";
}

if (p_columna_existe($conn, 'concurso_participantes', 'nivel_modalidad_ie')) {
    $selectListaExtra .= ", p.nivel_modalidad_ie ";
}

if (p_columna_existe($conn, 'concurso_participantes', 'id_persona')) {
    $selectListaExtra .= ", p.id_persona ";
}

$sqlLista = "
    SELECT
        p.codigo_participante,
        p.apellidos_nombres,
        p.institucion_educativa,
        p.tipo_institucion,
        p.documento,
        p.created_at
        {$selectListaExtra},
        g.nombre AS grupo,
        s.nombre_salon
    FROM concurso_participantes p
    LEFT JOIN concurso_grupos g ON g.id_grupo = p.id_grupo
    LEFT JOIN concurso_salones s ON s.id_salon = p.id_salon
    WHERE p.id_concurso = ?
      AND p.estado = 'ACTIVO'
";

if ($idGrupoFijo > 0) {
    $sqlLista .= " AND (p.id_grupo = ? OR p.id_grupo IS NULL) ";
}

$sqlLista .= " ORDER BY p.id_participante DESC LIMIT 120";

$stmtLista = mysqli_prepare($conn, $sqlLista);

if ($stmtLista) {
    if ($idGrupoFijo > 0) {
        mysqli_stmt_bind_param($stmtLista, 'ii', $idConcurso, $idGrupoFijo);
    } else {
        mysqli_stmt_bind_param($stmtLista, 'i', $idConcurso);
    }

    mysqli_stmt_execute($stmtLista);
    $resLista = mysqli_stmt_get_result($stmtLista);

    if ($resLista) {
        while ($row = mysqli_fetch_assoc($resLista)) {
            $participantes[] = $row;
        }
    }

    mysqli_stmt_close($stmtLista);
}

$ambito = cn_ambito_texto($acceso, $concursoTrabajo);
?>
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <title>Participantes | NOBEX</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Bootstrap Icons + Font Awesome -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css">
    <link rel="stylesheet" href="assets/css/menu_concurso.css?v=4">
    <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>

    <style>
        *{box-sizing:border-box}
        :root{
            --red:#dc2626;
            --red-dark:#991b1b;
            --yellow:#facc15;
            --blue:#1d4ed8;
            --green:#16a34a;
            --slate:#0f172a;
            --muted:#64748b;
            --line:#e2e8f0;
            --bg:#f8fafc;
            --card:#ffffff;
        }

        body{
            margin:0;
            font-family:Inter,Arial,Helvetica,sans-serif;
            background:linear-gradient(135deg,#f8fafc 0%,#eef2ff 46%,#fff7ed 100%);
            color:#111827;
        }

        .topbar{
            background:linear-gradient(135deg,#991b1b,#dc2626);
            color:#fff;
            border-bottom:6px solid var(--yellow);
            padding:20px 22px;
            box-shadow:0 18px 40px rgba(153,27,27,.26);
        }

        .topbar-inner{
            max-width:1280px;
            margin:0 auto;
            display:flex;
            justify-content:space-between;
            gap:16px;
            align-items:center;
        }

        .brand-block{
            display:flex;
            gap:14px;
            align-items:center;
        }

        .brand-icon{
            width:48px;
            height:48px;
            border-radius:16px;
            background:rgba(255,255,255,.16);
            display:flex;
            align-items:center;
            justify-content:center;
            font-size:24px;
            border:1px solid rgba(255,255,255,.22);
        }

        .topbar h1{
            margin:0;
            font-size:25px;
            font-weight:900;
            letter-spacing:-.03em;
        }

        .topbar p{
            margin:5px 0 0;
            color:#fde68a;
            font-weight:800;
            font-size:13px;
        }

        .btn-panel{
            color:#fff;
            text-decoration:none;
            border:1px solid rgba(255,255,255,.35);
            border-radius:14px;
            padding:11px 15px;
            font-weight:900;
            white-space:nowrap;
            display:inline-flex;
            align-items:center;
            gap:8px;
            background:rgba(255,255,255,.10);
        }

        .container{
            max-width:1680px;
            margin:24px auto;
            padding:0 22px 42px;
        }

        .alert-ok,.alert-error,.alert-warn{
            border-radius:16px;
            padding:13px 15px;
            margin-bottom:16px;
            font-weight:800;
            line-height:1.45;
            box-shadow:0 8px 18px rgba(15,23,42,.06);
        }

        .alert-ok{background:#dcfce7;color:#166534;border:1px solid #bbf7d0}
        .alert-ok,.alert-error{display:none!important}
        .alert-error{background:#fee2e2;color:#991b1b;border:1px solid #fecaca}
        .alert-warn{background:#fef3c7;color:#92400e;border:1px solid #fde68a;display:none}

        .tabs{
            display:flex;
            gap:10px;
            flex-wrap:wrap;
            margin:0 0 20px;
        }

        .tab{
            display:inline-flex;
            align-items:center;
            gap:8px;
            justify-content:center;
            text-decoration:none;
            border:1px solid #e2e8f0;
            background:#fff;
            color:#334155;
            border-radius:999px;
            padding:11px 16px;
            font-weight:900;
            box-shadow:0 8px 18px rgba(15,23,42,.06);
        }

        .tab.active{
            background:linear-gradient(135deg,#dc2626,#991b1b);
            color:#fff;
            border-color:transparent;
        }

        .grid{
            display:grid;
            grid-template-columns:1fr;
            gap:24px;
            align-items:start;
        }

        .grid > .card{
            width:100%;
        }

        .grid > .card:first-child{
            padding:30px 34px;
        }

        .grid > .card:first-child .card-header{
            border-bottom:1px solid #e5e7eb;
            padding-bottom:16px;
            margin-bottom:22px;
        }

        .grid > .card:first-child .card-title i{
            width:52px;
            height:52px;
            border-radius:18px;
            font-size:23px;
        }

        .grid > .card:first-child h2{
            font-size:28px;
        }

        .card{
            background:rgba(255,255,255,.94);
            border:1px solid rgba(226,232,240,.95);
            border-radius:26px;
            padding:24px;
            box-shadow:0 20px 45px rgba(15,23,42,.10);
            backdrop-filter:blur(8px);
        }

        .card-header{
            display:flex;
            align-items:center;
            justify-content:space-between;
            gap:12px;
            margin-bottom:18px;
        }

        .card-title{
            display:flex;
            gap:11px;
            align-items:center;
        }

        .card-title i{
            width:42px;
            height:42px;
            border-radius:15px;
            background:#fee2e2;
            color:#dc2626;
            display:flex;
            align-items:center;
            justify-content:center;
            font-size:20px;
        }

        .card h2{
            margin:0;
            font-size:22px;
            font-weight:900;
            letter-spacing:-.03em;
        }

        .badge-soft{
            background:#eff6ff;
            color:#1d4ed8;
            font-weight:900;
            border-radius:999px;
            padding:7px 10px;
            font-size:12px;
            white-space:nowrap;
        }

        .admin-select{
            margin-bottom:18px;
            padding:14px;
            border-radius:18px;
            background:#f8fafc;
            border:1px solid var(--line);
        }

        label{
            display:block;
            font-weight:900;
            margin:14px 0 7px;
            color:#1f2937;
            font-size:13px;
        }

        label i{
            color:#dc2626;
            margin-right:7px;
        }

        input,select,textarea{
            width:100%;
            border:1px solid #dbe3ef;
            border-radius:15px;
            padding:12px 13px;
            font-size:15px;
            outline:none;
            background:#fff;
            min-height:46px;
            color:#0f172a;
        }

        textarea{
            min-height:74px;
            resize:vertical;
        }

        input:focus,select:focus,textarea:focus{
            border-color:#dc2626;
            box-shadow:0 0 0 4px rgba(220,38,38,.12);
        }

        input[readonly]{
            background:#f8fafc;
            color:#334155;
            font-weight:800;
        }

        .form-section-title{
            margin:18px 0 10px;
            padding:12px 14px;
            border-radius:16px;
            background:#f8fafc;
            border:1px solid #e5e7eb;
            color:#111827;
            font-weight:900;
            display:flex;
            gap:9px;
            align-items:center;
        }

        .form-section-title i{
            color:#dc2626;
        }

        .form-grid-2{
            display:grid;
            grid-template-columns:repeat(2,minmax(260px,1fr));
            gap:16px;
        }

        .input-icon{
            position:relative;
        }

        .input-icon > i{
            position:absolute;
            left:14px;
            top:50%;
            transform:translateY(-50%);
            color:#64748b;
            font-size:15px;
            pointer-events:none;
        }

        .input-icon input,
        .input-icon select{
            padding-left:42px;
        }

        .input-with-status input{
            padding-right:104px;
        }

        .spin{
            display:none;
            font-size:12px;
            color:#1d4ed8;
            font-weight:900;
            min-width:76px;
        }

        .input-with-status .spin{
            position:absolute;
            right:12px;
            top:50%;
            transform:translateY(-50%);
            min-width:auto;
            background:#eff6ff;
            color:#1d4ed8;
            padding:5px 8px;
            border-radius:999px;
        }

        .field-ok{border-color:#22c55e!important}
        .field-bad{border-color:#ef4444!important}

        .btn-save{
            width:100%;
            border:0;
            border-radius:17px;
            background:linear-gradient(135deg,#1d4ed8,#2563eb);
            color:#fff;
            font-weight:900;
            padding:14px 16px;
            margin-top:18px;
            cursor:pointer;
            font-size:15px;
            display:flex;
            justify-content:center;
            align-items:center;
            gap:9px;
            box-shadow:0 14px 26px rgba(37,99,235,.24);
        }

        .btn-save:hover{
            background:linear-gradient(135deg,#1e40af,#1d4ed8);
        }

        .btn-save:disabled{
            background:#9ca3af;
            cursor:not-allowed;
            box-shadow:none;
        }

        .ie-panel{
            border:1px solid #e5e7eb;
            background:#ffffff;
            border-radius:22px;
            padding:18px;
            margin-top:18px;
            box-shadow:inset 0 0 0 1px rgba(248,250,252,.85);
        }

        .ie-panel-title{
            font-weight:900;
            color:#0f172a;
            margin-bottom:12px;
            font-size:17px;
            display:flex;
            align-items:center;
            gap:9px;
        }

        .ie-panel-title i{
            color:#dc2626;
        }

        .ie-filters{
            display:grid;
            grid-template-columns:repeat(3,minmax(180px,1fr));
            gap:14px;
            margin:14px 0 12px;
        }

        .ie-filter-full{
            grid-column:auto;
        }

        .ie-search-wrap{
            position:relative;
        }

        .ie-results{
            display:none;
            position:static;
            margin-top:10px;
            background:#fff;
            border:1px solid #cbd5e1;
            border-radius:18px;
            box-shadow:0 10px 24px rgba(15,23,42,.09);
            max-height:292px;
            overflow-y:auto;
        }

        .ie-result-item{
            width:100%;
            display:block;
            text-align:left;
            border:0;
            border-bottom:1px solid #eef2f7;
            border-radius:0;
            background:linear-gradient(180deg,#ffffff 0%,#fffdfd 100%);
            color:#111827;
            padding:14px 16px;
            margin:0;
            cursor:pointer;
            font-size:14px;
            line-height:1.45;
            position:relative;
            transition:background .18s ease, transform .18s ease, box-shadow .18s ease;
        }

        .ie-result-item::before{
            content:"";
            position:absolute;
            left:0;
            top:12px;
            bottom:12px;
            width:5px;
            border-radius:0 8px 8px 0;
            background:linear-gradient(180deg,#ef4444 0%,#f97316 100%);
            opacity:.9;
        }

        .ie-result-item:last-child{border-bottom:0}
        .ie-result-item:hover{
            background:linear-gradient(180deg,#fff7f7 0%,#fff3f0 100%);
            color:#111827;
            transform:translateY(-1px);
            box-shadow:inset 0 0 0 1px #fecaca;
        }

        .ie-result-main{
            display:flex;
            align-items:center;
            gap:8px;
            font-size:14px;
            color:#111827;
            font-weight:900;
            letter-spacing:.01em;
        }

        .ie-result-main i{
            color:#dc2626;
            font-size:15px;
        }

        .ie-result-level{
            display:flex;
            flex-wrap:wrap;
            gap:8px;
            align-items:center;
            font-weight:900;
            font-size:12px;
            margin-top:9px;
        }

        .pill{
            display:inline-flex;
            align-items:center;
            gap:6px;
            padding:6px 11px;
            border-radius:999px;
            font-weight:900;
            font-size:12px;
            line-height:1;
            border:1px solid transparent;
        }

        .pill-blue{background:#dbeafe;color:#1d4ed8}
        .pill-green{background:#dcfce7;color:#15803d}
        .pill-red{background:#fee2e2;color:#b91c1c}
        .pill-gray{background:#f1f5f9;color:#475569}
        .pill-yellow{background:#fef3c7;color:#a16207}
        .pill-purple{background:#ede9fe;color:#6d28d9}
        .pill-orange{background:#ffedd5;color:#c2410c}
        .pill-inicial{background:#fee2e2;color:#b91c1c;border-color:#fecaca}
        .pill-primaria{background:#dcfce7;color:#15803d;border-color:#bbf7d0}
        .pill-secundaria{background:#dbeafe;color:#1d4ed8;border-color:#bfdbfe}
        .pill-modular{background:#fef3c7;color:#a16207;border-color:#fde68a}
        .pill-ubigeo{background:#ede9fe;color:#6d28d9;border-color:#ddd6fe}

        .ie-result-small{
            display:block;
            color:#64748b;
            font-size:12px;
            margin-top:4px;
        }

        .ie-selected{
            display:none;
            margin-top:11px;
            border:1px solid #fecaca;
            background:linear-gradient(180deg,#fff7f7 0%,#fff1f2 100%);
            color:#7f1d1d;
            border-radius:16px;
            padding:12px 13px;
            font-size:14px;
            font-weight:900;
            line-height:1.45;
        }

        .mini-label{
            margin:0 0 6px;
            font-size:13px;
            color:#475569;
            font-weight:900;
        }

        .table-wrap{
            overflow:auto;
        }

        table{
            width:100%;
            border-collapse:separate;
            border-spacing:0 8px;
            font-size:14px;
        }

        th,td{
            padding:11px 10px;
            text-align:left;
            vertical-align:top;
        }

        th{
            border:0;
            background:transparent;
            color:#64748b;
            font-size:12px;
            text-transform:uppercase;
            white-space:nowrap;
        }

        td{
            background:#fff;
            border-top:1px solid #e5e7eb;
            border-bottom:1px solid #e5e7eb;
        }

        tbody tr td:first-child{
            border-left:1px solid #e5e7eb;
            border-radius:14px 0 0 14px;
        }

        tbody tr td:last-child{
            border-right:1px solid #e5e7eb;
            border-radius:0 14px 14px 0;
        }

        .codigo{
            color:#1e40af;
            font-weight:900;
            white-space:nowrap;
        }

        .tipo{
            font-weight:900;
        }

        .empty{
            color:#6b7280;
            font-style:italic;
            padding:24px;
            background:#f8fafc;
            border-radius:18px;
            border:1px dashed #cbd5e1;
        }

        .page-summary{
            display:grid;
            grid-template-columns:repeat(3,1fr);
            gap:14px;
            margin:0 0 20px;
        }

        .summary-card{
            background:rgba(255,255,255,.95);
            border:1px solid rgba(226,232,240,.95);
            border-radius:22px;
            padding:16px;
            box-shadow:0 14px 32px rgba(15,23,42,.08);
            display:flex;
            align-items:center;
            gap:12px;
        }

        .summary-icon{
            width:44px;
            height:44px;
            border-radius:16px;
            display:flex;
            align-items:center;
            justify-content:center;
            flex:0 0 auto;
            font-size:20px;
        }

        .summary-icon.blue{background:#dbeafe;color:#1d4ed8}
        .summary-icon.green{background:#dcfce7;color:#166534}
        .summary-icon.yellow{background:#fef3c7;color:#92400e}
        .summary-card strong{display:block;font-size:22px;color:#0f172a;line-height:1}
        .summary-card span{display:block;color:#64748b;font-size:12px;font-weight:900;text-transform:uppercase;margin-top:5px}

        .table-toolbar{
            display:flex;
            justify-content:space-between;
            align-items:center;
            gap:12px;
            margin:0 0 14px;
            flex-wrap:wrap;
        }

        .search-box{
            position:relative;
            max-width:340px;
            min-width:230px;
            flex:1;
        }

        .search-box i{
            position:absolute;
            top:50%;
            left:13px;
            transform:translateY(-50%);
            color:#64748b;
        }

        .search-box input{
            min-height:42px;
            padding-left:40px;
        }

        .swal2-popup{border-radius:24px!important}
        .swal2-title{letter-spacing:-.02em!important}

        @media(max-width:1050px){
            .grid{grid-template-columns:1fr}
            .page-summary{grid-template-columns:1fr}
            .ie-filters{grid-template-columns:1fr}
        }

        @media(max-width:640px){
            .container{padding:0 14px 32px}
            .topbar-inner{flex-direction:column;align-items:flex-start}
            .form-grid-2{grid-template-columns:1fr}
            .ie-filters{grid-template-columns:1fr}
            .card{padding:18px}
            .grid > .card:first-child{padding:20px}
            .grid > .card:first-child h2{font-size:23px}
        }


        /* ============================================================
           DISEÑO COMPACTO TIPO FICHA - MÁS CAMPOS EN MENOS ESPACIO
        ============================================================ */
        .grid{
            grid-template-columns:1fr!important;
            gap:18px!important;
        }

        .container{
            max-width:1720px!important;
        }

        .grid > .card:first-child{
            padding:0!important;
            overflow:hidden;
            border-radius:20px!important;
        }

        .grid > .card:first-child .card-header{
            display:none!important;
        }

        .admin-select{
            margin:14px 16px 0!important;
            padding:10px 12px!important;
            border-radius:12px!important;
        }

        #frmParticipante{
            padding:0 16px 16px;
        }

        .registro-panel{
            border:1px solid #dbe3ef;
            border-radius:18px;
            background:#fff;
            margin-top:14px;
            overflow:visible;
        }

        .registro-panel-title{
            display:flex;
            align-items:center;
            justify-content:space-between;
            gap:12px;
            padding:10px 18px;
            background:linear-gradient(135deg,#16a34a,#0ea5e9);
            color:#fff;
            font-size:16px;
            font-weight:900;
            line-height:1.1;
        }

        .registro-panel-title span{
            display:flex;
            align-items:center;
            gap:9px;
        }

        .registro-panel-title small{
            color:#ecfeff;
            font-size:12px;
            font-weight:900;
        }

        .registro-panel-ie .registro-panel-title{
            background:linear-gradient(135deg,#dc2626,#f59e0b);
        }

        .registro-row{
            display:grid;
            gap:14px;
            padding:14px 18px;
            align-items:start;
        }

        .registro-row-datos{
            grid-template-columns:230px minmax(210px,1fr) minmax(210px,1fr) minmax(260px,1.25fr);
        }

        .registro-row-ie-main{
            grid-template-columns:190px 1fr;
            padding-bottom:8px;
        }

        .registro-row-ubicacion{
            grid-template-columns:repeat(3,minmax(180px,1fr));
            padding-top:0;
        }

        .registro-row-ie-unica{
            grid-template-columns:170px minmax(340px,2.1fr) minmax(145px,.75fr) minmax(145px,.75fr) minmax(145px,.75fr);
            align-items:end;
            gap:12px;
            padding:12px 18px 14px;
        }

        .registro-row-ie-unica .field label{
            white-space:nowrap;
            margin-bottom:5px!important;
        }

        .registro-row-ie-unica .field-ie-search{
            min-width:0;
        }

        .registro-row-ie-unica .field-ubigeo select{
            padding-left:12px!important;
        }

        .registro-row-final{
            grid-template-columns:1fr 280px;
            padding:14px 0 0;
            align-items:end;
        }

        .field label,
        #frmParticipante label{
            margin:0 0 6px!important;
            font-size:13px!important;
            line-height:1.05!important;
            color:#07142b!important;
            font-weight:900!important;
        }

        .field label i,
        #frmParticipante label i{
            color:#07142b!important;
            margin-right:5px!important;
        }

        .compact-input input,
        .compact-input select,
        .field select,
        #frmParticipante input,
        #frmParticipante select{
            height:38px!important;
            min-height:38px!important;
            border-radius:12px!important;
            padding-top:7px!important;
            padding-bottom:7px!important;
            font-size:14px!important;
        }

        #frmParticipante textarea{
            min-height:48px!important;
            height:48px!important;
            border-radius:12px!important;
            padding:8px 12px!important;
            font-size:14px!important;
        }

        .input-icon > i{
            left:13px!important;
            font-size:14px!important;
            color:#0f172a!important;
        }

        .input-icon input,
        .input-icon select{
            padding-left:40px!important;
        }

        .field-help{
            display:block;
            margin-top:6px;
            font-size:12px;
            color:#475569;
            line-height:1.15;
        }

        .input-with-status input{
            padding-right:96px!important;
        }

        .input-with-status .spin{
            right:8px!important;
            padding:4px 8px!important;
            font-size:11px!important;
        }

        .ie-results{
            margin:6px 18px 14px!important;
            max-height:230px!important;
            border-radius:14px!important;
        }

        .ie-selected{
            margin:0 18px 14px!important;
            border-radius:12px!important;
            padding:9px 11px!important;
            font-size:13px!important;
        }

        .btn-save{
            height:48px!important;
            margin-top:0!important;
            border-radius:13px!important;
            padding:10px 14px!important;
            font-size:14px!important;
        }

        .tabs{
            margin-bottom:14px!important;
        }

        .tab{
            padding:9px 14px!important;
            font-size:14px!important;
        }

        .page-summary{
            gap:10px!important;
            margin-bottom:14px!important;
        }

        .summary-card{
            padding:12px 14px!important;
            border-radius:16px!important;
        }

        .summary-icon{
            width:38px!important;
            height:38px!important;
            border-radius:13px!important;
            font-size:17px!important;
        }

        .summary-card strong{
            font-size:20px!important;
        }

        .summary-card span{
            font-size:11px!important;
        }

        .grid > .card:nth-child(2){
            padding:20px!important;
            border-radius:20px!important;
        }

        @media(max-width:1250px){
            .registro-row-datos{
                grid-template-columns:200px 1fr 1fr;
            }
            .field-nombres{
                grid-column:1 / -1;
            }
        }



        @media(max-width:1350px){
            .registro-row-ie-unica{
                grid-template-columns:160px minmax(300px,1.8fr) repeat(3,minmax(130px,1fr));
                gap:10px;
            }
        }

        @media(max-width:1100px){
            .registro-row-ie-unica{
                grid-template-columns:160px 1fr 1fr;
            }
            .field-ie-search{
                grid-column:2 / -1;
            }
        }
        @media(max-width:850px){
            .registro-row-datos,
            .registro-row-ie-main,
            .registro-row-ubicacion,
            .registro-row-ie-unica,
            .registro-row-final{
                grid-template-columns:1fr!important;
            }
            .field-nombres,
            .field-ie-search,
            .field-observacion,
            .field-boton{
                grid-column:auto!important;
            }
            #frmParticipante{
                padding:0 12px 14px;
            }
            .registro-row{
                padding:12px;
            }
        }

    

        /* ============================================================
           TEMA ROJO UNIFICADO - NOBEX
           Todo el formulario mantiene una sola línea visual institucional.
        ============================================================ */
        :root{
            --red:#dc2626!important;
            --red-dark:#991b1b!important;
            --blue:#dc2626!important;
            --green:#dc2626!important;
            --yellow:#facc15!important;
        }

        .topbar,
        .tab.active,
        .registro-panel-title,
        .registro-panel-ie .registro-panel-title,
        .btn-save,
        .btn-save:hover{
            background:linear-gradient(135deg,#991b1b 0%,#dc2626 52%,#ef4444 100%)!important;
            color:#fff!important;
        }

        .registro-panel-title small,
        .topbar p{
            color:#fff7ed!important;
        }

        .btn-save{
            box-shadow:0 12px 24px rgba(220,38,38,.24)!important;
        }

        .btn-save:disabled{
            background:#9ca3af!important;
            box-shadow:none!important;
        }

        .badge-soft,
        .pill-blue,
        .pill-green,
        .pill-yellow,
        .pill-gray,
        .summary-icon.blue,
        .summary-icon.green,
        .summary-icon.yellow,
        .card-title i{
            background:#fee2e2!important;
            color:#991b1b!important;
        }

        .pill-red{
            background:#fee2e2!important;
            color:#991b1b!important;
        }

        .summary-card strong,
        .codigo{
            color:#991b1b!important;
        }

        label i,
        .field label i,
        #frmParticipante label i,
        .form-section-title i,
        .ie-panel-title i,
        .input-icon > i{
            color:#991b1b!important;
        }

        input:focus,
        select:focus,
        textarea:focus{
            border-color:#dc2626!important;
            box-shadow:0 0 0 3px rgba(220,38,38,.12)!important;
        }

        .field-ok,
        #documento.field-ok,
        #institucion_educativa.field-ok{
            border-color:#dc2626!important;
            box-shadow:0 0 0 3px rgba(220,38,38,.10)!important;
        }

        .field-bad,
        #documento.field-bad,
        #institucion_educativa.field-bad{
            border-color:#991b1b!important;
            box-shadow:0 0 0 3px rgba(153,27,27,.10)!important;
        }

        .ie-selected{
            border-color:#fecaca!important;
            background:#fff1f2!important;
            color:#991b1b!important;
        }

        .input-with-status .spin{
            background:#fee2e2!important;
            color:#991b1b!important;
        }

        .ie-result-level .pill,
        .ie-result-item:hover .pill{
            background:#fee2e2!important;
            color:#991b1b!important;
        }

        .swal2-confirm{
            background:#dc2626!important;
        }

    
        /* ============================================================
           CORRECCIÓN FINAL: RESULTADOS DE I.E. EN LISTA COLORIDA
           Mantiene formato lista, pero corrige los colores que salían rojos.
        ============================================================ */

        .ie-results{
            display:none;
            position:static!important;
            margin:6px 18px 14px!important;
            padding:0!important;
            background:#ffffff!important;
            border:1px solid #dbe3ef!important;
            border-radius:16px!important;
            box-shadow:0 10px 24px rgba(15,23,42,.08)!important;
            max-height:292px!important;
            overflow-y:auto!important;
        }

        .ie-result-item{
            width:100%!important;
            display:block!important;
            text-align:left!important;
            border:0!important;
            border-bottom:1px solid #e5e7eb!important;
            border-radius:0!important;
            background:#ffffff!important;
            color:#0f172a!important;
            padding:13px 15px 13px 18px!important;
            margin:0!important;
            cursor:pointer!important;
            font-size:14px!important;
            line-height:1.42!important;
            position:relative!important;
            box-shadow:none!important;
            transform:none!important;
            transition:background .15s ease, box-shadow .15s ease!important;
        }

        .ie-result-item::before{
            content:""!important;
            position:absolute!important;
            left:0!important;
            top:10px!important;
            bottom:10px!important;
            width:5px!important;
            border-radius:0 8px 8px 0!important;
            background:linear-gradient(180deg,#3b82f6,#22c55e)!important;
            opacity:1!important;
        }

        .ie-result-item:last-child{
            border-bottom:0!important;
        }

        .ie-result-item:hover{
            background:#f8fafc!important;
            color:#0f172a!important;
            transform:none!important;
            box-shadow:inset 0 0 0 1px #bfdbfe!important;
        }

        .ie-result-main{
            display:flex!important;
            align-items:center!important;
            gap:8px!important;
            font-size:14px!important;
            color:#0f172a!important;
            font-weight:900!important;
            letter-spacing:.01em!important;
        }

        .ie-result-main i{
            color:#2563eb!important;
            font-size:15px!important;
        }

        .ie-result-level{
            display:flex!important;
            flex-wrap:wrap!important;
            gap:8px!important;
            align-items:center!important;
            margin-top:8px!important;
            font-weight:900!important;
            font-size:12px!important;
        }

        .ie-results .pill,
        .ie-selected .pill{
            display:inline-flex!important;
            align-items:center!important;
            gap:6px!important;
            padding:5px 10px!important;
            border-radius:999px!important;
            font-weight:900!important;
            font-size:12px!important;
            line-height:1!important;
            border:1px solid transparent!important;
            white-space:nowrap!important;
        }

        .ie-results .pill-inicial,
        .ie-selected .pill-inicial{
            background:#fce7f3!important;
            color:#be185d!important;
            border-color:#fbcfe8!important;
        }

        .ie-results .pill-primaria,
        .ie-selected .pill-primaria{
            background:#dcfce7!important;
            color:#166534!important;
            border-color:#bbf7d0!important;
        }

        .ie-results .pill-secundaria,
        .ie-selected .pill-secundaria{
            background:#dbeafe!important;
            color:#1d4ed8!important;
            border-color:#bfdbfe!important;
        }

        .ie-results .pill-modular,
        .ie-selected .pill-modular{
            background:#fef3c7!important;
            color:#92400e!important;
            border-color:#fde68a!important;
        }

        .ie-results .pill-ubigeo,
        .ie-selected .pill-ubigeo{
            background:#ede9fe!important;
            color:#6d28d9!important;
            border-color:#ddd6fe!important;
        }

        .ie-results .pill-red,
        .ie-selected .pill-red{
            background:#f1f5f9!important;
            color:#334155!important;
            border-color:#cbd5e1!important;
        }

        .ie-selected{
            margin:0 18px 14px!important;
            border:1px solid #bfdbfe!important;
            background:#eff6ff!important;
            color:#1e3a8a!important;
            border-radius:13px!important;
            padding:10px 12px!important;
            font-size:13px!important;
            font-weight:900!important;
        }

        .ie-selected .bi-check-circle-fill{
            color:#2563eb!important;
        }

    </style>
</head>
<body class="cn-con-sidebar">

<?php include __DIR__ . '/includes/sidebar_concurso.php'; ?>

<header class="topbar">
    <div class="topbar-inner">
        <div class="brand-block">
            <div class="brand-icon">
                <i class="fa-solid fa-trophy"></i>
            </div>
            <div>
                <h1>Pre-registro de participantes</h1>
                <p><?php echo cn_h($ambito); ?> | Código: <?php echo cn_h($acceso['codigo']); ?></p>
            </div>
        </div>
        <a class="btn-panel" href="panel.php">
            <i class="bi bi-arrow-left-circle"></i>
            Volver al panel
        </a>
    </div>
</header>

<main class="container">
    <div id="dniAviso" class="alert-warn" style="display:none"></div>

    <nav class="tabs">
        <a class="tab active" href="participantes.php"><i class="fa-solid fa-user-plus"></i> Registro manual</a>
        <a class="tab" href="admin/importar_participantes.php"><i class="fa-solid fa-file-excel"></i> Importar Excel</a>
        <a class="tab" href="admin/salones.php"><i class="fa-solid fa-door-open"></i> Control de salones</a>
    </nav>

    <div class="page-summary">
        <div class="summary-card">
            <div class="summary-icon blue"><i class="fa-solid fa-user-plus"></i></div>
            <div>
                <strong><?php echo count($participantes); ?></strong>
                <span>Registrados</span>
            </div>
        </div>
        <div class="summary-card">
            <div class="summary-icon green"><i class="fa-solid fa-database"></i></div>
            <div>
                <strong>Padrón</strong>
                <span>Base general</span>
            </div>
        </div>
        <div class="summary-card">
            <div class="summary-icon yellow"><i class="fa-solid fa-school"></i></div>
            <div>
                <strong>IE</strong>
                <span>Código modular</span>
            </div>
        </div>
    </div>

    <div class="grid">
        <section class="card">
            <div class="card-header">
                <div class="card-title">
                    <i class="fa-solid fa-user-graduate"></i>
                    <h2>Nuevo participante</h2>
                </div>
                <span class="badge-soft">NOBEX</span>
            </div>

            <?php if ($esAdmin): ?>
                <form method="get" action="" class="admin-select">
                    <label><i class="bi bi-trophy"></i> Concurso</label>
                    <select name="id_concurso" onchange="this.form.submit()">
                        <?php foreach ($concursosActivos as $c): ?>
                            <option value="<?php echo cn_h($c['id_concurso']); ?>" <?php echo (int)$c['id_concurso'] === $idConcurso ? 'selected' : ''; ?>>
                                <?php echo cn_h($c['nombre'] . ' ' . $c['subtitulo']); ?>
                            </option>
                        <?php endforeach; ?>
                    </select>
                </form>
            <?php endif; ?>

            <form method="post" action="" id="frmParticipante">
                <input type="hidden" name="csrf_token" value="<?php echo cn_h($csrf); ?>">
                <input type="hidden" name="id_concurso" id="id_concurso_actual" value="<?php echo cn_h($idConcurso); ?>">

                <div class="registro-panel">
                    <div class="registro-panel-title">
                        <span><i class="fa-solid fa-graduation-cap"></i> Ficha de Registro</span>
                        <small><?php echo cn_h($ambito); ?></small>
                    </div>

                    <div class="registro-row registro-row-datos">
                        <div class="field field-dni">
                            <label><i class="bi bi-credit-card-2-front"></i> DNI</label>
                            <div class="input-icon input-with-status compact-input">
                                <i class="fa-solid fa-hashtag"></i>
                                <input type="text" id="documento" name="documento" maxlength="8" placeholder="8 dígitos" autocomplete="off">
                                <span id="dniSpin" class="spin">Buscando...</span>
                            </div>
                            <small class="field-help">Se autocompleta si existe en padrón/API.</small>
                        </div>

                        <div class="field">
                            <label><i class="bi bi-person-vcard"></i> Apellido paterno</label>
                            <div class="input-icon compact-input">
                                <i class="fa-solid fa-user"></i>
                                <input type="text" id="apellido_paterno" name="apellido_paterno" maxlength="80" placeholder="Apellido paterno" autocomplete="off" required>
                            </div>
                        </div>

                        <div class="field">
                            <label><i class="bi bi-person-vcard"></i> Apellido materno</label>
                            <div class="input-icon compact-input">
                                <i class="fa-regular fa-user"></i>
                                <input type="text" id="apellido_materno" name="apellido_materno" maxlength="80" placeholder="Apellido materno" autocomplete="off" required>
                            </div>
                        </div>

                        <div class="field field-nombres">
                            <label><i class="bi bi-person-lines-fill"></i> Nombres</label>
                            <div class="input-icon compact-input">
                                <i class="fa-solid fa-signature"></i>
                                <input type="text" id="nombres" name="nombres" maxlength="120" placeholder="Nombres" autocomplete="off" required>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="registro-panel registro-panel-ie">
                    <div class="registro-panel-title">
                        <span><i class="fa-solid fa-school"></i> Institución educativa</span>
                        <small>Código modular y nivel</small>
                    </div>

                    <div class="registro-row registro-row-ie-unica">
                        <div class="field field-tipo">
                            <label><i class="bi bi-building"></i> Tipo</label>
                            <div class="input-icon compact-input">
                                <i class="fa-solid fa-layer-group"></i>
                                <select name="tipo_institucion" id="tipo_institucion" required>
                                    <option value="PRIVADA">PRIVADA</option>
                                    <option value="PUBLICA">PÚBLICA</option>
                                </select>
                            </div>
                        </div>

                        <div class="field field-ie-search">
                            <label><i class="fa-solid fa-magnifying-glass-location"></i> Buscar I.E.</label>
                            <div class="ie-search-wrap">
                                <div class="input-icon compact-input">
                                    <i class="fa-solid fa-school-flag"></i>
                                    <input type="text" id="institucion_educativa" name="institucion_educativa" maxlength="180" placeholder="Nombre de institución" autocomplete="off" required>
                                </div>

                                <input type="hidden" id="id_institucion_catalogo" name="id_institucion_catalogo" value="">
                                <input type="hidden" id="codigo_modular_ie_hidden" name="codigo_modular_ie" value="">
                                <input type="hidden" id="nivel_modalidad_ie_hidden" name="nivel_modalidad_ie" value="">
                            </div>
                        </div>

                        <div class="field field-ubigeo">
                            <label><i class="fa-solid fa-map-location-dot"></i> Departamento</label>
                            <select id="ie_departamento">
                                <option value="">Todos</option>
                            </select>
                        </div>

                        <div class="field field-ubigeo">
                            <label><i class="fa-solid fa-location-dot"></i> Provincia</label>
                            <select id="ie_provincia" disabled>
                                <option value="">Todas</option>
                            </select>
                        </div>

                        <div class="field field-ubigeo">
                            <label><i class="fa-solid fa-map-pin"></i> Distrito</label>
                            <select id="ie_distrito" disabled>
                                <option value="">Todos</option>
                            </select>
                        </div>
                    </div>

                    <div id="ieResultados" class="ie-results"></div>
                    <div id="ieSeleccionada" class="ie-selected"></div>
                </div>

                <div class="registro-row registro-row-final">
                    <div class="field field-observacion">
                        <label><i class="bi bi-chat-left-text"></i> Observación</label>
                        <textarea name="observacion" maxlength="1000" placeholder="Opcional"></textarea>
                    </div>

                    <div class="field field-boton">
                        <button type="submit" id="btnGuardar" class="btn-save">
                            <i class="fa-solid fa-floppy-disk"></i>
                            Registrar participante
                        </button>
                    </div>
                </div>
            </form>
        </section>

        <section class="card">
            <div class="card-header">
                <div class="card-title">
                    <i class="fa-solid fa-users"></i>
                    <h2>Participantes registrados</h2>
                </div>
                <span class="badge-soft"><?php echo count($participantes); ?> registros</span>
            </div>

            <?php if (!empty($participantes)): ?>
                <div class="table-toolbar">
                    <div class="search-box">
                        <i class="fa-solid fa-magnifying-glass"></i>
                        <input type="text" id="buscarParticipante" placeholder="Buscar participante, DNI o I.E...">
                    </div>
                    <span class="badge-soft"><i class="fa-solid fa-database"></i> <?php echo count($participantes); ?> registros</span>
                </div>
                <div class="table-wrap">
                    <table id="tablaParticipantes">
                        <thead>
                            <tr>
                                <th>Código</th>
                                <th>DNI</th>
                                <th>Participante</th>
                                <th>I.E.</th>
                                <th>Tipo</th>
                                <th>Nivel</th>
                                <th>Padrón</th>
                                <th>Grado</th>
                                <th>Salón</th>
                                <th>Registro</th>
                            </tr>
                        </thead>
                        <tbody>
                            <?php foreach ($participantes as $p): ?>
                                <?php
                                    $nivelFila = '';
                                    if (isset($p['nivel_modalidad_ie'])) {
                                        $nivelFila = p_nivel_filtro_modular((string)$p['nivel_modalidad_ie']);
                                    }

                                    $tipoFila = (string)($p['tipo_institucion'] ?? '');
                                    $tipoClase = $tipoFila === 'PUBLICA' ? 'pill-blue' : 'pill-red';
                                    $idPersonaFila = (int)($p['id_persona'] ?? 0);
                                ?>
                                <tr>
                                    <td class="codigo"><?php echo cn_h($p['codigo_participante']); ?></td>
                                    <td><?php echo cn_h($p['documento']); ?></td>
                                    <td><strong><?php echo cn_h($p['apellidos_nombres']); ?></strong></td>
                                    <td><?php echo cn_h($p['institucion_educativa']); ?></td>
                                    <td><span class="pill <?php echo cn_h($tipoClase); ?>"><?php echo cn_h($tipoFila); ?></span></td>
                                    <td><span class="pill pill-green"><?php echo cn_h($nivelFila ?: 'PENDIENTE'); ?></span></td>
                                    <td>
                                        <?php if ($idPersonaFila > 0): ?>
                                            <span class="pill pill-blue">ID <?php echo cn_h((string)$idPersonaFila); ?></span>
                                        <?php else: ?>
                                            <span class="pill pill-yellow">Temporal</span>
                                        <?php endif; ?>
                                    </td>
                                    <td><?php echo cn_h($p['grupo'] ?: 'Pendiente'); ?></td>
                                    <td><?php echo cn_h($p['nombre_salon'] ?: 'Pendiente'); ?></td>
                                    <td><?php echo cn_h($p['created_at']); ?></td>
                                </tr>
                            <?php endforeach; ?>
                        </tbody>
                    </table>
                </div>
            <?php else: ?>
                <p class="empty"><i class="bi bi-info-circle"></i> Todavía no hay participantes registrados.</p>
            <?php endif; ?>
        </section>
    </div>
</main>

<script>
document.addEventListener('DOMContentLoaded', function () {
    const documento = document.getElementById('documento');
    const apellidoPaterno = document.getElementById('apellido_paterno');
    const apellidoMaterno = document.getElementById('apellido_materno');
    const nombres = document.getElementById('nombres');
    const ie = document.getElementById('institucion_educativa');
    const tipoInstitucion = document.getElementById('tipo_institucion');
    const aviso = document.getElementById('dniAviso');
    const spin = document.getElementById('dniSpin');
    const btnGuardar = document.getElementById('btnGuardar');
    const idConcursoActual = document.getElementById('id_concurso_actual');
    const ieResultados = document.getElementById('ieResultados');
    const ieSeleccionada = document.getElementById('ieSeleccionada');
    const idInstitucionCatalogo = document.getElementById('id_institucion_catalogo');
    const codigoModularIeHidden = document.getElementById('codigo_modular_ie_hidden');
    const nivelModalidadIeHidden = document.getElementById('nivel_modalidad_ie_hidden');
    const ieDepartamento = document.getElementById('ie_departamento');
    const ieProvincia = document.getElementById('ie_provincia');
    const ieDistrito = document.getElementById('ie_distrito');
    const frmParticipante = document.getElementById('frmParticipante');
    const buscarParticipante = document.getElementById('buscarParticipante');
    const tablaParticipantes = document.getElementById('tablaParticipantes');

    const mensajeServidorOk = <?php echo json_encode($mensajeOk, JSON_UNESCAPED_UNICODE); ?>;
    const mensajeServidorError = <?php echo json_encode($mensajeError, JSON_UNESCAPED_UNICODE); ?>;

    let ieTimer = null;
    let ultimoSweetTexto = '';
    let ultimoSweetTiempo = 0;
    let ieAbort = null;
    let dniAbort = null;

    function mostrarSweet(texto, tipo, tituloPersonalizado) {
        if (!texto || typeof Swal === 'undefined') return;

        const ahora = Date.now();
        const key = String(tipo || '') + '|' + String(texto || '');

        if (key === ultimoSweetTexto && (ahora - ultimoSweetTiempo) < 900) return;

        ultimoSweetTexto = key;
        ultimoSweetTiempo = ahora;

        let icono = 'warning';
        let titulo = tituloPersonalizado || 'Atención';

        if (tipo === 'error') {
            icono = 'error';
            titulo = tituloPersonalizado || 'No permitido';
        } else if (tipo === 'ok') {
            icono = 'success';
            titulo = tituloPersonalizado || 'Correcto';

            Swal.fire({
                toast: true,
                position: 'top-end',
                icon: icono,
                title: titulo,
                text: texto,
                showConfirmButton: false,
                timer: 2600,
                timerProgressBar: true,
                background: '#ffffff',
                color: '#0f172a'
            });

            return;
        }

        Swal.fire({
            icon: icono,
            title: titulo,
            text: texto,
            confirmButtonText: 'Entendido',
            confirmButtonColor: tipo === 'error' ? '#dc2626' : '#dc2626'
        });
    }

    function mostrarAviso(texto, tipo) {
        if (aviso) {
            aviso.textContent = '';
            aviso.style.display = 'none';
        }

        if (!texto) {
            return;
        }

        try {
            mostrarSweet(texto, tipo);
        } catch (e) {
            console.warn('SweetAlert2 no pudo mostrarse:', e);
        }
    }

    if (mensajeServidorOk) {
        mostrarSweet(mensajeServidorOk, 'ok', 'Registrado');
    }

    if (mensajeServidorError) {
        mostrarSweet(mensajeServidorError, 'error', 'No se pudo registrar');
    }

    function upperInput(el) {
        if (!el) return;
        el.addEventListener('input', function () {
            el.value = el.value.toUpperCase();
        });
    }

    function limpiarOpciones(select, texto, disabled) {
        if (!select) return;
        select.innerHTML = '';
        const opt = document.createElement('option');
        opt.value = '';
        opt.textContent = texto;
        select.appendChild(opt);
        select.disabled = !!disabled;
    }

    function agregarOpciones(select, items) {
        if (!select) return;

        items.forEach(function (item) {
            const opt = document.createElement('option');
            opt.value = item;
            opt.textContent = item;
            select.appendChild(opt);
        });
    }

    function nivelBase(nivel) {
        const n = String(nivel || '').toUpperCase();

        if (n.indexOf('INICIAL') !== -1) return 'INICIAL';
        if (n.indexOf('PRIMARIA') !== -1) return 'PRIMARIA';
        if (n.indexOf('SECUNDARIA') !== -1) return 'SECUNDARIA';

        return n;
    }

    async function cargarUbicaciones(tipo) {
        const gestion = tipoInstitucion ? tipoInstitucion.value : 'PRIVADA';
        const departamento = ieDepartamento ? ieDepartamento.value : '';
        const provincia = ieProvincia ? ieProvincia.value : '';

        let url = 'participantes.php?ajax=ubicaciones_ie&tipo=' + encodeURIComponent(tipo) + '&gestion=' + encodeURIComponent(gestion);

        if (tipo === 'provincias') {
            url += '&departamento=' + encodeURIComponent(departamento);
        }

        if (tipo === 'distritos') {
            url += '&departamento=' + encodeURIComponent(departamento) + '&provincia=' + encodeURIComponent(provincia);
        }

        try {
            const resp = await fetch(url, { headers: { 'Accept': 'application/json' } });
            const json = await resp.json();

            if (!json || !json.success) {
                return;
            }

            const items = Array.isArray(json.items) ? json.items : [];

            if (tipo === 'departamentos') {
                limpiarOpciones(ieDepartamento, 'Todos', false);
                agregarOpciones(ieDepartamento, items);
            }

            if (tipo === 'provincias') {
                limpiarOpciones(ieProvincia, 'Todas', items.length === 0);
                agregarOpciones(ieProvincia, items);
            }

            if (tipo === 'distritos') {
                limpiarOpciones(ieDistrito, 'Todos', items.length === 0);
                agregarOpciones(ieDistrito, items);
            }
        } catch (error) {
            return;
        }
    }

    function ocultarResultadosIE() {
        if (!ieResultados) return;
        ieResultados.style.display = 'none';
        ieResultados.innerHTML = '';
    }

    function escapeHtml(texto) {
        return String(texto || '')
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#039;');
    }
    function nivelPillClass(nivel) {
        const texto = String(nivel || '').toUpperCase();

        if (texto.indexOf('INICIAL') !== -1) return 'pill-inicial';
        if (texto.indexOf('PRIMARIA') !== -1) return 'pill-primaria';
        if (texto.indexOf('SECUNDARIA') !== -1) return 'pill-secundaria';

        return 'pill-red';
    }

    function ubigeoTexto(item) {
        return [item.departamento || '', item.provincia || '', item.distrito || '']
            .filter(Boolean)
            .join(' / ');
    }


    function mostrarSeleccionIE(item) {
        if (!ieSeleccionada) return;

        const nivel = nivelBase(item.nivel_base || item.nivel_modalidad || '');
        const codigo = String(item.codigo_modular || '');
        const nivelClass = nivelPillClass(nivel);
        const ubigeo = ubigeoTexto(item);

        ieSeleccionada.innerHTML =
            '<div style="display:flex;align-items:center;gap:8px;font-weight:900;margin-bottom:8px;"><i class="bi bi-check-circle-fill" style="color:#dc2626;"></i><span>' + escapeHtml(item.nombre_institucion) + '</span></div>' +
            '<span class="pill ' + nivelClass + '"><i class="fa-solid fa-layer-group"></i> ' + escapeHtml(nivel) + '</span> ' +
            '<span class="pill pill-modular"><i class="fa-solid fa-barcode"></i> ' + escapeHtml(codigo) + '</span> ' +
            (ubigeo ? '<span class="pill pill-ubigeo"><i class="fa-solid fa-location-dot"></i> ' + escapeHtml(ubigeo) + '</span>' : '');

        ieSeleccionada.style.display = 'block';
    }

    function limpiarSeleccionIE() {
        if (idInstitucionCatalogo) {
            idInstitucionCatalogo.value = '';
        }

        if (codigoModularIeHidden) {
            codigoModularIeHidden.value = '';
        }

        if (nivelModalidadIeHidden) {
            nivelModalidadIeHidden.value = '';
        }

        if (ieSeleccionada) {
            ieSeleccionada.textContent = '';
            ieSeleccionada.style.display = 'none';
        }
    }

    function renderResultadosIE(items, mensaje) {
        if (!ieResultados) return;

        ieResultados.innerHTML = '';

        if (!items.length) {
            const empty = document.createElement('button');
            empty.type = 'button';
            empty.className = 'ie-result-item';
            empty.innerHTML = '<strong>Sin resultados</strong><span class="ie-result-small">' + escapeHtml(mensaje || 'Prueba con otro nombre o cambia los filtros.') + '</span>';
            empty.addEventListener('click', function () {
                ocultarResultadosIE();
            });
            ieResultados.appendChild(empty);
            ieResultados.style.display = 'block';
            return;
        }

        items.forEach(function (item) {
            const btn = document.createElement('button');
            btn.type = 'button';
            btn.className = 'ie-result-item';

            const nivel = nivelBase(item.nivel_base || item.nivel_modalidad || '');
            const nivelClass = nivelPillClass(nivel);
            const ubigeo = ubigeoTexto(item);

            btn.innerHTML =
                '<span class="ie-result-main">' +
                    '<i class="fa-solid fa-school"></i> ' +
                    escapeHtml(item.nombre_institucion) +
                '</span>' +
                '<span class="ie-result-level">' +
                    '<span class="pill ' + nivelClass + '"><i class="fa-solid fa-layer-group"></i> ' + escapeHtml(nivel) + '</span>' +
                    '<span class="pill pill-modular"><i class="fa-solid fa-barcode"></i> ' + escapeHtml(item.codigo_modular || '') + '</span>' +
                    '<span class="pill pill-ubigeo"><i class="fa-solid fa-location-dot"></i> ' + escapeHtml(ubigeo) + '</span>' +
                '</span>';

            btn.addEventListener('click', function () {
                if (ie) {
                    ie.value = String(item.nombre_institucion || '').toUpperCase();
                    ie.classList.remove('field-bad');
                    ie.classList.add('field-ok');
                }

                if (tipoInstitucion && item.gestion) {
                    tipoInstitucion.value = item.gestion;
                }

                if (idInstitucionCatalogo) {
                    idInstitucionCatalogo.value = item.id_institucion || '';
                }

                if (codigoModularIeHidden) {
                    codigoModularIeHidden.value = item.codigo_modular || '';
                }

                if (nivelModalidadIeHidden) {
                    nivelModalidadIeHidden.value = nivel;
                }

                mostrarSeleccionIE(item);
                ocultarResultadosIE();
            });

            ieResultados.appendChild(btn);
        });

        ieResultados.style.display = 'block';
    }

    async function buscarIE() {
        if (!ie || !tipoInstitucion) return;

        const q = ie.value.trim();
        const gestion = tipoInstitucion.value;
        const departamento = ieDepartamento ? ieDepartamento.value : '';
        const provincia = ieProvincia ? ieProvincia.value : '';
        const distrito = ieDistrito ? ieDistrito.value : '';

        if (q.length < 2) {
            ocultarResultadosIE();
            return;
        }

        if (ieAbort) {
            ieAbort.abort();
        }

        ieAbort = new AbortController();

        const params = new URLSearchParams();
        params.set('ajax', 'buscar_ie');
        params.set('q', q);
        params.set('gestion', gestion);

        if (departamento) params.set('departamento', departamento);
        if (provincia) params.set('provincia', provincia);
        if (distrito) params.set('distrito', distrito);

        try {
            const resp = await fetch('participantes.php?' + params.toString(), {
                headers: { 'Accept': 'application/json' },
                signal: ieAbort.signal
            });

            const json = await resp.json();

            if (!json || !json.success) {
                renderResultadosIE([], json && json.message ? json.message : 'No se pudo buscar instituciones.');
                return;
            }

            renderResultadosIE(Array.isArray(json.items) ? json.items : [], json.message || '');
        } catch (error) {
            if (error.name === 'AbortError') {
                return;
            }

            renderResultadosIE([], 'No se pudo consultar el catálogo de instituciones.');
        }
    }

    function programarBusquedaIE() {
        if (ieTimer) {
            clearTimeout(ieTimer);
        }

        ieTimer = setTimeout(function () {
            buscarIE();
        }, 320);
    }

    function dividirNombreCompleto(texto) {
        const limpio = String(texto || '').trim().replace(/\s+/g, ' ');
        const partes = limpio ? limpio.split(' ') : [];

        if (partes.length >= 3) {
            return {
                apellido_paterno: partes[0] || '',
                apellido_materno: partes[1] || '',
                nombres: partes.slice(2).join(' ')
            };
        }

        return {
            apellido_paterno: partes[0] || '',
            apellido_materno: partes[1] || '',
            nombres: partes.slice(2).join(' ')
        };
    }

    function cargarDatosPersona(data) {
        data = data || {};

        let apP = data.apellido_paterno || data.apellidoPaterno || data.ape_paterno || '';
        let apM = data.apellido_materno || data.apellidoMaterno || data.ape_materno || '';
        let nom = data.nombres || '';

        if ((!apP || !apM || !nom) && (data.nombre_completo || data.nombreCompleto || data.apellidos_nombres)) {
            const separado = dividirNombreCompleto(data.nombre_completo || data.nombreCompleto || data.apellidos_nombres);

            if (!apP) apP = separado.apellido_paterno;
            if (!apM) apM = separado.apellido_materno;
            if (!nom) nom = separado.nombres;
        }

        if (apellidoPaterno) {
            apellidoPaterno.value = String(apP || '').toUpperCase();
        }

        if (apellidoMaterno) {
            apellidoMaterno.value = String(apM || '').toUpperCase();
        }

        if (nombres) {
            nombres.value = String(nom || '').toUpperCase();
        }
    }

    upperInput(apellidoPaterno);
    upperInput(apellidoMaterno);
    upperInput(nombres);
    upperInput(ie);

    if (tipoInstitucion) {
        tipoInstitucion.addEventListener('change', function () {
            if (ie) {
                ie.value = '';
                ie.classList.remove('field-ok', 'field-bad');
            }

            limpiarSeleccionIE();
            ocultarResultadosIE();
            limpiarOpciones(ieProvincia, 'Todas', true);
            limpiarOpciones(ieDistrito, 'Todos', true);
            cargarUbicaciones('departamentos');
        });
    }

    if (ieDepartamento) {
        ieDepartamento.addEventListener('change', function () {
            limpiarOpciones(ieProvincia, 'Todas', !ieDepartamento.value);
            limpiarOpciones(ieDistrito, 'Todos', true);
            limpiarSeleccionIE();

            if (ieDepartamento.value) {
                cargarUbicaciones('provincias');
            }

            programarBusquedaIE();
        });
    }

    if (ieProvincia) {
        ieProvincia.addEventListener('change', function () {
            limpiarOpciones(ieDistrito, 'Todos', !ieProvincia.value);
            limpiarSeleccionIE();

            if (ieProvincia.value) {
                cargarUbicaciones('distritos');
            }

            programarBusquedaIE();
        });
    }

    if (ieDistrito) {
        ieDistrito.addEventListener('change', function () {
            limpiarSeleccionIE();
            programarBusquedaIE();
        });
    }

    if (ie) {
        ie.addEventListener('input', function () {
            ie.value = ie.value.toUpperCase();
            ie.classList.remove('field-ok', 'field-bad');
            limpiarSeleccionIE();
            programarBusquedaIE();
        });

        ie.addEventListener('focus', function () {
            if (ie.value.trim().length >= 2) {
                programarBusquedaIE();
            }
        });
    }

    document.addEventListener('click', function (event) {
        if (!ieResultados || !ie) return;

        const target = event.target;

        if (target === ie || ieResultados.contains(target)) {
            return;
        }

        ocultarResultadosIE();
    });

    cargarUbicaciones('departamentos');

    if (frmParticipante) {
        frmParticipante.addEventListener('submit', function (event) {
            if (!idInstitucionCatalogo || !idInstitucionCatalogo.value || !codigoModularIeHidden || !codigoModularIeHidden.value) {
                event.preventDefault();

                if (ie) {
                    ie.classList.add('field-bad');
                    ie.focus();
                }

                mostrarAviso('Selecciona la I.E. exacta desde el catálogo.', 'error');
                return;
            }

            if (!nivelModalidadIeHidden || !nivelModalidadIeHidden.value) {
                event.preventDefault();
                mostrarAviso('El código modular no tiene nivel asignado.', 'error');
                return;
            }

            if (!frmParticipante.dataset.confirmado) {
                event.preventDefault();

                Swal.fire({
                    icon: 'question',
                    title: '¿Registrar participante?',
                    text: documento && documento.value.trim() === '' ? 'No ingresaste DNI. El sistema generará un código alfanumérico automático de 8 caracteres.' : 'Se guardará como pre-registro del concurso y se vinculará al padrón general si tiene DNI.',
                    showCancelButton: true,
                    confirmButtonText: 'Sí, registrar',
                    cancelButtonText: 'Cancelar',
                    confirmButtonColor: '#dc2626',
                    cancelButtonColor: '#64748b'
                }).then(function (result) {
                    if (result.isConfirmed) {
                        frmParticipante.dataset.confirmado = '1';

                        if (btnGuardar) {
                            btnGuardar.disabled = true;
                            btnGuardar.innerHTML = '<i class="fa-solid fa-spinner fa-spin"></i> Guardando...';
                        }

                        frmParticipante.submit();
                    }
                });
            }
        });
    }

    if (documento) {
        documento.addEventListener('input', function () {
            documento.value = documento.value.replace(/\D/g, '').slice(0, 8);
            documento.classList.remove('field-ok', 'field-bad');
            if (btnGuardar) btnGuardar.disabled = false;
            mostrarAviso('', '');
        });

        documento.addEventListener('blur', async function () {
            const dni = documento.value.trim();

            if (dni === '') {
                return;
            }

            if (!/^\d{8}$/.test(dni)) {
                documento.classList.add('field-bad');
                mostrarAviso('El DNI debe tener 8 dígitos.', 'error');
                return;
            }

            if (dniAbort) {
                dniAbort.abort();
            }

            dniAbort = new AbortController();

            try {
                if (spin) spin.style.display = 'inline-block';

                const idConcurso = idConcursoActual ? idConcursoActual.value : '';
                const params = new URLSearchParams();
                params.set('ajax', 'buscar_documento');
                params.set('id_concurso', idConcurso);
                params.set('documento', dni);

                const resp = await fetch('participantes.php?' + params.toString(), {
                    headers: { 'Accept': 'application/json' },
                    signal: dniAbort.signal
                });

                const json = await resp.json();

                if (!json || !json.success) {
                    documento.classList.add('field-bad');
                    if (btnGuardar) btnGuardar.disabled = false;
                    mostrarAviso(json && json.message ? json.message : 'No se pudo consultar el DNI.', 'warn');
                    return;
                }

                const data = json.data || {};

                if (json.exists) {
                    documento.classList.remove('field-ok');
                    documento.classList.add('field-bad');

                    cargarDatosPersona(data);

                    if (ie && data.institucion_educativa) {
                        ie.value = String(data.institucion_educativa).toUpperCase();
                    }

                    if (tipoInstitucion && data.tipo_institucion) {
                        tipoInstitucion.value = String(data.tipo_institucion).toUpperCase();
                    }

                    if (btnGuardar) {
                        btnGuardar.disabled = true;
                    }

                    mostrarAviso(json.message || 'Este DNI ya está registrado en este concurso.', 'error');
                    return;
                }

                if (json.found) {
                    cargarDatosPersona(data);

                    documento.classList.remove('field-bad');
                    documento.classList.add('field-ok');

                    if (btnGuardar) {
                        btnGuardar.disabled = false;
                    }

                    const origen = String(json.origen || '').toUpperCase();
                    const msg = origen === 'PERSONAS_GENERAL'
                        ? 'DNI encontrado en padrón general local. Datos cargados automáticamente.'
                        : 'DNI encontrado por API RENIEC y guardado en padrón general.';

                    mostrarAviso(msg, 'ok');
                    return;
                }

                documento.classList.add('field-bad');

                if (btnGuardar) {
                    btnGuardar.disabled = false;
                }

                mostrarAviso(json.message || 'No se encontró el DNI. Puedes completar manualmente.', 'warn');
            } catch (error) {
                if (error.name === 'AbortError') {
                    return;
                }

                documento.classList.add('field-bad');

                if (btnGuardar) {
                    btnGuardar.disabled = false;
                }

                mostrarAviso('No se pudo consultar el DNI. Puedes completar manualmente.', 'warn');
            } finally {
                if (spin) spin.style.display = 'none';
            }
        });
    }

    if (buscarParticipante && tablaParticipantes) {
        buscarParticipante.addEventListener('input', function () {
            const q = String(buscarParticipante.value || '').toUpperCase().trim();
            const filas = tablaParticipantes.querySelectorAll('tbody tr');

            filas.forEach(function (fila) {
                const texto = String(fila.textContent || '').toUpperCase();
                fila.style.display = texto.indexOf(q) !== -1 ? '' : 'none';
            });
        });
    }
});
</script>

</body>
</html>
