<?php
declare(strict_types=1);

// ============================================================
//  vinculacion/index.php — Panel de gestión de vinculaciones
//  Roles permitidos: admin, recursos_humanos, analista
// ============================================================
require_once __DIR__ . '/../config.php';
require_once __DIR__ . '/../lib/Mailer.php';
requireRole(['admin', 'recursos_humanos', 'analista']);

$db  = getDB();
$csrf = csrfToken();
$msg = '';
$error = '';

const ESTADOS = [
    'registrado'       => 'Registrado',
    'en_proceso'       => 'En proceso',
    'solicitado_banco' => 'Solicitado en Banco',
    'no_viable'        => 'No viable',
    'viable'           => 'Viable',
];
// Solo estos se pueden asignar manualmente — 'registrado' es automático
// del formulario público, nadie debe poder "regresar" un registro a ese
// estado desde el panel (perdería sentido el historial de progreso).
const ESTADOS_MANUALES = ['en_proceso', 'solicitado_banco', 'no_viable', 'viable'];

/**
 * Construye la cláusula WHERE + parámetros a partir de los filtros de
 * la URL (banco, estado, rango de fechas, ver_convertidos). Se usa
 * tanto para la tabla en pantalla como para las dos exportaciones
 * (CSV y ZIP de PDFs) — una sola fuente de verdad, para que lo que
 * ves en pantalla sea exactamente lo que se exporta.
 */
function construirFiltroVinculaciones(array $get): array {
    $where  = ["1=1"];
    $params = [];

    if (empty($get['ver_convertidos'])) {
        $where[] = "v.estado != 'viable'";
    }
    if (!empty($get['banco']) && $get['banco'] !== 'todos') {
        $where[] = "b.slug = ?";
        $params[] = $get['banco'];
    }
    if (!empty($get['estado']) && $get['estado'] !== 'todos' && array_key_exists($get['estado'], ESTADOS)) {
        $where[] = "v.estado = ?";
        $params[] = $get['estado'];
    }
    // Rango de fechas: opcional por diseño — se puede aplicar solo
    // "desde", solo "hasta", ambas, o ninguna.
    if (!empty($get['fecha_desde']) && preg_match('/^\d{4}-\d{2}-\d{2}$/', $get['fecha_desde'])) {
        $where[] = "v.created_at >= ?";
        $params[] = $get['fecha_desde'] . ' 00:00:00';
    }
    if (!empty($get['fecha_hasta']) && preg_match('/^\d{4}-\d{2}-\d{2}$/', $get['fecha_hasta'])) {
        $where[] = "v.created_at <= ?";
        $params[] = $get['fecha_hasta'] . ' 23:59:59';
    }

    return [implode(' AND ', $where), $params];
}

/**
 * Convierte una vinculación 'viable' en asesor + registro dentro de
 * Planta. Idempotente: si el asesor ya existe (misma cédula) o el
 * registro ya existe (mismo asesor+banco), actualiza en vez de duplicar.
 */
function convertirVinculacionAAsesor(PDO $db, array $vinc, int $usuarioId): array {
    $db->beginTransaction();
    try {
        $asesorSt = $db->prepare("SELECT id FROM asesores WHERE cedula = ?");
        $asesorSt->execute([$vinc['cedula']]);
        $asesorId = $asesorSt->fetchColumn();

        if ($asesorId) {
            $db->prepare("UPDATE asesores SET nombre=?, email=?, telefono=? WHERE id=?")
               ->execute([$vinc['nombres'], $vinc['email'], $vinc['telefono'], $asesorId]);
        } else {
            $db->prepare("INSERT INTO asesores (cedula, nombre, email, telefono, estado_contrato) VALUES (?,?,?,?,'ACTIVO')")
               ->execute([$vinc['cedula'], $vinc['nombres'], $vinc['email'], $vinc['telefono']]);
            $asesorId = (int)$db->lastInsertId();
        }

        $db->prepare("
            INSERT INTO registros (asesor_id, banco_id, campana_id, coordinador_id, estado, observaciones, crm)
            VALUES (?,?,?,?,'ACTIVO',?,'PENDIENTE VALIDAR')
            ON DUPLICATE KEY UPDATE campana_id=VALUES(campana_id), coordinador_id=VALUES(coordinador_id)
        ")->execute([
            $asesorId, $vinc['banco_id'], $vinc['campana_id'], $vinc['coordinador_id'],
            "Convertido automáticamente desde vinculación #{$vinc['id']}",
        ]);
        $registroSt = $db->prepare("SELECT id FROM registros WHERE asesor_id=? AND banco_id=?");
        $registroSt->execute([$asesorId, $vinc['banco_id']]);
        $registroId = (int)$registroSt->fetchColumn();

        $db->prepare("
            UPDATE vinculaciones
            SET asesor_id=?, registro_id=?, convertido_at=NOW(), convertido_por=?
            WHERE id=?
        ")->execute([$asesorId, $registroId, $usuarioId, $vinc['id']]);

        $db->commit();
        return ['asesor_id' => $asesorId, 'registro_id' => $registroId];
    } catch (\Throwable $e) {
        $db->rollBack();
        error_log('[convertirVinculacionAAsesor] ' . $e->getMessage());
        throw $e;
    }
}

