<?php
// concurso_nobel/publicacion_resultados.php
// VERSION PUBLICACION CONTROLADA + EXCLUSION DE SALONES/I.E. + RECALCULO DE PUESTOS
// Control administrativo para decidir qué resultados salen o no salen en el ranking público.
// No elimina participantes ni notas; solo marca concurso_resultados.publicar_resultado = 1/0.
// Además permite excluir salones e instituciones educativas completas del ranking y recalcular puestos nuevamente.

declare(strict_types=1);

session_start();
require_once __DIR__ . '/includes/db.php';
require_once __DIR__ . '/includes/concurso_contexto.php';
date_default_timezone_set('America/Lima');

function pr_h($v): string { return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); }
function pr_post(string $k, string $d=''): string { return trim((string)($_POST[$k] ?? $d)); }
function pr_get(string $k, string $d=''): string { return trim((string)($_GET[$k] ?? $d)); }

function pr_table_exists(mysqli $conn, string $t): bool {
    $t = mysqli_real_escape_string($conn, $t);
    $rs = @mysqli_query($conn, "SHOW TABLES LIKE '{$t}'");
    return $rs instanceof mysqli_result && mysqli_num_rows($rs) > 0;
}

function pr_col_exists(mysqli $conn, string $t, string $c): bool {
    $t = mysqli_real_escape_string($conn, $t);
    $c = mysqli_real_escape_string($conn, $c);
    $rs = @mysqli_query($conn, "SHOW COLUMNS FROM `{$t}` LIKE '{$c}'");
    return $rs instanceof mysqli_result && mysqli_num_rows($rs) > 0;
}