/** Trae los datos necesarios para armar la notificación de cambio de estado. */
function datosParaNotificar(PDO $db, int $vincId): ?array {
    $st = $db->prepare("
        SELECT v.*, b.nombre AS banco_nombre
        FROM vinculaciones v JOIN bancos b ON b.id = v.banco_id
        WHERE v.id = ?
    ");
    $st->execute([$vincId]);
    $vinc = $st->fetch();
    if (!$vinc) return null;

    $coordSt = $db->prepare("SELECT email, nombre_completo, username FROM usuarios WHERE id = ?");
    $coordSt->execute([$vinc['coordinador_id']]);
    return ['vinc' => $vinc, 'coordinador' => $coordSt->fetch() ?: []];
}

function cambiarEstado(PDO $db, int $vincId, string $nuevoEstado, ?string $observaciones, int $usuarioId): void {
    if (!in_array($nuevoEstado, ESTADOS_MANUALES, true)) {
        throw new \InvalidArgumentException('Estado no permitido para asignación manual.');
    }

    $datos = datosParaNotificar($db, $vincId);
    if (!$datos) return;

    $upd = $db->prepare("UPDATE vinculaciones SET estado=?, observaciones_analista=? WHERE id=?");
    $upd->execute([$nuevoEstado, $observaciones, $vincId]);

    if ($nuevoEstado === 'viable') {
        convertirVinculacionAAsesor($db, $datos['vinc'], $usuarioId);
    }

    try {
        Mailer::notificarVinculacionCambioEstado(
            ['id' => $vincId, 'nombres' => $datos['vinc']['nombres'], 'email' => $datos['vinc']['email'], 'banco_nombre' => $datos['vinc']['banco_nombre']],
            $datos['coordinador'],
            ESTADOS[$nuevoEstado],
            $observaciones
        );
    } catch (\Throwable $e) {
        error_log('[cambiarEstado] Error notificando: ' . $e->getMessage());
    }
}

// ---- POST: acciones -----------------------------------------
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    verifyCsrf();
    $action = $_POST['action'] ?? '';

    if ($action === 'bulk_update_estado') {
        $ids = array_map('intval', $_POST['ids'] ?? []);
        $nuevoEstado = $_POST['nuevo_estado'] ?? '';
        if (empty($ids)) {
            $error = 'No seleccionaste ningún registro.';
        } elseif (!in_array($nuevoEstado, ESTADOS_MANUALES, true)) {
            $error = 'Estado inválido.';
        } else {
            $ok = 0; $fallos = 0;
            foreach ($ids as $id) {
                try {
                    cambiarEstado($db, $id, $nuevoEstado, null, (int)$_SESSION['user_id']);
                    $ok++;
                } catch (\Throwable $e) {
                    $fallos++;
                }
            }
            $msg = "Actualizados: {$ok}." . ($fallos ? " Fallaron: {$fallos} (revisa el log)." : '');
        }
    }

    if ($action === 'update_detalle') {
        $id = (int)($_POST['vinc_id'] ?? 0);
        $nuevoEstado = $_POST['estado'] ?? '';
        $obs = trim($_POST['observaciones'] ?? '') ?: null;
        try {
            cambiarEstado($db, $id, $nuevoEstado, $obs, (int)$_SESSION['user_id']);
            $msg = "Solicitud #{$id} actualizada.";
        } catch (\Throwable $e) {
            $error = 'No se pudo actualizar: ' . $e->getMessage();
        }
    }
}