function pr_ensure_schema(mysqli $conn): void {
    if (!pr_table_exists($conn, 'concurso_resultados')) {
        throw new RuntimeException('No existe la tabla concurso_resultados.');
    }

    if (!pr_col_exists($conn, 'concurso_resultados', 'publicar_resultado')) {
        $ok = @mysqli_query($conn, "ALTER TABLE concurso_resultados ADD COLUMN publicar_resultado TINYINT(1) NOT NULL DEFAULT 1 COMMENT '1 sale en resultados, 0 oculto por administración'");
        if (!$ok) throw new RuntimeException('No se pudo crear publicar_resultado: ' . mysqli_error($conn));
    }

    if (!pr_col_exists($conn, 'concurso_resultados', 'motivo_no_publicar')) {
        $ok = @mysqli_query($conn, "ALTER TABLE concurso_resultados ADD COLUMN motivo_no_publicar VARCHAR(255) NULL COMMENT 'Motivo para ocultar resultado'");
        if (!$ok) throw new RuntimeException('No se pudo crear motivo_no_publicar: ' . mysqli_error($conn));
    }

    if (pr_table_exists($conn, 'concurso_salones')) {
        if (!pr_col_exists($conn, 'concurso_salones', 'excluir_ranking')) {
            $ok = @mysqli_query($conn, "ALTER TABLE concurso_salones ADD COLUMN excluir_ranking TINYINT(1) NOT NULL DEFAULT 0 COMMENT '1 excluye todo el salón del ranking público'");
            if (!$ok) throw new RuntimeException('No se pudo crear excluir_ranking en concurso_salones: ' . mysqli_error($conn));
        }
        if (!pr_col_exists($conn, 'concurso_salones', 'motivo_exclusion_ranking')) {
            $ok = @mysqli_query($conn, "ALTER TABLE concurso_salones ADD COLUMN motivo_exclusion_ranking VARCHAR(255) NULL COMMENT 'Motivo para excluir el salón del ranking'");
            if (!$ok) throw new RuntimeException('No se pudo crear motivo_exclusion_ranking en concurso_salones: ' . mysqli_error($conn));
        }
    }

    $ok = @mysqli_query($conn, "
        CREATE TABLE IF NOT EXISTS concurso_ie_exclusiones (
            id_ie_exclusion INT AUTO_INCREMENT PRIMARY KEY,
            id_concurso INT NOT NULL,
            institucion_educativa VARCHAR(255) NOT NULL,
            excluir_ranking TINYINT(1) NOT NULL DEFAULT 1,
            motivo_exclusion_ie VARCHAR(255) NULL,
            created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME NULL DEFAULT NULL,
            UNIQUE KEY uq_concurso_ie (id_concurso, institucion_educativa(190)),
            KEY idx_concurso_ie (id_concurso)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
    ");
    if (!$ok) throw new RuntimeException('No se pudo crear concurso_ie_exclusiones: ' . mysqli_error($conn));
}

function pr_grupos(mysqli $conn, int $idConcurso): array {
    $out = [];
    $st = mysqli_prepare($conn, "SELECT id_grupo,nombre,nivel FROM concurso_grupos WHERE id_concurso=? AND estado=1 ORDER BY id_grupo ASC,nombre ASC");
    if (!$st) return $out;
    mysqli_stmt_bind_param($st, 'i', $idConcurso);
    mysqli_stmt_execute($st);
    $rs = mysqli_stmt_get_result($st);
    while ($rs && ($r = mysqli_fetch_assoc($rs))) $out[] = $r;
    mysqli_stmt_close($st);
    return $out;
}

function pr_stats(mysqli $conn, int $idConcurso): array {
    $out = ['total'=>0,'publicados'=>0,'ocultos'=>0,'salones_excluidos'=>0,'ies_excluidas'=>0];

    $st = mysqli_prepare($conn, "
        SELECT
            COUNT(*) total,
            SUM(CASE WHEN r.publicar_resultado=1 THEN 1 ELSE 0 END) publicados,
            SUM(CASE WHEN r.publicar_resultado=0 THEN 1 ELSE 0 END) ocultos,
            COUNT(DISTINCT CASE WHEN COALESCE(s.excluir_ranking,0)=1 THEN r.id_salon END) salones_excluidos,
            COUNT(DISTINCT CASE WHEN COALESCE(iex.excluir_ranking,0)=1 THEN TRIM(p.institucion_educativa) END) ies_excluidas
        FROM concurso_resultados r
        INNER JOIN concurso_participantes p ON p.id_participante=r.id_participante
        LEFT JOIN concurso_salones s ON s.id_salon=r.id_salon
        LEFT JOIN concurso_ie_exclusiones iex
               ON iex.id_concurso=r.id_concurso
              AND LOWER(TRIM(iex.institucion_educativa))=LOWER(TRIM(p.institucion_educativa))
              AND iex.excluir_ranking=1
        WHERE r.id_concurso=? AND r.estado='ACTIVO' AND p.estado='ACTIVO'
    ");
    if (!$st) return $out;
    mysqli_stmt_bind_param($st, 'i', $idConcurso);
    mysqli_stmt_execute($st);
    $rs = mysqli_stmt_get_result($st);
    $r = $rs ? mysqli_fetch_assoc($rs) : null;
    mysqli_stmt_close($st);
    if ($r) {
        $out['total'] = (int)$r['total'];
        $out['publicados'] = (int)$r['publicados'];
        $out['ocultos'] = (int)$r['ocultos'];
        $out['salones_excluidos'] = (int)$r['salones_excluidos'];
        $out['ies_excluidas'] = (int)$r['ies_excluidas'];
    }
    return $out;
}

function pr_salones(mysqli $conn, int $idConcurso, int $idGrupo = 0): array {
    $out = [];
    if (!pr_table_exists($conn, 'concurso_salones')) return $out;

    $sql = "
        SELECT
            r.id_salon,
            COALESCE(s.nombre_salon, CONCAT('Salón ', r.id_salon)) AS nombre_salon,
            r.id_grupo,
            COALESCE(g.nombre,'Sin grupo') AS grupo_nombre,
            COALESCE(g.nivel,'') AS nivel,
            COALESCE(s.excluir_ranking,0) AS excluir_ranking,
            COALESCE(s.motivo_exclusion_ranking,'') AS motivo_exclusion_ranking,
            COUNT(*) AS total_calificados,
            SUM(CASE WHEN r.publicar_resultado=1 THEN 1 ELSE 0 END) AS visibles,
            SUM(CASE WHEN r.publicar_resultado=0 THEN 1 ELSE 0 END) AS ocultos
        FROM concurso_resultados r
        INNER JOIN concurso_participantes p ON p.id_participante=r.id_participante
        LEFT JOIN concurso_salones s ON s.id_salon=r.id_salon
        LEFT JOIN concurso_grupos g ON g.id_grupo=r.id_grupo
        WHERE r.id_concurso=?
          AND r.estado='ACTIVO'
          AND p.estado='ACTIVO'
          AND r.id_salon IS NOT NULL
          AND r.id_salon > 0
    ";

    $types = 'i';
    $params = [$idConcurso];
    if ($idGrupo > 0) {
        $sql .= " AND r.id_grupo=?";
        $types .= 'i';
        $params[] = $idGrupo;
    }

    $sql .= "
        GROUP BY r.id_salon, s.nombre_salon, r.id_grupo, g.nombre, g.nivel, s.excluir_ranking, s.motivo_exclusion_ranking
        ORDER BY g.id_grupo ASC, s.nombre_salon ASC, r.id_salon ASC
    ";

    $st = mysqli_prepare($conn, $sql);
    if (!$st) return $out;
    $refs = [$st, $types];
    foreach ($params as $k => $v) $refs[] = &$params[$k];
    call_user_func_array('mysqli_stmt_bind_param', $refs);
    mysqli_stmt_execute($st);
    $rs = mysqli_stmt_get_result($st);
    while ($rs && ($r = mysqli_fetch_assoc($rs))) $out[] = $r;
    mysqli_stmt_close($st);
    return $out;
}

function pr_instituciones(mysqli $conn, int $idConcurso, int $idGrupo = 0, string $q = ''): array {
    $out = [];

    $sql = "
        SELECT
            TRIM(p.institucion_educativa) AS institucion_educativa,
            COALESCE(MAX(iex.excluir_ranking),0) AS excluir_ranking,
            COALESCE(MAX(iex.motivo_exclusion_ie),'') AS motivo_exclusion_ie,
            COUNT(*) AS total_calificados,
            SUM(CASE WHEN r.publicar_resultado=1 THEN 1 ELSE 0 END) AS visibles,
            SUM(CASE WHEN r.publicar_resultado=0 THEN 1 ELSE 0 END) AS ocultos,
            COUNT(DISTINCT r.id_grupo) AS grupos_count,
            COUNT(DISTINCT r.id_salon) AS salones_count
        FROM concurso_resultados r
        INNER JOIN concurso_participantes p ON p.id_participante=r.id_participante
        LEFT JOIN concurso_ie_exclusiones iex
               ON iex.id_concurso=r.id_concurso
              AND LOWER(TRIM(iex.institucion_educativa))=LOWER(TRIM(p.institucion_educativa))
        WHERE r.id_concurso=?
          AND r.estado='ACTIVO'
          AND p.estado='ACTIVO'
          AND TRIM(COALESCE(p.institucion_educativa,''))<>''
    ";

    $types = 'i';
    $params = [$idConcurso];
    if ($idGrupo > 0) { $sql .= " AND r.id_grupo=?"; $types .= 'i'; $params[] = $idGrupo; }
    if ($q !== '') { $sql .= " AND p.institucion_educativa LIKE CONCAT('%',?,'%')"; $types .= 's'; $params[] = $q; }

    $sql .= "
        GROUP BY TRIM(p.institucion_educativa)
        ORDER BY COALESCE(MAX(iex.excluir_ranking),0) DESC, TRIM(p.institucion_educativa) ASC
        LIMIT 300
    ";

    $st = mysqli_prepare($conn, $sql);
    if (!$st) return $out;
    $refs = [$st, $types];
    foreach ($params as $k => $v) $refs[] = &$params[$k];
    call_user_func_array('mysqli_stmt_bind_param', $refs);
    mysqli_stmt_execute($st);
    $rs = mysqli_stmt_get_result($st);
    while ($rs && ($r = mysqli_fetch_assoc($rs))) $out[] = $r;
    mysqli_stmt_close($st);
    return $out;
}

function pr_listar(mysqli $conn, int $idConcurso, int $idGrupo, int $idSalon, string $estado, string $q): array {
    $sql = "
        SELECT
            r.id_resultado,r.id_concurso,r.id_grupo,r.id_salon,r.id_participante,
            r.correctas,r.incorrectas,r.blanco,r.puntaje,r.tiempo_texto,r.puesto,
            r.publicar_resultado,r.motivo_no_publicar,
            p.documento,p.codigo_participante,p.apellidos_nombres,p.institucion_educativa,p.tipo_institucion,
            g.nombre grupo_nombre,
            s.nombre_salon,
            COALESCE(s.excluir_ranking,0) AS salon_excluido,
            COALESCE(s.motivo_exclusion_ranking,'') AS motivo_salon_excluido,
            COALESCE(iex.excluir_ranking,0) AS ie_excluida,
            COALESCE(iex.motivo_exclusion_ie,'') AS motivo_ie_excluida
        FROM concurso_resultados r
        INNER JOIN concurso_participantes p ON p.id_participante=r.id_participante
        LEFT JOIN concurso_grupos g ON g.id_grupo=r.id_grupo
        LEFT JOIN concurso_salones s ON s.id_salon=r.id_salon
        LEFT JOIN concurso_ie_exclusiones iex
               ON iex.id_concurso=r.id_concurso
              AND LOWER(TRIM(iex.institucion_educativa))=LOWER(TRIM(p.institucion_educativa))
              AND iex.excluir_ranking=1
        WHERE r.id_concurso=? AND r.estado='ACTIVO' AND p.estado='ACTIVO'
    ";

    $types = 'i';
    $params = [$idConcurso];

    if ($idGrupo > 0) {
        $sql .= " AND r.id_grupo=?";
        $types .= 'i';
        $params[] = $idGrupo;
    }

    if ($idSalon > 0) {
        $sql .= " AND r.id_salon=?";
        $types .= 'i';
        $params[] = $idSalon;
    }

    if ($estado === 'publicados') $sql .= " AND r.publicar_resultado=1 AND COALESCE(s.excluir_ranking,0)=0 AND COALESCE(iex.excluir_ranking,0)=0";
    if ($estado === 'ocultos') $sql .= " AND (r.publicar_resultado=0 OR COALESCE(s.excluir_ranking,0)=1 OR COALESCE(iex.excluir_ranking,0)=1)";

    if ($q !== '') {
        $sql .= " AND (p.documento LIKE CONCAT('%',?,'%') OR p.codigo_participante LIKE CONCAT('%',?,'%') OR p.apellidos_nombres LIKE CONCAT('%',?,'%') OR p.institucion_educativa LIKE CONCAT('%',?,'%'))";
        $types .= 'ssss';
        array_push($params, $q, $q, $q, $q);
    }

    $sql .= "
        ORDER BY
            g.id_grupo ASC,
            p.tipo_institucion ASC,
            COALESCE(s.excluir_ranking,0) ASC,
            COALESCE(iex.excluir_ranking,0) ASC,
            r.publicar_resultado DESC,
            r.puntaje DESC,
            (r.tiempo_segundos IS NULL) ASC,
            r.tiempo_segundos ASC,
            r.correctas DESC,
            r.incorrectas ASC,
            p.apellidos_nombres ASC
        LIMIT 800
    ";

    $st = mysqli_prepare($conn, $sql);
    $out = [];
    if (!$st) return $out;
    $refs = [$st, $types];
    foreach ($params as $k => $v) $refs[] = &$params[$k];
    call_user_func_array('mysqli_stmt_bind_param', $refs);
    mysqli_stmt_execute($st);
    $rs = mysqli_stmt_get_result($st);
    while ($rs && ($r = mysqli_fetch_assoc($rs))) $out[] = $r;
    mysqli_stmt_close($st);
    return $out;
}

function pr_contexto(mysqli $conn, int $idConcurso, int $idResultado): ?array {
    $st = mysqli_prepare($conn, "
        SELECT
            r.id_resultado,r.id_grupo,r.id_salon,r.id_participante,r.publicar_resultado,
            COALESCE(s.excluir_ranking,0) AS salon_excluido,
            COALESCE(iex.excluir_ranking,0) AS ie_excluida,
            p.apellidos_nombres,p.documento,p.tipo_institucion,p.institucion_educativa
        FROM concurso_resultados r
        INNER JOIN concurso_participantes p ON p.id_participante=r.id_participante
        LEFT JOIN concurso_salones s ON s.id_salon=r.id_salon
        LEFT JOIN concurso_ie_exclusiones iex
               ON iex.id_concurso=r.id_concurso
              AND LOWER(TRIM(iex.institucion_educativa))=LOWER(TRIM(p.institucion_educativa))
              AND iex.excluir_ranking=1
        WHERE r.id_concurso=? AND r.id_resultado=? AND r.estado='ACTIVO' AND p.estado='ACTIVO'
        LIMIT 1
    ");
    if (!$st) return null;
    mysqli_stmt_bind_param($st, 'ii', $idConcurso, $idResultado);
    mysqli_stmt_execute($st);
    $rs = mysqli_stmt_get_result($st);
    $row = $rs ? mysqli_fetch_assoc($rs) : null;
    mysqli_stmt_close($st);
    return $row ?: null;
}

function pr_grupos_a_recalcular(mysqli $conn, int $idConcurso, int $idGrupoFiltro = 0): array {
    $out = [];
    if ($idGrupoFiltro > 0) return [$idGrupoFiltro];

    $st = mysqli_prepare($conn, "
        SELECT DISTINCT id_grupo
        FROM concurso_resultados
        WHERE id_concurso=? AND estado='ACTIVO' AND id_grupo IS NOT NULL AND id_grupo > 0
        ORDER BY id_grupo ASC
    ");
    if (!$st) return $out;
    mysqli_stmt_bind_param($st, 'i', $idConcurso);
    mysqli_stmt_execute($st);
    $rs = mysqli_stmt_get_result($st);
    while ($rs && ($r = mysqli_fetch_assoc($rs))) $out[] = (int)$r['id_grupo'];
    mysqli_stmt_close($st);
    return $out;
}

function pr_grupos_por_salon(mysqli $conn, int $idConcurso, int $idSalon): array {
    $out = [];
    $st = mysqli_prepare($conn, "
        SELECT DISTINCT id_grupo
        FROM concurso_resultados
        WHERE id_concurso=? AND id_salon=? AND estado='ACTIVO' AND id_grupo IS NOT NULL AND id_grupo > 0
    ");
    if (!$st) return $out;
    mysqli_stmt_bind_param($st, 'ii', $idConcurso, $idSalon);
    mysqli_stmt_execute($st);
    $rs = mysqli_stmt_get_result($st);
    while ($rs && ($r = mysqli_fetch_assoc($rs))) $out[] = (int)$r['id_grupo'];
    mysqli_stmt_close($st);
    return $out;
}

function pr_grupos_por_ie(mysqli $conn, int $idConcurso, string $institucion): array {
    $out = [];
    $institucion = trim($institucion);
    if ($institucion === '') return $out;
    $st = mysqli_prepare($conn, "
        SELECT DISTINCT r.id_grupo
        FROM concurso_resultados r
        INNER JOIN concurso_participantes p ON p.id_participante=r.id_participante
        WHERE r.id_concurso=?
          AND r.estado='ACTIVO'
          AND p.estado='ACTIVO'
          AND LOWER(TRIM(p.institucion_educativa))=LOWER(TRIM(?))
          AND r.id_grupo IS NOT NULL
          AND r.id_grupo > 0
    ");
    if (!$st) return $out;
    mysqli_stmt_bind_param($st, 'is', $idConcurso, $institucion);
    mysqli_stmt_execute($st);
    $rs = mysqli_stmt_get_result($st);
    while ($rs && ($r = mysqli_fetch_assoc($rs))) $out[] = (int)$r['id_grupo'];
    mysqli_stmt_close($st);
    return $out;
}

function pr_recalcular_categoria(mysqli $conn, int $idConcurso, int $idGrupo, string $tipo): void {
    if ($idConcurso <= 0 || $idGrupo <= 0 || !in_array($tipo, ['PUBLICA','PRIVADA'], true)) return;

    if (pr_col_exists($conn, 'concurso_resultados', 'puesto')) {
        $clear = mysqli_prepare($conn, "
            UPDATE concurso_resultados r
            INNER JOIN concurso_participantes p ON p.id_participante=r.id_participante
            SET r.puesto=NULL
            WHERE r.id_concurso=?
              AND r.id_grupo=?
              AND r.estado='ACTIVO'
              AND p.estado='ACTIVO'
              AND p.tipo_institucion=?
        ");
        if ($clear) {
            mysqli_stmt_bind_param($clear, 'iis', $idConcurso, $idGrupo, $tipo);
            mysqli_stmt_execute($clear);
            mysqli_stmt_close($clear);
        }
    }

    $st = mysqli_prepare($conn, "
        SELECT r.id_resultado
        FROM concurso_resultados r
        INNER JOIN concurso_participantes p ON p.id_participante=r.id_participante
        LEFT JOIN concurso_salones s ON s.id_salon=r.id_salon
        LEFT JOIN concurso_ie_exclusiones iex
               ON iex.id_concurso=r.id_concurso
              AND LOWER(TRIM(iex.institucion_educativa))=LOWER(TRIM(p.institucion_educativa))
              AND iex.excluir_ranking=1
        WHERE r.id_concurso=?
          AND r.id_grupo=?
          AND r.estado='ACTIVO'
          AND r.publicar_resultado=1
          AND COALESCE(s.excluir_ranking,0)=0
          AND COALESCE(iex.excluir_ranking,0)=0
          AND p.estado='ACTIVO'
          AND p.tipo_institucion=?
        ORDER BY
          r.puntaje DESC,
          (r.tiempo_segundos IS NULL) ASC,
          r.tiempo_segundos ASC,
          r.correctas DESC,
          r.incorrectas ASC,
          r.id_resultado ASC
    ");
    if (!$st) return;

    mysqli_stmt_bind_param($st, 'iis', $idConcurso, $idGrupo, $tipo);
    mysqli_stmt_execute($st);
    $rs = mysqli_stmt_get_result($st);
    $puesto = 1;
    while ($rs && ($r = mysqli_fetch_assoc($rs))) {
        $id = (int)$r['id_resultado'];
        $up = mysqli_prepare($conn, "UPDATE concurso_resultados SET puesto=? WHERE id_resultado=? LIMIT 1");
        if ($up) {
            mysqli_stmt_bind_param($up, 'ii', $puesto, $id);
            mysqli_stmt_execute($up);
            mysqli_stmt_close($up);
        }
        $puesto++;
    }
    mysqli_stmt_close($st);
}

function pr_recalcular_grupo(mysqli $conn, int $idConcurso, int $idGrupo): void {
    pr_recalcular_categoria($conn, $idConcurso, $idGrupo, 'PRIVADA');
    pr_recalcular_categoria($conn, $idConcurso, $idGrupo, 'PUBLICA');
}

function pr_recalcular_varios(mysqli $conn, int $idConcurso, array $grupos): int {
    $grupos = array_values(array_unique(array_filter(array_map('intval', $grupos), fn($v) => $v > 0)));
    foreach ($grupos as $g) pr_recalcular_grupo($conn, $idConcurso, $g);
    return count($grupos);
}

function pr_forzar_exclusion_salones(mysqli $conn, int $idConcurso): void {
    if (!pr_table_exists($conn, 'concurso_salones') || !pr_col_exists($conn, 'concurso_salones', 'excluir_ranking')) return;

    $sqlUpdated = pr_col_exists($conn, 'concurso_resultados', 'updated_at') ? ", r.updated_at=NOW()" : "";
    $st = mysqli_prepare($conn, "
        UPDATE concurso_resultados r
        INNER JOIN concurso_salones s ON s.id_salon=r.id_salon
        SET
            r.publicar_resultado=0,
            r.motivo_no_publicar=CASE
                WHEN COALESCE(s.motivo_exclusion_ranking,'')<>'' THEN CONCAT('SALÓN EXCLUIDO: ', s.motivo_exclusion_ranking)
                ELSE 'SALÓN EXCLUIDO POR ADMINISTRADOR'
            END,
            r.puesto=NULL
            {$sqlUpdated}
        WHERE r.id_concurso=?
          AND r.estado='ACTIVO'
          AND COALESCE(s.excluir_ranking,0)=1
    ");
    if ($st) {
        mysqli_stmt_bind_param($st, 'i', $idConcurso);
        mysqli_stmt_execute($st);
        mysqli_stmt_close($st);
    }
}

function pr_forzar_exclusion_ies(mysqli $conn, int $idConcurso): void {
    if (!pr_table_exists($conn, 'concurso_ie_exclusiones')) return;
    $sqlUpdated = pr_col_exists($conn, 'concurso_resultados', 'updated_at') ? ", r.updated_at=NOW()" : "";
    $st = mysqli_prepare($conn, "
        UPDATE concurso_resultados r
        INNER JOIN concurso_participantes p ON p.id_participante=r.id_participante
        INNER JOIN concurso_ie_exclusiones iex
                ON iex.id_concurso=r.id_concurso
               AND LOWER(TRIM(iex.institucion_educativa))=LOWER(TRIM(p.institucion_educativa))
               AND iex.excluir_ranking=1
        SET r.publicar_resultado=0,
            r.motivo_no_publicar=CASE
                WHEN COALESCE(iex.motivo_exclusion_ie,'')<>'' THEN CONCAT('I.E. EXCLUIDA: ', iex.motivo_exclusion_ie)
                ELSE 'I.E. EXCLUIDA POR ADMINISTRADOR'
            END,
            r.puesto=NULL {$sqlUpdated}
        WHERE r.id_concurso=? AND r.estado='ACTIVO'
    ");
    if ($st) { mysqli_stmt_bind_param($st, 'i', $idConcurso); mysqli_stmt_execute($st); mysqli_stmt_close($st); }
}

function pr_forzar_exclusiones(mysqli $conn, int $idConcurso): void {
    pr_forzar_exclusion_salones($conn, $idConcurso);
    pr_forzar_exclusion_ies($conn, $idConcurso);
}

function pr_actualizar_ie_exclusion(mysqli $conn, int $idConcurso, string $institucion, int $excluir, string $motivo): void {
    $institucion = trim($institucion);
    if ($institucion === '') return;
    $motivo = trim($motivo);
    if ($excluir === 1 && $motivo === '') $motivo = 'I.E. EXCLUIDA POR ADMINISTRADOR';
    if ($excluir === 0) $motivo = '';

    $st = mysqli_prepare($conn, "
        INSERT INTO concurso_ie_exclusiones (id_concurso, institucion_educativa, excluir_ranking, motivo_exclusion_ie, updated_at)
        VALUES (?, ?, ?, ?, NOW())
        ON DUPLICATE KEY UPDATE excluir_ranking=VALUES(excluir_ranking), motivo_exclusion_ie=VALUES(motivo_exclusion_ie), updated_at=NOW()
    ");
    if (!$st) throw new RuntimeException('No se pudo preparar la actualización de la I.E.');
    mysqli_stmt_bind_param($st, 'isis', $idConcurso, $institucion, $excluir, $motivo);
    if (!mysqli_stmt_execute($st)) { $err = mysqli_stmt_error($st); mysqli_stmt_close($st); throw new RuntimeException('No se pudo actualizar la I.E.: ' . $err); }
    mysqli_stmt_close($st);

    $sqlUpdatedResultado = pr_col_exists($conn, 'concurso_resultados', 'updated_at') ? ", r.updated_at=NOW()" : "";
    if ($excluir === 1) {
        $motivoResultado = 'I.E. EXCLUIDA' . ($motivo !== '' ? ': ' . $motivo : '');
        $up = mysqli_prepare($conn, "
            UPDATE concurso_resultados r
            INNER JOIN concurso_participantes p ON p.id_participante=r.id_participante
            SET r.publicar_resultado=0, r.motivo_no_publicar=?, r.puesto=NULL {$sqlUpdatedResultado}
            WHERE r.id_concurso=? AND r.estado='ACTIVO' AND p.estado='ACTIVO'
              AND LOWER(TRIM(p.institucion_educativa))=LOWER(TRIM(?))
        ");
        if (!$up) throw new RuntimeException('No se pudo preparar la exclusión de resultados de la I.E.');
        mysqli_stmt_bind_param($up, 'sis', $motivoResultado, $idConcurso, $institucion);
        if (!mysqli_stmt_execute($up)) { $err = mysqli_stmt_error($up); mysqli_stmt_close($up); throw new RuntimeException('No se pudo excluir resultados de la I.E.: ' . $err); }
        mysqli_stmt_close($up);
    } else {
        $up = mysqli_prepare($conn, "
            UPDATE concurso_resultados r
            INNER JOIN concurso_participantes p ON p.id_participante=r.id_participante
            SET r.publicar_resultado=1, r.motivo_no_publicar='', r.puesto=NULL {$sqlUpdatedResultado}
            WHERE r.id_concurso=? AND r.estado='ACTIVO' AND p.estado='ACTIVO'
              AND LOWER(TRIM(p.institucion_educativa))=LOWER(TRIM(?))
              AND (r.motivo_no_publicar LIKE 'I.E. EXCLUIDA%' OR r.motivo_no_publicar LIKE 'IE EXCLUIDA%')
        ");
        if (!$up) throw new RuntimeException('No se pudo preparar la rehabilitación de la I.E.');
        mysqli_stmt_bind_param($up, 'is', $idConcurso, $institucion);
        if (!mysqli_stmt_execute($up)) { $err = mysqli_stmt_error($up); mysqli_stmt_close($up); throw new RuntimeException('No se pudo rehabilitar resultados de la I.E.: ' . $err); }
        mysqli_stmt_close($up);
    }
}

function pr_actualizar_salon_exclusion(mysqli $conn, int $idConcurso, int $idSalon, int $excluir, string $motivo): void {
    if ($idSalon <= 0) return;
    if (!pr_table_exists($conn, 'concurso_salones')) throw new RuntimeException('No existe la tabla concurso_salones.');

    $motivo = trim($motivo);
    if ($excluir === 1 && $motivo === '') $motivo = 'SALÓN EXCLUIDO POR ADMINISTRADOR';
    if ($excluir === 0) $motivo = '';

    $sqlUpdatedSalon = pr_col_exists($conn, 'concurso_salones', 'updated_at') ? ", updated_at=NOW()" : "";
    $st = mysqli_prepare($conn, "
        UPDATE concurso_salones
        SET excluir_ranking=?, motivo_exclusion_ranking=? {$sqlUpdatedSalon}
        WHERE id_salon=?
        LIMIT 1
    ");
    if (!$st) throw new RuntimeException('No se pudo preparar la actualización del salón.');
    mysqli_stmt_bind_param($st, 'isi', $excluir, $motivo, $idSalon);
    if (!mysqli_stmt_execute($st)) {
        $err = mysqli_stmt_error($st);
        mysqli_stmt_close($st);
        throw new RuntimeException('No se pudo actualizar el salón: ' . $err);
    }
    mysqli_stmt_close($st);

    $sqlUpdatedResultado = pr_col_exists($conn, 'concurso_resultados', 'updated_at') ? ", updated_at=NOW()" : "";

    if ($excluir === 1) {
        $motivoResultado = 'SALÓN EXCLUIDO' . ($motivo !== '' ? ': ' . $motivo : '');
        $up = mysqli_prepare($conn, "
            UPDATE concurso_resultados
            SET publicar_resultado=0, motivo_no_publicar=?, puesto=NULL {$sqlUpdatedResultado}
            WHERE id_concurso=? AND id_salon=? AND estado='ACTIVO'
        ");
        if (!$up) throw new RuntimeException('No se pudo preparar la exclusión de resultados del salón.');
        mysqli_stmt_bind_param($up, 'sii', $motivoResultado, $idConcurso, $idSalon);
        if (!mysqli_stmt_execute($up)) {
            $err = mysqli_stmt_error($up);
            mysqli_stmt_close($up);
            throw new RuntimeException('No se pudo excluir resultados del salón: ' . $err);
        }
        mysqli_stmt_close($up);
    } else {
        // Rehabilita solo los resultados que fueron ocultados por exclusión de salón.
        // No toca a los participantes ocultos manualmente por otro motivo.
        $up = mysqli_prepare($conn, "
            UPDATE concurso_resultados
            SET publicar_resultado=1, motivo_no_publicar='', puesto=NULL {$sqlUpdatedResultado}
            WHERE id_concurso=?
              AND id_salon=?
              AND estado='ACTIVO'
              AND (
                    motivo_no_publicar LIKE 'SALÓN EXCLUIDO%'
                 OR motivo_no_publicar LIKE 'SALON EXCLUIDO%'
              )
        ");
        if (!$up) throw new RuntimeException('No se pudo preparar la rehabilitación del salón.');
        mysqli_stmt_bind_param($up, 'ii', $idConcurso, $idSalon);
        if (!mysqli_stmt_execute($up)) {
            $err = mysqli_stmt_error($up);
            mysqli_stmt_close($up);
            throw new RuntimeException('No se pudo rehabilitar resultados del salón: ' . $err);
        }
        mysqli_stmt_close($up);
    }
}

$acceso = cn_validar_acceso($conn, 'index.php');
if (!cn_es_admin($acceso)) {
    http_response_code(403);
    die('Solo el administrador puede controlar la publicación de resultados.');
}

$idAcceso = (int)$acceso['id_acceso'];
$idConcurso = cn_concurso_trabajo($conn, $acceso);
if (isset($_GET['id_concurso']) && is_numeric($_GET['id_concurso'])) $idConcurso = (int)$_GET['id_concurso'];
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['id_concurso']) && is_numeric($_POST['id_concurso'])) $idConcurso = (int)$_POST['id_concurso'];

$concursosActivos = cn_concursos_activos($conn);
if ($idConcurso <= 0 && !empty($concursosActivos)) $idConcurso = (int)$concursosActivos[0]['id_concurso'];
if ($idConcurso <= 0) {
    http_response_code(500);
    die('No hay concurso activo disponible.');
}
$concursoTrabajo = cn_datos_concurso($conn, $idConcurso);

if (empty($_SESSION['csrf_publicacion_resultados_nobex'])) $_SESSION['csrf_publicacion_resultados_nobex'] = bin2hex(random_bytes(32));
$csrf = (string)$_SESSION['csrf_publicacion_resultados_nobex'];
$mensajeOk = '';
$mensajeError = '';

try {
    pr_ensure_schema($conn);
} catch (Throwable $e) {
    $mensajeError = $e->getMessage();
}

$idGrupoFiltro = max(0, (int)($_GET['id_grupo'] ?? $_POST['id_grupo'] ?? 0));
$idSalonFiltro = max(0, (int)($_GET['id_salon'] ?? $_POST['id_salon'] ?? 0));
$estadoFiltro = pr_get('estado', (string)($_POST['estado'] ?? 'todos'));
$q = pr_get('q', (string)($_POST['q'] ?? ''));
if (!in_array($estadoFiltro, ['todos','publicados','ocultos'], true)) $estadoFiltro = 'todos';

if ($_SERVER['REQUEST_METHOD'] === 'POST' && $mensajeError === '') {
    $accion = pr_post('accion');
    $csrfPost = pr_post('csrf_token');

    if (!hash_equals($csrf, $csrfPost)) {
        $mensajeError = 'Solicitud no válida. Recarga la página.';
    } elseif ($accion === 'guardar_publicacion') {
        $ids = $_POST['ids'] ?? [];
        $pub = $_POST['publicar'] ?? [];
        $motivos = $_POST['motivo'] ?? [];

        try {
            mysqli_begin_transaction($conn);
            $grupos = [];
            $actualizados = 0;
            $pubs = 0;
            $oculs = 0;

            foreach ($ids as $raw) {
                $idResultado = (int)$raw;
                if ($idResultado <= 0) continue;

                $ctx = pr_contexto($conn, $idConcurso, $idResultado);
                if (!$ctx) continue;

                $nuevo = isset($pub[$idResultado]) ? 1 : 0;
                if ((int)$ctx['salon_excluido'] === 1 || (int)$ctx['ie_excluida'] === 1) $nuevo = 0;

                $motivo = trim((string)($motivos[$idResultado] ?? ''));
                if ($nuevo === 0 && $motivo === '') {
                    if ((int)$ctx['salon_excluido'] === 1) {
                        $motivo = 'SALÓN EXCLUIDO POR ADMINISTRADOR';
                    } elseif ((int)$ctx['ie_excluida'] === 1) {
                        $motivo = 'I.E. EXCLUIDA POR ADMINISTRADOR';
                    } else {
                        $motivo = 'OCULTO POR ADMINISTRADOR';
                    }
                }
                if ($nuevo === 1) $motivo = '';

                $sqlUpdatedResultado = pr_col_exists($conn, 'concurso_resultados', 'updated_at') ? ", updated_at=NOW()" : "";
                $st = mysqli_prepare($conn, "
                    UPDATE concurso_resultados
                    SET publicar_resultado=?, motivo_no_publicar=? {$sqlUpdatedResultado}
                    WHERE id_resultado=? AND id_concurso=? AND estado='ACTIVO'
                    LIMIT 1
                ");
                if (!$st) throw new RuntimeException('No se pudo preparar la actualización.');

                mysqli_stmt_bind_param($st, 'isii', $nuevo, $motivo, $idResultado, $idConcurso);
                if (!mysqli_stmt_execute($st)) {
                    $err = mysqli_stmt_error($st);
                    mysqli_stmt_close($st);
                    throw new RuntimeException('No se pudo actualizar: ' . $err);
                }
                mysqli_stmt_close($st);

                $actualizados++;
                $nuevo === 1 ? $pubs++ : $oculs++;
                $g = (int)$ctx['id_grupo'];
                if ($g > 0) $grupos[$g] = true;

                if (function_exists('cn_auditar') && (int)$ctx['publicar_resultado'] !== $nuevo) {
                    cn_auditar(
                        $conn,
                        $idConcurso,
                        $g,
                        $idAcceso,
                        (int)$ctx['id_participante'],
                        $nuevo === 1 ? 'RESULTADO_PUBLICADO' : 'RESULTADO_OCULTADO',
                        'Participante: ' . $ctx['apellidos_nombres'] . ' | Documento: ' . $ctx['documento'] . ' | Publicar: ' . ($nuevo ? 'SI' : 'NO') . ($motivo !== '' ? ' | Motivo: ' . $motivo : '')
                    );
                }
            }

            pr_forzar_exclusiones($conn, $idConcurso);
            mysqli_commit($conn);

            $nGrupos = pr_recalcular_varios($conn, $idConcurso, array_keys($grupos ?: array_flip(pr_grupos_a_recalcular($conn, $idConcurso, $idGrupoFiltro))));

            $_SESSION['csrf_publicacion_resultados_nobex'] = bin2hex(random_bytes(32));
            $csrf = (string)$_SESSION['csrf_publicacion_resultados_nobex'];
            $mensajeOk = 'Publicación actualizada. Procesados: ' . $actualizados . ' | Visibles: ' . $pubs . ' | Ocultos: ' . $oculs . '. Puestos recalculados solo con visibles, sin salones excluidos y sin I.E. excluidas.';
        } catch (Throwable $e) {
            mysqli_rollback($conn);
            $mensajeError = $e->getMessage();
        }
    } elseif ($accion === 'guardar_salones') {
        $salonIds = $_POST['salon_ids'] ?? [];
        $excluirSalon = $_POST['excluir_salon'] ?? [];
        $motivoSalon = $_POST['motivo_salon'] ?? [];

        try {
            mysqli_begin_transaction($conn);
            $procesados = 0;
            $excluidos = 0;
            $incluidos = 0;
            $grupos = [];

            foreach ($salonIds as $rawSalon) {
                $idSalon = (int)$rawSalon;
                if ($idSalon <= 0) continue;

                $excluir = isset($excluirSalon[$idSalon]) ? 1 : 0;
                $motivo = trim((string)($motivoSalon[$idSalon] ?? ''));

                pr_actualizar_salon_exclusion($conn, $idConcurso, $idSalon, $excluir, $motivo);

                foreach (pr_grupos_por_salon($conn, $idConcurso, $idSalon) as $g) $grupos[$g] = true;
                $procesados++;
                $excluir === 1 ? $excluidos++ : $incluidos++;
            }

            pr_forzar_exclusiones($conn, $idConcurso);
            mysqli_commit($conn);

            if (empty($grupos)) $grupos = array_flip(pr_grupos_a_recalcular($conn, $idConcurso, $idGrupoFiltro));
            $nGrupos = pr_recalcular_varios($conn, $idConcurso, array_keys($grupos));

            $_SESSION['csrf_publicacion_resultados_nobex'] = bin2hex(random_bytes(32));
            $csrf = (string)$_SESSION['csrf_publicacion_resultados_nobex'];
            $mensajeOk = 'Salones actualizados. Procesados: ' . $procesados . ' | Excluidos: ' . $excluidos . ' | Incluidos: ' . $incluidos . '. Puestos recalculados en ' . $nGrupos . ' grupo(s).';
        } catch (Throwable $e) {
            mysqli_rollback($conn);
            $mensajeError = $e->getMessage();
        }
    } elseif ($accion === 'guardar_instituciones') {
        $institucionesIds = $_POST['instituciones_ids'] ?? [];
        $excluirIe = $_POST['excluir_ie'] ?? [];
        $motivoIe = $_POST['motivo_ie'] ?? [];
        try {
            mysqli_begin_transaction($conn);
            $procesadas = 0; $excluidas = 0; $incluidas = 0; $grupos = [];
            foreach ($institucionesIds as $idx => $institucionRaw) {
                $institucion = trim((string)$institucionRaw);
                if ($institucion === '') continue;
                $key = (string)$idx;
                $excluir = isset($excluirIe[$key]) ? 1 : 0;
                $motivo = trim((string)($motivoIe[$key] ?? ''));
                pr_actualizar_ie_exclusion($conn, $idConcurso, $institucion, $excluir, $motivo);
                foreach (pr_grupos_por_ie($conn, $idConcurso, $institucion) as $g) $grupos[$g] = true;
                $procesadas++; $excluir === 1 ? $excluidas++ : $incluidas++;
            }
            pr_forzar_exclusiones($conn, $idConcurso);
            mysqli_commit($conn);
            if (empty($grupos)) $grupos = array_flip(pr_grupos_a_recalcular($conn, $idConcurso, $idGrupoFiltro));
            $nGrupos = pr_recalcular_varios($conn, $idConcurso, array_keys($grupos));
            $_SESSION['csrf_publicacion_resultados_nobex'] = bin2hex(random_bytes(32));
            $csrf = (string)$_SESSION['csrf_publicacion_resultados_nobex'];
            $mensajeOk = 'Instituciones actualizadas. Procesadas: ' . $procesadas . ' | Excluidas: ' . $excluidas . ' | Incluidas: ' . $incluidas . '. Puestos recalculados en ' . $nGrupos . ' grupo(s).';
        } catch (Throwable $e) {
            mysqli_rollback($conn);
            $mensajeError = $e->getMessage();
        }
    } elseif ($accion === 'recalcular_puestos') {
        try {
            pr_forzar_exclusiones($conn, $idConcurso);
            $grupos = pr_grupos_a_recalcular($conn, $idConcurso, $idGrupoFiltro);
            $nGrupos = pr_recalcular_varios($conn, $idConcurso, $grupos);

            $_SESSION['csrf_publicacion_resultados_nobex'] = bin2hex(random_bytes(32));
            $csrf = (string)$_SESSION['csrf_publicacion_resultados_nobex'];
            $mensajeOk = 'Puestos recalculados correctamente en ' . $nGrupos . ' grupo(s). No se contaron participantes ocultos, salones excluidos ni I.E. excluidas.';
        } catch (Throwable $e) {
            $mensajeError = $e->getMessage();
        }
    }
}

$grupos = pr_grupos($conn, $idConcurso);
$salones = $mensajeError === '' ? pr_salones($conn, $idConcurso, $idGrupoFiltro) : [];
$instituciones = $mensajeError === '' ? pr_instituciones($conn, $idConcurso, $idGrupoFiltro, $q) : [];
$stats = $mensajeError === '' ? pr_stats($conn, $idConcurso) : ['total'=>0,'publicados'=>0,'ocultos'=>0,'salones_excluidos'=>0,'ies_excluidas'=>0];
$resultados = $mensajeError === '' ? pr_listar($conn, $idConcurso, $idGrupoFiltro, $idSalonFiltro, $estadoFiltro, $q) : [];
$queryConcurso = $idConcurso > 0 ? '?id_concurso=' . urlencode((string)$idConcurso) : '';
$nombreConcursoVista = $concursoTrabajo['nombre'] ?? ('Concurso ID ' . $idConcurso);
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Publicación de resultados | NOBEX</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<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;--gold:#facc15;--blue:#1d4ed8;--green:#16a34a;--ink:#0f172a;--muted:#64748b;--line:#e2e8f0;--shadow:0 22px 50px rgba(15,23,42,.10)}
body{margin:0;min-height:100vh;font-family:Inter,Arial,Helvetica,sans-serif;background:radial-gradient(circle at top left,rgba(250,204,21,.16),transparent 32%),linear-gradient(135deg,#f8fafc 0%,#eef2ff 48%,#fff7ed 100%);color:var(--ink)}
a{text-decoration:none;color:inherit}
.topbar{color:#fff;background:radial-gradient(circle at 18% 0%,rgba(250,204,21,.28),transparent 28%),linear-gradient(135deg,#0f172a,#1f2937 52%,#991b1b);border-bottom:7px solid var(--gold);box-shadow:0 20px 50px rgba(15,23,42,.22)}
.topbar-inner{max-width:1420px;margin:0 auto;padding:22px 18px;display:flex;justify-content:space-between;align-items:center;gap:16px}
.brand{display:flex;gap:14px;align-items:center}.brand-mark{width:56px;height:56px;border-radius:19px;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,.13);border:1px solid rgba(255,255,255,.22);font-size:24px}
.eyebrow{margin:0 0 5px;color:#fde68a;font-size:12px;font-weight:950;letter-spacing:.08em;text-transform:uppercase}
h1{margin:0;font-size:clamp(25px,3.2vw,36px);line-height:1.05;letter-spacing:-.04em;font-weight:950}.topbar p{margin:7px 0 0;color:#e5e7eb;font-weight:850;font-size:14px}
.top-actions{display:flex;gap:10px;flex-wrap:wrap}.btn-top{display:inline-flex;align-items:center;justify-content:center;gap:8px;border-radius:15px;padding:12px 15px;color:#fff;border:1px solid rgba(255,255,255,.28);background:rgba(255,255,255,.10);font-weight:950;white-space:nowrap}.btn-top:hover{background:rgba(255,255,255,.18)}
.container{max-width:1420px;margin:22px auto;padding:0 18px 42px}
.stats{display:grid;grid-template-columns:repeat(5,1fr);gap:14px;margin-bottom:18px}.card{background:rgba(255,255,255,.96);border:1px solid rgba(226,232,240,.95);border-radius:24px;box-shadow:var(--shadow);overflow:hidden}
.stat{padding:18px;display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:110px}.stat strong{display:block;font-size:32px;line-height:1;font-weight:950;letter-spacing:-.04em}.stat span{display:block;margin-top:7px;color:#64748b;font-size:12px;font-weight:950;text-transform:uppercase}.stat-icon{width:50px;height:50px;border-radius:17px;display:flex;align-items:center;justify-content:center;font-size:21px}.icon-green{background:#dcfce7;color:#166534}.icon-red{background:#fee2e2;color:#991b1b}.icon-blue{background:#dbeafe;color:#1d4ed8}.icon-amber{background:#fef3c7;color:#92400e}
.panel-head{padding:18px 20px;border-bottom:1px solid var(--line);background:linear-gradient(135deg,#fff,#f8fafc)}.panel-head h2{margin:0;font-size:20px;font-weight:950;letter-spacing:-.02em}.panel-head p{margin:6px 0 0;color:var(--muted);font-size:13px;font-weight:780;line-height:1.45}.panel-body{padding:18px 20px}
.filters{display:grid;grid-template-columns:1.35fr .9fr .9fr .9fr auto;gap:12px;align-items:end}label{display:block;font-weight:950;color:#334155;margin-bottom:7px;font-size:13px}input,select{width:100%;border:1px solid #cbd5e1;border-radius:14px;padding:12px 13px;outline:none;font-size:14px;background:#fff;color:#0f172a}input:focus,select:focus{border-color:var(--blue);box-shadow:0 0 0 4px rgba(29,78,216,.12)}
.btn{border:0;border-radius:15px;padding:13px 16px;font-weight:950;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:8px;white-space:nowrap}.btn-primary{background:linear-gradient(135deg,#1d4ed8,#1e40af);color:#fff;box-shadow:0 12px 24px rgba(29,78,216,.18)}.btn-danger{background:linear-gradient(135deg,#dc2626,#991b1b);color:#fff;box-shadow:0 12px 24px rgba(220,38,38,.16)}.btn-soft{background:#f1f5f9;color:#334155;border:1px solid #e2e8f0}.btn-warning{background:linear-gradient(135deg,#f59e0b,#d97706);color:#fff;box-shadow:0 12px 24px rgba(245,158,11,.16)}
.msg{border-radius:16px;padding:14px 16px;font-weight:850;line-height:1.5;margin-bottom:16px}.ok{background:#dcfce7;color:#166534;border:1px solid #86efac}.error{background:#fee2e2;color:#991b1b;border:1px solid #fca5a5}.warn{background:#fef3c7;color:#92400e;border:1px solid #fcd34d}
.salon-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}.salon-card{border:1px solid #e2e8f0;border-radius:20px;background:linear-gradient(135deg,#fff,#f8fafc);padding:15px;box-shadow:0 12px 26px rgba(15,23,42,.06)}.salon-card.excluido{border-color:#fecaca;background:linear-gradient(135deg,#fff1f2,#fff)}.salon-top{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.salon-title{font-weight:950;color:#0f172a}.salon-meta{margin-top:5px;font-size:12px;color:#64748b;font-weight:850;line-height:1.4}.salon-check{display:flex;align-items:center;gap:8px;margin-top:12px;font-weight:950;color:#991b1b}.salon-check input{width:20px;height:20px}.salon-motivo{margin-top:10px}
.table-wrap{overflow-x:auto}table{width:100%;border-collapse:separate;border-spacing:0;font-size:13px;min-width:1240px}th,td{padding:12px;border-bottom:1px solid #e2e8f0;text-align:left;vertical-align:middle}th{background:#f8fafc;color:#475569;font-size:11px;font-weight:950;text-transform:uppercase;white-space:nowrap}tbody tr:hover td{background:#f8fafc}.name{font-weight:950;color:#0f172a}.mini{font-size:12px;color:#64748b;font-weight:800;line-height:1.4}.badge{display:inline-flex;align-items:center;gap:6px;border-radius:999px;padding:6px 9px;font-size:12px;font-weight:950;white-space:nowrap}.badge-green{background:#dcfce7;color:#166534}.badge-red{background:#fee2e2;color:#991b1b}.badge-blue{background:#dbeafe;color:#1d4ed8}.badge-amber{background:#fef3c7;color:#92400e}.motivo-input{min-width:230px}.switchline{display:flex;align-items:center;gap:8px;font-weight:950}.switchline input{width:20px;height:20px}.actions-row{display:flex;gap:10px;flex-wrap:wrap;justify-content:space-between;align-items:center;margin:16px 0}.empty{padding:32px;text-align:center;color:#64748b;font-weight:900}
@media(max-width:1100px){.stats{grid-template-columns:repeat(2,1fr)}.salon-grid{grid-template-columns:repeat(2,1fr)}.filters{grid-template-columns:1fr 1fr}}
@media(max-width:760px){.topbar-inner{flex-direction:column;align-items:flex-start}.stats{grid-template-columns:1fr}.salon-grid{grid-template-columns:1fr}.filters{grid-template-columns:1fr}.btn,.btn-top{width:100%}.top-actions{width:100%}}
</style>
</head>
<body class="cn-con-sidebar">
<?php include __DIR__ . '/includes/sidebar_concurso.php'; ?>
<header class="topbar">
    <div class="topbar-inner">
        <div class="brand">
            <div class="brand-mark"><i class="fa-solid fa-eye-slash"></i></div>
            <div>
                <p class="eyebrow">NOBEX · Administración</p>
                <h1>Publicación de resultados</h1>
                <p><?php echo pr_h($nombreConcursoVista); ?> · controla participantes, salones, I.E. y recalcula puestos.</p>
            </div>
        </div>
        <div class="top-actions">
            <a class="btn-top" href="panel.php<?php echo pr_h($queryConcurso); ?>"><i class="fa-solid fa-table-columns"></i> Panel</a>
            <a class="btn-top" href="resultados.php<?php echo pr_h($queryConcurso); ?>"><i class="fa-solid fa-ranking-star"></i> Ver resultados</a>
        </div>
    </div>
</header>

<main class="container">
    <?php if ($mensajeOk !== ''): ?>
        <div class="msg ok"><i class="fa-solid fa-circle-check"></i> <?php echo pr_h($mensajeOk); ?></div>
    <?php endif; ?>
    <?php if ($mensajeError !== ''): ?>
        <div class="msg error"><i class="fa-solid fa-triangle-exclamation"></i> <?php echo pr_h($mensajeError); ?></div>
    <?php endif; ?>

    <section class="stats">
        <div class="card stat"><div><strong><?php echo (int)$stats['total']; ?></strong><span>Total calificados</span></div><div class="stat-icon icon-blue"><i class="fa-solid fa-clipboard-check"></i></div></div>
        <div class="card stat"><div><strong><?php echo (int)$stats['publicados']; ?></strong><span>Salen en resultados</span></div><div class="stat-icon icon-green"><i class="fa-solid fa-eye"></i></div></div>
        <div class="card stat"><div><strong><?php echo (int)$stats['ocultos']; ?></strong><span>No salen</span></div><div class="stat-icon icon-red"><i class="fa-solid fa-eye-slash"></i></div></div>
        <div class="card stat"><div><strong><?php echo (int)$stats['salones_excluidos']; ?></strong><span>Salones excluidos</span></div><div class="stat-icon icon-amber"><i class="fa-solid fa-door-closed"></i></div></div>
        <div class="card stat"><div><strong><?php echo (int)$stats['ies_excluidas']; ?></strong><span>I.E. excluidas</span></div><div class="stat-icon icon-red"><i class="fa-solid fa-school-circle-xmark"></i></div></div>
    </section>

    <section class="card">
        <div class="panel-head">
            <h2>Filtros</h2>
            <p>Filtra por grado, salón, estado o busca por DNI, código, nombres o institución.</p>
        </div>
        <div class="panel-body">
            <form method="get" action="" class="filters">
                <input type="hidden" name="id_concurso" value="<?php echo (int)$idConcurso; ?>">
                <div>
                    <label for="q">Buscar</label>
                    <input type="text" id="q" name="q" value="<?php echo pr_h($q); ?>" placeholder="DNI, código, nombres o I.E.">
                </div>
                <div>
                    <label for="id_grupo">Grado / grupo</label>
                    <select id="id_grupo" name="id_grupo">
                        <option value="0">Todos los grados</option>
                        <?php foreach ($grupos as $g): ?>
                            <option value="<?php echo (int)$g['id_grupo']; ?>" <?php echo (int)$g['id_grupo'] === $idGrupoFiltro ? 'selected' : ''; ?>>
                                <?php echo pr_h($g['nombre'] . (!empty($g['nivel']) ? ' · ' . $g['nivel'] : '')); ?>
                            </option>
                        <?php endforeach; ?>
                    </select>
                </div>
                <div>
                    <label for="id_salon">Salón</label>
                    <select id="id_salon" name="id_salon">
                        <option value="0">Todos los salones</option>
                        <?php foreach ($salones as $s): ?>
                            <option value="<?php echo (int)$s['id_salon']; ?>" <?php echo (int)$s['id_salon'] === $idSalonFiltro ? 'selected' : ''; ?>>
                                <?php echo pr_h($s['grupo_nombre'] . ' · ' . $s['nombre_salon']); ?><?php echo (int)$s['excluir_ranking'] === 1 ? ' (excluido)' : ''; ?>
                            </option>
                        <?php endforeach; ?>
                    </select>
                </div>
                <div>
                    <label for="estado">Estado</label>
                    <select id="estado" name="estado">
                        <option value="todos" <?php echo $estadoFiltro === 'todos' ? 'selected' : ''; ?>>Todos</option>
                        <option value="publicados" <?php echo $estadoFiltro === 'publicados' ? 'selected' : ''; ?>>Salen</option>
                        <option value="ocultos" <?php echo $estadoFiltro === 'ocultos' ? 'selected' : ''; ?>>No salen</option>
                    </select>
                </div>
                <button class="btn btn-primary" type="submit"><i class="fa-solid fa-filter"></i> Filtrar</button>
            </form>
        </div>
    </section>

    <section class="card" style="margin-top:18px">
        <div class="panel-head">
            <h2>Excluir salones del ranking</h2>
            <p>Marca un salón para que ninguno de sus participantes cuente en el ranking. Al guardar, los puestos se recalculan nuevamente.</p>
        </div>
        <div class="panel-body">
            <?php if (empty($salones)): ?>
                <div class="empty"><i class="fa-regular fa-folder-open"></i><br>No hay salones con resultados calificados.</div>
            <?php else: ?>
                <form method="post" action="" id="frmSalones">
                    <input type="hidden" name="csrf_token" value="<?php echo pr_h($csrf); ?>">
                    <input type="hidden" name="accion" value="guardar_salones">
                    <input type="hidden" name="id_concurso" value="<?php echo (int)$idConcurso; ?>">
                    <input type="hidden" name="id_grupo" value="<?php echo (int)$idGrupoFiltro; ?>">
                    <input type="hidden" name="id_salon" value="<?php echo (int)$idSalonFiltro; ?>">
                    <input type="hidden" name="estado" value="<?php echo pr_h($estadoFiltro); ?>">
                    <input type="hidden" name="q" value="<?php echo pr_h($q); ?>">

                    <div class="salon-grid">
                        <?php foreach ($salones as $s):
                            $idS = (int)$s['id_salon'];
                            $ex = (int)$s['excluir_ranking'] === 1;
                        ?>
                            <div class="salon-card <?php echo $ex ? 'excluido' : ''; ?>">
                                <input type="hidden" name="salon_ids[]" value="<?php echo $idS; ?>">
                                <div class="salon-top">
                                    <div>
                                        <div class="salon-title"><?php echo pr_h($s['nombre_salon']); ?></div>
                                        <div class="salon-meta">
                                            <?php echo pr_h($s['grupo_nombre'] . (!empty($s['nivel']) ? ' · ' . $s['nivel'] : '')); ?><br>
                                            Calificados: <?php echo (int)$s['total_calificados']; ?> · Visibles: <?php echo (int)$s['visibles']; ?> · Ocultos: <?php echo (int)$s['ocultos']; ?>
                                        </div>
                                    </div>
                                    <?php if ($ex): ?>
                                        <span class="badge badge-red"><i class="fa-solid fa-ban"></i> Excluido</span>
                                    <?php else: ?>
                                        <span class="badge badge-green"><i class="fa-solid fa-check"></i> Activo</span>
                                    <?php endif; ?>
                                </div>
                                <label class="salon-check">
                                    <input type="checkbox" name="excluir_salon[<?php echo $idS; ?>]" value="1" class="chk-salon" data-motivo="motivo_salon_<?php echo $idS; ?>" <?php echo $ex ? 'checked' : ''; ?>>
                                    Excluir este salón del ranking
                                </label>
                                <div class="salon-motivo">
                                    <input type="text" id="motivo_salon_<?php echo $idS; ?>" name="motivo_salon[<?php echo $idS; ?>]" value="<?php echo pr_h($s['motivo_exclusion_ranking']); ?>" placeholder="Motivo de exclusión del salón" <?php echo $ex ? '' : 'disabled'; ?>>
                                </div>
                            </div>
                        <?php endforeach; ?>
                    </div>

                    <div class="actions-row" style="margin-top:18px">
                        <div class="msg warn" style="margin:0"><i class="fa-solid fa-circle-info"></i> Si vuelves a incluir un salón, solo se rehabilitan los resultados ocultos por exclusión de salón; los ocultos manualmente se respetan.</div>
                        <button class="btn btn-danger" type="submit"><i class="fa-solid fa-door-closed"></i> Guardar salones y recalcular</button>
                    </div>
                </form>
            <?php endif; ?>
        </div>
    </section>

    <section class="card" style="margin-top:18px">
        <div class="panel-head">
            <h2>Excluir instituciones educativas del ranking</h2>
            <p>Marca una I.E. para que todos sus estudiantes calificados queden fuera del ranking público. Al guardar, los puestos se recalculan nuevamente.</p>
        </div>
        <div class="panel-body">
            <?php if (empty($instituciones)): ?>
                <div class="empty"><i class="fa-regular fa-folder-open"></i><br>No hay instituciones educativas con resultados calificados.</div>
            <?php else: ?>
                <form method="post" action="" id="frmInstituciones">
                    <input type="hidden" name="csrf_token" value="<?php echo pr_h($csrf); ?>">
                    <input type="hidden" name="accion" value="guardar_instituciones">
                    <input type="hidden" name="id_concurso" value="<?php echo (int)$idConcurso; ?>">
                    <input type="hidden" name="id_grupo" value="<?php echo (int)$idGrupoFiltro; ?>">
                    <input type="hidden" name="id_salon" value="<?php echo (int)$idSalonFiltro; ?>">
                    <input type="hidden" name="estado" value="<?php echo pr_h($estadoFiltro); ?>">
                    <input type="hidden" name="q" value="<?php echo pr_h($q); ?>">

                    <div class="salon-grid">
                        <?php foreach ($instituciones as $idx => $ie):
                            $inst = (string)$ie['institucion_educativa'];
                            $exIe = (int)$ie['excluir_ranking'] === 1;
                        ?>
                            <div class="salon-card <?php echo $exIe ? 'excluido' : ''; ?>">
                                <input type="hidden" name="instituciones_ids[<?php echo (int)$idx; ?>]" value="<?php echo pr_h($inst); ?>">
                                <div class="salon-top">
                                    <div>
                                        <div class="salon-title"><?php echo pr_h($inst); ?></div>
                                        <div class="salon-meta">
                                            Calificados: <?php echo (int)$ie['total_calificados']; ?> · Visibles: <?php echo (int)$ie['visibles']; ?> · Ocultos: <?php echo (int)$ie['ocultos']; ?><br>
                                            Grupos: <?php echo (int)$ie['grupos_count']; ?> · Salones: <?php echo (int)$ie['salones_count']; ?>
                                        </div>
                                    </div>
                                    <?php if ($exIe): ?>
                                        <span class="badge badge-red"><i class="fa-solid fa-ban"></i> Excluida</span>
                                    <?php else: ?>
                                        <span class="badge badge-green"><i class="fa-solid fa-check"></i> Activa</span>
                                    <?php endif; ?>
                                </div>
                                <label class="salon-check">
                                    <input type="checkbox" name="excluir_ie[<?php echo (int)$idx; ?>]" value="1" class="chk-ie" data-motivo="motivo_ie_<?php echo (int)$idx; ?>" <?php echo $exIe ? 'checked' : ''; ?>>
                                    Excluir esta I.E. del ranking
                                </label>
                                <div class="salon-motivo">
                                    <input type="text" id="motivo_ie_<?php echo (int)$idx; ?>" name="motivo_ie[<?php echo (int)$idx; ?>]" value="<?php echo pr_h($ie['motivo_exclusion_ie']); ?>" placeholder="Motivo de exclusión de la I.E." <?php echo $exIe ? '' : 'disabled'; ?>>
                                </div>
                            </div>
                        <?php endforeach; ?>
                    </div>

                    <div class="actions-row" style="margin-top:18px">
                        <div class="msg warn" style="margin:0"><i class="fa-solid fa-circle-info"></i> Si vuelves a incluir una I.E., solo se rehabilitan los resultados ocultos por exclusión de I.E.; los ocultos manualmente se respetan.</div>
                        <button class="btn btn-danger" type="submit"><i class="fa-solid fa-school-circle-xmark"></i> Guardar I.E. y recalcular</button>
                    </div>
                </form>
            <?php endif; ?>
        </div>
    </section>

    <section class="card" style="margin-top:18px">
        <div class="panel-head">
            <h2>Recalcular puestos</h2>
            <p>Usa esta opción cuando ya corregiste nombres, instituciones, ocultaste participantes o excluiste salones/I.E.</p>
        </div>
        <div class="panel-body">
            <form method="post" action="" id="frmRecalcular" class="actions-row" style="margin:0">
                <input type="hidden" name="csrf_token" value="<?php echo pr_h($csrf); ?>">
                <input type="hidden" name="accion" value="recalcular_puestos">
                <input type="hidden" name="id_concurso" value="<?php echo (int)$idConcurso; ?>">
                <input type="hidden" name="id_grupo" value="<?php echo (int)$idGrupoFiltro; ?>">
                <input type="hidden" name="id_salon" value="<?php echo (int)$idSalonFiltro; ?>">
                <input type="hidden" name="estado" value="<?php echo pr_h($estadoFiltro); ?>">
                <input type="hidden" name="q" value="<?php echo pr_h($q); ?>">
                <div class="mini">El recálculo ordena por puntaje, tiempo, correctas, incorrectas e ID de resultado. No cuenta ocultos, salones excluidos ni I.E. excluidas.</div>
                <button class="btn btn-warning" type="submit"><i class="fa-solid fa-rotate"></i> Recalcular puestos ahora</button>
            </form>
        </div>
    </section>

    <form method="post" action="" id="frmPublicacion">
        <input type="hidden" name="csrf_token" value="<?php echo pr_h($csrf); ?>">
        <input type="hidden" name="accion" value="guardar_publicacion">
        <input type="hidden" name="id_concurso" value="<?php echo (int)$idConcurso; ?>">
        <input type="hidden" name="id_grupo" value="<?php echo (int)$idGrupoFiltro; ?>">
        <input type="hidden" name="id_salon" value="<?php echo (int)$idSalonFiltro; ?>">
        <input type="hidden" name="estado" value="<?php echo pr_h($estadoFiltro); ?>">
        <input type="hidden" name="q" value="<?php echo pr_h($q); ?>">

        <section class="card" style="margin-top:18px">
            <div class="panel-head">
                <h2>Control de publicación por participante</h2>
                <p>Desmarca a quienes no deben salir. Al guardar, los puestos se recalculan solo con visibles, sin salones excluidos y sin I.E. excluidas.</p>
            </div>

            <?php if (empty($resultados)): ?>
                <div class="empty"><i class="fa-regular fa-folder-open"></i><br>No hay resultados con los filtros seleccionados.</div>
            <?php else: ?>
                <div class="panel-body">
                    <div class="actions-row">
                        <div class="mini">Mostrando <strong><?php echo count($resultados); ?></strong> resultado(s). Límite por vista: 800.</div>
                        <div style="display:flex;gap:10px;flex-wrap:wrap">
                            <button class="btn btn-soft" type="button" id="btnMarcarTodos"><i class="fa-solid fa-eye"></i> Marcar todos visibles</button>
                            <button class="btn btn-primary" type="submit"><i class="fa-solid fa-floppy-disk"></i> Guardar publicación</button>
                        </div>
                    </div>
                </div>

                <div class="table-wrap">
                    <table>
                        <thead>
                            <tr>
                                <th>Publicar</th>
                                <th>Participante</th>
                                <th>I.E.</th>
                                <th>Grupo / salón</th>
                                <th>Tipo</th>
                                <th>Nota</th>
                                <th>Puesto</th>
                                <th>Motivo si no sale</th>
                            </tr>
                        </thead>
                        <tbody>
                        <?php foreach ($resultados as $r):
                            $id = (int)$r['id_resultado'];
                            $salonExcluido = (int)$r['salon_excluido'] === 1;
                            $ieExcluida = (int)$r['ie_excluida'] === 1;
                            $sale = (int)$r['publicar_resultado'] === 1 && !$salonExcluido && !$ieExcluida;
                            if ($ieExcluida && !empty($r['motivo_ie_excluida'])) {
                                $motivoVista = 'I.E. EXCLUIDA: ' . $r['motivo_ie_excluida'];
                            } elseif ($salonExcluido && !empty($r['motivo_salon_excluido'])) {
                                $motivoVista = 'SALÓN EXCLUIDO: ' . $r['motivo_salon_excluido'];
                            } else {
                                $motivoVista = (string)$r['motivo_no_publicar'];
                            }
                        ?>
                            <tr>
                                <td>
                                    <input type="hidden" name="ids[]" value="<?php echo $id; ?>">
                                    <label class="switchline">
                                        <input type="checkbox" name="publicar[<?php echo $id; ?>]" value="1" class="chk-publicar" data-motivo="motivo_<?php echo $id; ?>" <?php echo $sale ? 'checked' : ''; ?> <?php echo ($salonExcluido || $ieExcluida) ? 'disabled' : ''; ?>>
                                        <?php if ($ieExcluida): ?>
                                            <span class="badge badge-red"><i class="fa-solid fa-school-circle-xmark"></i> I.E. excluida</span>
                                        <?php elseif ($salonExcluido): ?>
                                            <span class="badge badge-red"><i class="fa-solid fa-door-closed"></i> Salón excluido</span>
                                        <?php elseif ($sale): ?>
                                            <span class="badge badge-green"><i class="fa-solid fa-eye"></i> Sale</span>
                                        <?php else: ?>
                                            <span class="badge badge-red"><i class="fa-solid fa-eye-slash"></i> No sale</span>
                                        <?php endif; ?>
                                    </label>
                                </td>
                                <td>
                                    <div class="name"><?php echo pr_h($r['apellidos_nombres']); ?></div>
                                    <div class="mini">DNI/Cód.: <?php echo pr_h($r['documento']); ?> · <?php echo pr_h($r['codigo_participante']); ?></div>
                                </td>
                                <td><div class="mini"><?php echo pr_h($r['institucion_educativa']); ?></div><?php if ($ieExcluida): ?><div style="margin-top:6px"><span class="badge badge-red"><i class="fa-solid fa-ban"></i> I.E. excluida</span></div><?php endif; ?></td>
                                <td>
                                    <span class="badge badge-blue"><?php echo pr_h($r['grupo_nombre'] ?: 'Sin grupo'); ?></span>
                                    <div class="mini"><?php echo pr_h($r['nombre_salon'] ?: 'Sin salón'); ?></div>
                                    <?php if ($salonExcluido): ?><div style="margin-top:6px"><span class="badge badge-amber"><i class="fa-solid fa-ban"></i> No participa</span></div><?php endif; ?>
                                </td>
                                <td><?php echo pr_h($r['tipo_institucion']); ?></td>
                                <td>
                                    <strong><?php echo number_format((float)$r['puntaje'], 2, '.', ''); ?></strong>
                                    <div class="mini">C: <?php echo (int)$r['correctas']; ?> · I: <?php echo (int)$r['incorrectas']; ?> · B: <?php echo (int)$r['blanco']; ?><?php if (!empty($r['tiempo_texto'])): ?> · T: <?php echo pr_h($r['tiempo_texto']); ?><?php endif; ?></div>
                                </td>
                                <td>
                                    <?php if ($sale && $r['puesto'] !== null && $r['puesto'] !== ''): ?>
                                        <span class="badge badge-green">#<?php echo (int)$r['puesto']; ?></span>
                                    <?php elseif ($ieExcluida): ?>
                                        <span class="badge badge-red">I.E. excluida</span>
                                    <?php elseif ($salonExcluido): ?>
                                        <span class="badge badge-amber">Salón excluido</span>
                                    <?php elseif (!$sale): ?>
                                        <span class="badge badge-red">Oculto</span>
                                    <?php else: ?>
                                        <span class="badge badge-blue">Por recalcular</span>
                                    <?php endif; ?>
                                </td>
                                <td>
                                    <input class="motivo-input motivo-no-publicar" id="motivo_<?php echo $id; ?>" type="text" name="motivo[<?php echo $id; ?>]" value="<?php echo pr_h($motivoVista); ?>" placeholder="Ej.: ausente, descalificado, no corresponde..." <?php echo $sale ? 'disabled' : ''; ?>>
                                </td>
                            </tr>
                        <?php endforeach; ?>
                        </tbody>
                    </table>
                </div>

                <div class="panel-body">
                    <div class="actions-row">
                        <div class="msg warn" style="margin:0"><i class="fa-solid fa-circle-info"></i> Esto no borra calificaciones. Solo controla quién sale en la publicación/ranking.</div>
                        <button class="btn btn-primary" type="submit"><i class="fa-solid fa-floppy-disk"></i> Guardar publicación</button>
                    </div>
                </div>
            <?php endif; ?>
        </section>
    </form>
</main>

<script>
document.addEventListener('DOMContentLoaded', function () {
    const frm = document.getElementById('frmPublicacion');
    const frmSalones = document.getElementById('frmSalones');
    const frmInstituciones = document.getElementById('frmInstituciones');
    const frmRecalcular = document.getElementById('frmRecalcular');
    const btn = document.getElementById('btnMarcarTodos');

    function refreshParticipantes() {
        document.querySelectorAll('.chk-publicar').forEach(function (chk) {
            const input = document.getElementById(chk.dataset.motivo);
            if (!input) return;
            input.disabled = chk.checked && !chk.disabled;
            if (chk.checked && !chk.disabled) input.value = '';
        });
    }

    function refreshSalones() {
        document.querySelectorAll('.chk-salon').forEach(function (chk) {
            const input = document.getElementById(chk.dataset.motivo);
            if (!input) return;
            input.disabled = !chk.checked;
            if (!chk.checked) input.value = '';
        });
    }

    function refreshInstituciones() {
        document.querySelectorAll('.chk-ie').forEach(function (chk) {
            const input = document.getElementById(chk.dataset.motivo);
            if (!input) return;
            input.disabled = !chk.checked;
            if (!chk.checked) input.value = '';
        });
    }

    document.querySelectorAll('.chk-publicar').forEach(function (chk) {
        chk.addEventListener('change', refreshParticipantes);
    });
    document.querySelectorAll('.chk-salon').forEach(function (chk) {
        chk.addEventListener('change', refreshSalones);
    });
    document.querySelectorAll('.chk-ie').forEach(function (chk) {
        chk.addEventListener('change', refreshInstituciones);
    });

    if (btn) {
        btn.addEventListener('click', function () {
            document.querySelectorAll('.chk-publicar').forEach(function (chk) {
                if (!chk.disabled) chk.checked = true;
            });
            refreshParticipantes();
        });
    }

    if (frm) {
        frm.addEventListener('submit', function (e) {
            if (frm.dataset.confirmado === '1') return;
            e.preventDefault();
            Swal.fire({
                icon: 'warning',
                title: '¿Guardar publicación?',
                text: 'Se actualizará quién sale y quién no sale. También se recalcularán los puestos visibles sin salones excluidos ni I.E. excluidas.',
                showCancelButton: true,
                confirmButtonText: 'Sí, guardar',
                cancelButtonText: 'Cancelar',
                confirmButtonColor: '#1d4ed8',
                cancelButtonColor: '#64748b'
            }).then(function (r) {
                if (r.isConfirmed) {
                    document.querySelectorAll('.motivo-no-publicar').forEach(function (input) { input.disabled = false; });
                    frm.dataset.confirmado = '1';
                    frm.submit();
                }
            });
        });
    }

    if (frmSalones) {
        frmSalones.addEventListener('submit', function (e) {
            if (frmSalones.dataset.confirmado === '1') return;
            e.preventDefault();
            Swal.fire({
                icon: 'warning',
                title: '¿Guardar exclusión de salones?',
                text: 'Los salones marcados no contarán en el ranking. Luego se recalcularán los puestos.',
                showCancelButton: true,
                confirmButtonText: 'Sí, guardar y recalcular',
                cancelButtonText: 'Cancelar',
                confirmButtonColor: '#dc2626',
                cancelButtonColor: '#64748b'
            }).then(function (r) {
                if (r.isConfirmed) {
                    document.querySelectorAll('[name^="motivo_salon"]').forEach(function (input) { input.disabled = false; });
                    frmSalones.dataset.confirmado = '1';
                    frmSalones.submit();
                }
            });
        });
    }

    if (frmInstituciones) {
        frmInstituciones.addEventListener('submit', function (e) {
            if (frmInstituciones.dataset.confirmado === '1') return;
            e.preventDefault();
            Swal.fire({
                icon: 'warning',
                title: '¿Guardar exclusión de I.E.?',
                text: 'Las instituciones marcadas no contarán en el ranking. Luego se recalcularán los puestos.',
                showCancelButton: true,
                confirmButtonText: 'Sí, guardar y recalcular',
                cancelButtonText: 'Cancelar',
                confirmButtonColor: '#dc2626',
                cancelButtonColor: '#64748b'
            }).then(function (r) {
                if (r.isConfirmed) {
                    document.querySelectorAll('[name^="motivo_ie"]').forEach(function (input) { input.disabled = false; });
                    frmInstituciones.dataset.confirmado = '1';
                    frmInstituciones.submit();
                }
            });
        });
    }

    if (frmRecalcular) {
        frmRecalcular.addEventListener('submit', function (e) {
            if (frmRecalcular.dataset.confirmado === '1') return;
            e.preventDefault();
            Swal.fire({
                icon: 'question',
                title: '¿Recalcular puestos?',
                text: 'Se recalculará el ranking sin contar ocultos, salones excluidos ni I.E. excluidas.',
                showCancelButton: true,
                confirmButtonText: 'Sí, recalcular',
                cancelButtonText: 'Cancelar',
                confirmButtonColor: '#f59e0b',
                cancelButtonColor: '#64748b'
            }).then(function (r) {
                if (r.isConfirmed) {
                    frmRecalcular.dataset.confirmado = '1';
                    frmRecalcular.submit();
                }
            });
        });
    }

    refreshParticipantes();
    refreshSalones();
    refreshInstituciones();
});
</script>
</body>
</html>