// ---- Exportar CSV (respeta los mismos filtros que la tabla) -----
if (($_GET['action'] ?? '') === 'export') {
    [$whereSql, $params] = construirFiltroVinculaciones($_GET);
    $st = $db->prepare("
        SELECT v.id, v.nombres, v.cedula, v.email, v.telefono, v.ciudad, v.departamento,
               v.fecha_nacimiento, v.estado, v.created_at,
               u.nombre_completo AS coordinador, b.nombre AS banco
        FROM vinculaciones v
        JOIN bancos b ON b.id = v.banco_id
        LEFT JOIN usuarios u ON u.id = v.coordinador_id
        WHERE {$whereSql}
        ORDER BY v.created_at DESC
    ");
    $st->execute($params);
    $rows = $st->fetchAll();

    header('Content-Type: text/csv; charset=utf-8');
    header('Content-Disposition: attachment; filename="vinculaciones_' . date('Ymd_His') . '.csv"');
    $out = fopen('php://output', 'w');
    fputs($out, "\xEF\xBB\xBF"); // BOM para que Excel abra UTF-8 correctamente
    fputcsv($out, ['ID','Nombres','Cédula','Email','Teléfono','Ciudad','Departamento','Fecha Nacimiento','Coordinador','Banco','Estado','Fecha Registro']);
    foreach ($rows as $r) {
        fputcsv($out, [
            $r['id'], $r['nombres'], $r['cedula'], $r['email'], $r['telefono'], $r['ciudad'], $r['departamento'],
            $r['fecha_nacimiento'], $r['coordinador'], $r['banco'], ESTADOS[$r['estado']] ?? $r['estado'], $r['created_at'],
        ]);
    }
    fclose($out);
    exit;
}

// ---- Exportar ZIP con las copias de los documentos PDF ----------
// (respeta los mismos filtros que la tabla y el CSV)
if (($_GET['action'] ?? '') === 'export_zip_pdfs') {
    if (!class_exists('ZipArchive')) {
        http_response_code(500);
        die('Este servidor no tiene la extensión PHP "zip" habilitada. Pide a tu proveedor de hosting que la active (ext-zip), o contacta soporte técnico.');
    }

    [$whereSql, $params] = construirFiltroVinculaciones($_GET);
    $st = $db->prepare("
        SELECT v.id, v.nombres, v.cedula, v.documento_pdf_path
        FROM vinculaciones v
        JOIN bancos b ON b.id = v.banco_id
        WHERE {$whereSql} AND v.documento_pdf_path IS NOT NULL
        ORDER BY v.nombres
    ");
    $st->execute($params);
    $rows = $st->fetchAll();

    if (empty($rows)) {
        http_response_code(404);
        die('No hay documentos para descargar con los filtros aplicados.');
    }

    $baseDir = realpath(__DIR__ . '/../data/vinculaciones');
    $zipTmpPath = tempnam(sys_get_temp_dir(), 'vinczip_');
    $zip = new ZipArchive();
    if ($zip->open($zipTmpPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
        http_response_code(500);
        die('No se pudo crear el archivo ZIP.');
    }

    $usados = []; // para evitar colisión de nombres si dos personas comparten cédula (no debería pasar, pero por defensa)
    foreach ($rows as $r) {
        $rutaReal = realpath(__DIR__ . '/../' . $r['documento_pdf_path']);
        // Misma defensa contra path traversal que descargar.php: el
        // archivo resuelto DEBE quedar dentro de data/vinculaciones.
        if ($rutaReal === false || $baseDir === false || !str_starts_with($rutaReal, $baseDir) || !is_file($rutaReal)) {
            error_log("[export_zip_pdfs] Ruta inválida o archivo faltante para vinculación id={$r['id']}");
            continue;
        }
        $cedulaLimpia = preg_replace('/[^0-9]/', '', $r['cedula']);
        $nombreEnZip = $cedulaLimpia . '.pdf';
        $sufijo = 1;
        while (in_array($nombreEnZip, $usados, true)) {
            $nombreEnZip = $cedulaLimpia . '_' . (++$sufijo) . '.pdf';
        }
        $usados[] = $nombreEnZip;
        $zip->addFile($rutaReal, $nombreEnZip);
    }
    $zip->close();

    header('Content-Type: application/zip');
    header('Content-Disposition: attachment; filename="documentos_vinculacion_' . date('Ymd_His') . '.zip"');
    header('Content-Length: ' . filesize($zipTmpPath));
    readfile($zipTmpPath);
    unlink($zipTmpPath);
    exit;
}

// ---- Datos para la vista --------------------------------------
$bancos = $db->query("SELECT id, nombre, slug, color FROM bancos ORDER BY id")->fetchAll();

$mostrarConvertidos = !empty($_GET['ver_convertidos']);
$bancoSeleccionado  = $_GET['banco'] ?? 'todos';
$estadoSeleccionado = $_GET['estado'] ?? 'todos';
$fechaDesde = $_GET['fecha_desde'] ?? '';
$fechaHasta = $_GET['fecha_hasta'] ?? '';

[$whereSql, $paramsVista] = construirFiltroVinculaciones($_GET);
$vincSt = $db->prepare("
    SELECT v.id, v.banco_id, v.nombres, v.cedula, v.email, v.telefono, v.estado, v.created_at,
           v.documento_pdf_nombre_original, v.observaciones_analista,
           u.nombre_completo AS coordinador_nombre, b.slug AS banco_slug
    FROM vinculaciones v
    JOIN bancos b ON b.id = v.banco_id
    LEFT JOIN usuarios u ON u.id = v.coordinador_id
    WHERE {$whereSql}
    ORDER BY v.created_at DESC
");
$vincSt->execute($paramsVista);
$vinculaciones = $vincSt->fetchAll();
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Vinculaciones · Wicapital Planta</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style>
<?php include __DIR__ . '/../assets/styles-base.css.php'; ?>
body{padding:24px}
h1{font-size:20px;font-weight:700;margin-bottom:16px}
.filter-bar{display:flex;align-items:flex-end;gap:12px;margin-bottom:16px;flex-wrap:wrap;background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:14px 16px}
.filter-group{display:flex;flex-direction:column;gap:4px}
.filter-group label{font-size:11px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.03em}
.toolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:12px;flex-wrap:wrap}
.bulk-bar{display:none;align-items:center;gap:10px;background:var(--surface2);border:1px solid var(--border2);border-radius:10px;padding:8px 14px}
.bulk-bar.show{display:flex}
select,button.btn,input[type=text],input[type=date]{font-family:'Inter',sans-serif;font-size:13px}
select,input[type=text],input[type=date]{background:var(--bg);border:1.5px solid var(--border);border-radius:8px;padding:8px 10px;color:var(--text)}
button.btn{background:linear-gradient(135deg,var(--primary),var(--primary-light));color:#fff;border:none;border-radius:8px;padding:8px 16px;font-weight:600;cursor:pointer}
button.btn-outline{background:transparent;border:1.5px solid var(--border2);color:var(--text2);border-radius:8px;padding:8px 16px;font-weight:600;cursor:pointer}
table.grid{width:100%;border-collapse:collapse;background:var(--surface);border-radius:12px;overflow:hidden}
table.grid th{background:var(--surface2);text-align:left;padding:10px 12px;font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);border-bottom:1px solid var(--border)}
table.grid td{padding:10px 12px;font-size:13px;border-bottom:1px solid var(--border);color:var(--text2)}
table.grid tr:hover td{background:var(--surface2)}
.badge-estado{padding:3px 10px;border-radius:100px;font-size:11px;font-weight:700;letter-spacing:.02em}
.e-registrado{background:#1e3a5f;color:#93c5fd}
.e-en_proceso{background:#3f2f0d;color:#fbbf24}
.e-solicitado_banco{background:#33235c;color:#c4b5fd}
.e-no_viable{background:#450a0a;color:#f87171}
.e-viable{background:#052e16;color:#4ade80}
.alert{border-radius:10px;padding:12px 16px;font-size:13px;margin-bottom:16px}
.alert-error{background:#450a0a;color:#f87171;border:1px solid #991b1b}
.alert-success{background:#052e16;color:#4ade80;border:1px solid #166534}
.modal-overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:100;align-items:center;justify-content:center}
.modal-overlay.show{display:flex}
.modal-box{background:var(--surface);border:1px solid var(--border2);border-radius:16px;padding:28px;max-width:520px;width:92%;max-height:88vh;overflow-y:auto}
.modal-box h2{font-size:17px;margin-bottom:16px}
.modal-box label{display:block;font-size:12px;font-weight:600;color:var(--muted);margin:12px 0 4px}
.modal-box .ro{font-size:13px;color:var(--text2)}
textarea{width:100%;background:var(--bg);border:1.5px solid var(--border);border-radius:8px;padding:10px;color:var(--text);font-family:'Inter',sans-serif;font-size:13px;box-sizing:border-box}
.modal-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:20px}
.link-pdf{color:var(--primary-light);font-size:12px}
.topbar{display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;flex-wrap:wrap;gap:10px}
.topbar-left{display:flex;align-items:center;gap:14px}
.topbar-left h1{margin:0}
.topbar-right{display:flex;align-items:center;gap:10px}
.user-chip{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--text2);background:var(--surface2);border:1px solid var(--border);border-radius:100px;padding:5px 12px 5px 5px}
.user-avatar{width:24px;height:24px;border-radius:50%;background:var(--primary);color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:700}
</style>
</head>
<body>
<div class="topbar">
    <div class="topbar-left">
        <h1>📋 Vinculaciones</h1>
    </div>
    <div class="topbar-right">
        <?php if (($_SESSION['rol'] ?? '') === 'admin' || ($_SESSION['rol'] ?? '') === 'recursos_humanos'): ?>
        <a href="/admin/index.php" class="btn-outline">← Panel Admin</a>
        <?php endif; ?>
        <div class="user-chip">
            <div class="user-avatar"><?= sanitizeOutput(strtoupper(substr($_SESSION['username'] ?? '?', 0, 2))) ?></div>
            <?= sanitizeOutput($_SESSION['username'] ?? '') ?>
        </div>
        <a href="/logout.php" class="btn-outline">Salir</a>
    </div>
</div>

<?php if ($msg): ?><div class="alert alert-success"><?= sanitizeOutput($msg) ?></div><?php endif; ?>
<?php if ($error): ?><div class="alert alert-error"><?= sanitizeOutput($error) ?></div><?php endif; ?>

<form method="GET" class="filter-bar" id="filter-form">
    <div class="filter-group">
        <label>Banco</label>
        <select name="banco">
            <option value="todos" <?= $bancoSeleccionado === 'todos' ? 'selected' : '' ?>>Todos</option>
            <?php foreach ($bancos as $b): ?>
            <option value="<?= sanitizeOutput($b['slug']) ?>" <?= $bancoSeleccionado === $b['slug'] ? 'selected' : '' ?>><?= sanitizeOutput($b['nombre']) ?></option>
            <?php endforeach; ?>
        </select>
    </div>
    <div class="filter-group">
        <label>Estado</label>
        <select name="estado">
            <option value="todos" <?= $estadoSeleccionado === 'todos' ? 'selected' : '' ?>>Todos</option>
            <?php foreach (ESTADOS as $k => $v): ?>
            <option value="<?= $k ?>" <?= $estadoSeleccionado === $k ? 'selected' : '' ?>><?= sanitizeOutput($v) ?></option>
            <?php endforeach; ?>
        </select>
    </div>
    <div class="filter-group">
        <label>Desde (opcional)</label>
        <input type="date" name="fecha_desde" value="<?= sanitizeOutput($fechaDesde) ?>">
    </div>
    <div class="filter-group">
        <label>Hasta (opcional)</label>
        <input type="date" name="fecha_hasta" value="<?= sanitizeOutput($fechaHasta) ?>">
    </div>
    <?php if ($mostrarConvertidos): ?><input type="hidden" name="ver_convertidos" value="1"><?php endif; ?>
    <button type="submit" class="btn">Aplicar filtros</button>
    <?php if ($bancoSeleccionado !== 'todos' || $estadoSeleccionado !== 'todos' || $fechaDesde || $fechaHasta): ?>
    <a href="?<?= $mostrarConvertidos ? 'ver_convertidos=1' : '' ?>" class="btn-outline">Limpiar filtros</a>
    <?php endif; ?>
</form>

<div class="toolbar">
    <div class="bulk-bar" id="bulk-bar">
        <span id="bulk-count" style="font-size:13px;color:var(--text2)"></span>
        <select id="bulk-estado">
            <?php foreach (ESTADOS_MANUALES as $e): ?>
            <option value="<?= $e ?>"><?= sanitizeOutput(ESTADOS[$e]) ?></option>
            <?php endforeach; ?>
        </select>
        <button class="btn" onclick="aplicarBulk()">Aplicar a seleccionados</button>
    </div>
    <div style="display:flex;gap:8px">
        <label style="font-size:12px;color:var(--muted);display:flex;align-items:center;gap:6px">
            <input type="checkbox" id="chk-convertidos" <?= $mostrarConvertidos ? 'checked' : '' ?> onchange="toggleConvertidos(this)">
            Ver convertidos a asesor
        </label>
        <button class="btn-outline" id="btn-exportar" onclick="exportarDatos()">⬇ Exportar</button>
    </div>
</div>

<table class="grid">
    <thead>
        <tr>
            <th style="width:30px"><input type="checkbox" onclick="toggleTodos(this)"></th>
            <th>Nombres</th>
            <th>Cédula</th>
            <th>Banco</th>
            <th>Coordinador</th>
            <th>Estado</th>
            <th>Fecha</th>
            <th></th>
        </tr>
    </thead>
    <tbody id="tabla-body">
        <?php foreach ($vinculaciones as $v): ?>
        <tr>
            <td><input type="checkbox" class="row-chk" value="<?= $v['id'] ?>" onchange="actualizarBulkBar()"></td>
            <td><?= sanitizeOutput($v['nombres']) ?></td>
            <td><?= sanitizeOutput($v['cedula']) ?></td>
            <td><?= sanitizeOutput($v['banco_slug']) ?></td>
            <td><?= sanitizeOutput($v['coordinador_nombre'] ?? '—') ?></td>
            <td><span class="badge-estado e-<?= $v['estado'] ?>"><?= sanitizeOutput(ESTADOS[$v['estado']] ?? $v['estado']) ?></span></td>
            <td><?= date('d/m/Y', strtotime($v['created_at'])) ?></td>
            <td>
                <button class="btn-outline" style="padding:5px 12px;font-size:12px"
                    onclick='abrirDetalle(<?= json_encode([
                        'id' => $v['id'], 'nombres' => $v['nombres'], 'cedula' => $v['cedula'],
                        'email' => $v['email'], 'telefono' => $v['telefono'], 'estado' => $v['estado'],
                        'observaciones' => $v['observaciones_analista'], 'pdf' => $v['documento_pdf_nombre_original'],
                    ], JSON_HEX_APOS | JSON_HEX_QUOT) ?>)'>Ver / Editar</button>
            </td>
        </tr>
        <?php endforeach; ?>
        <?php if (empty($vinculaciones)): ?>
        <tr><td colspan="8" style="text-align:center;color:var(--muted);padding:30px">No hay solicitudes de vinculación con estos filtros.</td></tr>
        <?php endif; ?>
    </tbody>
</table>

<!-- Modal detalle / edición -->
<div class="modal-overlay" id="modal-detalle">
    <div class="modal-box">
        <h2>Solicitud #<span id="md-id"></span></h2>
        <form method="POST">
            <input type="hidden" name="_csrf" value="<?= sanitizeOutput($csrf) ?>">
            <input type="hidden" name="action" value="update_detalle">
            <input type="hidden" name="vinc_id" id="md-vinc-id">

            <label>Nombres</label><div class="ro" id="md-nombres"></div>
            <label>Cédula</label><div class="ro" id="md-cedula"></div>
            <label>Email</label><div class="ro" id="md-email"></div>
            <label>Teléfono</label><div class="ro" id="md-telefono"></div>
            <label>Documento</label><div class="ro"><a class="link-pdf" id="md-pdf" href="#" target="_blank">Ver PDF cargado</a></div>

            <label>Estado</label>
            <select name="estado" id="md-estado">
                <?php foreach (ESTADOS_MANUALES as $e): ?>
                <option value="<?= $e ?>"><?= sanitizeOutput(ESTADOS[$e]) ?></option>
                <?php endforeach; ?>
            </select>

            <label>Observaciones</label>
            <textarea name="observaciones" id="md-observaciones" rows="3"></textarea>

            <div class="modal-actions">
                <button type="button" class="btn-outline" onclick="cerrarDetalle()">Cancelar</button>
                <button type="submit" class="btn">Guardar</button>
            </div>
        </form>
    </div>
</div>

<script>
function toggleConvertidos(chk) {
    const url = new URL(window.location.href);
    if (chk.checked) { url.searchParams.set('ver_convertidos', '1'); }
    else { url.searchParams.delete('ver_convertidos'); }
    window.location.href = url.toString();
}

function toggleTodos(master) {
    document.querySelectorAll('.row-chk').forEach(chk => chk.checked = master.checked);
    actualizarBulkBar();
}

function actualizarBulkBar() {
    const seleccionados = document.querySelectorAll('.row-chk:checked').length;
    const bar = document.getElementById('bulk-bar');
    if (seleccionados > 0) {
        bar.classList.add('show');
        document.getElementById('bulk-count').textContent = seleccionados + ' seleccionado(s)';
    } else {
        bar.classList.remove('show');
    }
}

function aplicarBulk() {
    const ids = Array.from(document.querySelectorAll('.row-chk:checked')).map(c => c.value);
    if (ids.length === 0) return;
    const estado = document.getElementById('bulk-estado').value;
    const estadoTexto = document.getElementById('bulk-estado').selectedOptions[0].text;
    if (!confirm('¿Cambiar ' + ids.length + ' solicitud(es) a "' + estadoTexto + '"? Esto enviará un correo a cada ejecutivo y coordinador afectado.')) return;

    const form = document.createElement('form');
    form.method = 'POST';
    let inner = '<input type="hidden" name="_csrf" value="<?= sanitizeOutput($csrf) ?>">';
    inner += '<input type="hidden" name="action" value="bulk_update_estado">';
    inner += '<input type="hidden" name="nuevo_estado" value="' + estado + '">';
    ids.forEach(id => { inner += '<input type="hidden" name="ids[]" value="' + id + '">'; });
    form.innerHTML = inner;
    document.body.appendChild(form);
    form.submit();
}

function abrirDetalle(d) {
    document.getElementById('md-id').textContent = d.id;
    document.getElementById('md-vinc-id').value = d.id;
    document.getElementById('md-nombres').textContent = d.nombres;
    document.getElementById('md-cedula').textContent = d.cedula;
    document.getElementById('md-email').textContent = d.email;
    document.getElementById('md-telefono').textContent = d.telefono;
    document.getElementById('md-estado').value = d.estado;
    document.getElementById('md-observaciones').value = d.observaciones || '';
    document.getElementById('md-pdf').href = 'descargar.php?id=' + d.id;
    document.getElementById('modal-detalle').classList.add('show');
}
function cerrarDetalle() {
    document.getElementById('modal-detalle').classList.remove('show');
}

function exportarDatos() {
    const incluirPdfs = confirm('¿También necesitas las copias de los documentos en PDF de los registros filtrados?\n\nAceptar = sí, descargar además un ZIP con los PDFs\nCancelar = solo el archivo de datos (Excel/CSV)');

    const qs = new URLSearchParams(window.location.search);
    qs.set('action', 'export');
    window.location.href = '?' + qs.toString();

    if (incluirPdfs) {
        setTimeout(() => {
            const qs2 = new URLSearchParams(window.location.search);
            qs2.set('action', 'export_zip_pdfs');
            window.location.href = '?' + qs2.toString();
        }, 900);
    }
}
</script>
</body>
</html>