<?php
/**
 * modules/turnero/views/historial.php
 * Historial consultable de turnos con filtros multi-día y paginación.
 */
require_once APP_ROOT . '/config/config.php';
if (!isUserLoggedIn()) { header('Location: ' . BASE_URL . 'login.php'); exit; }

Layout::open('Historial de Turnos', 'fas fa-history');
?>
<style>
    body { background:#f1f5f9; }

    /* ── Encabezado ── */
    .page-header {
        background:#fff; border-bottom:1px solid #e2e8f0;
        padding:12px 22px; display:flex; align-items:center; gap:10px; flex-wrap:wrap;
    }
    .page-header h1 { font-size:1.12rem; font-weight:700; color:#1e293b; margin:0; flex:1; min-width:150px; }

    /* ── Filtros ── */
    .filter-bar {
        background:#fff; border-bottom:1px solid #e2e8f0;
        padding:12px 22px; display:flex; align-items:flex-end; gap:10px; flex-wrap:wrap;
    }
    .filter-group { display:flex; flex-direction:column; gap:3px; }
    .filter-group label { font-size:.7rem; font-weight:600; text-transform:uppercase;
                          letter-spacing:.06em; color:#64748b; }
    .filter-group .form-control,
    .filter-group .form-select { font-size:.82rem; min-width:120px; }
    .filter-group.wide .form-control { min-width:200px; }

    /* ── Contenido ── */
    .content-wrap { max-width:1200px; margin:22px auto; padding:0 16px 60px; }

    /* ── KPIs resumen ── */
    .kpi-strip {
        display:flex; flex-wrap:wrap; gap:10px; margin-bottom:18px;
    }
    .kpi-chip {
        display:flex; align-items:center; gap:7px;
        background:#fff; border:1px solid #e2e8f0; border-radius:99px;
        padding:5px 14px; font-size:.8rem;
    }
    .kpi-chip .chip-val { font-weight:800; font-size:1rem; }
    .kpi-chip .chip-lbl { color:#64748b; }

    /* ── Tabla ── */
    .section-card { background:#fff; border:1px solid #e2e8f0; border-radius:12px;
                    padding:0; overflow:hidden; }
    .section-card .table { margin:0; }
    .section-card .table thead th {
        background:#f8fafc; font-size:.7rem; text-transform:uppercase;
        letter-spacing:.07em; color:#475569; font-weight:700;
        padding:10px 12px; white-space:nowrap; border-bottom:2px solid #e2e8f0;
    }
    .section-card .table tbody td { padding:9px 12px; font-size:.82rem; vertical-align:middle; }
    .section-card .table tbody tr:hover { background:#f8fafc; }

    /* ── Estado badges ── */
    .eb { font-size:.65rem; padding:2px 8px; border-radius:99px; font-weight:700; white-space:nowrap; }
    .eb-espera          { background:#fef9c3; color:#78350f; }
    .eb-en_recepcion    { background:#dbeafe; color:#1e40af; }
    .eb-en_espera_lugar { background:#fde68a; color:#92400e; }
    .eb-en_servicio     { background:#dcfce7; color:#166534; }
    .eb-finalizado      { background:#f1f5f9; color:#334155; }
    .eb-ausente         { background:#fee2e2; color:#991b1b; }
    .eb-cancelado       { background:#f1f5f9; color:#9ca3af; }

    /* ── Paginación ── */
    .pagination-wrap {
        display:flex; align-items:center; justify-content:space-between;
        padding:12px 18px; border-top:1px solid #e2e8f0; flex-wrap:wrap; gap:8px;
    }
    .pagination-info { font-size:.78rem; color:#64748b; }
    .page-btns { display:flex; gap:4px; }
    .page-btns button { font-size:.78rem; padding:3px 10px; border-radius:6px;
                        border:1px solid #e2e8f0; background:#fff; cursor:pointer; }
    .page-btns button.active { background:var(--brand,#2563eb); color:#fff; border-color:var(--brand,#2563eb); }
    .page-btns button:disabled { opacity:.4; cursor:default; }

    /* ── Estado vacío ── */
    .empty-state { text-align:center; color:#94a3b8; padding:60px 20px; font-size:.9rem; }
    .empty-state i { font-size:2.5rem; display:block; margin-bottom:10px; }

    /* ── Spinner ── */
    .spinner-row td { text-align:center; padding:40px; color:#94a3b8; }

    /* ── Detalle expandible ── */
    .detail-row { background:#f8fafc; }
    .detail-row td { padding:0 !important; }
    .detail-body { padding:10px 18px 14px; }
    .detail-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(160px,1fr)); gap:8px; }
    .detail-item { background:#fff; border:1px solid #e2e8f0; border-radius:8px; padding:8px 12px; }
    .detail-item .d-lbl { font-size:.67rem; text-transform:uppercase; letter-spacing:.07em; color:#94a3b8; }
    .detail-item .d-val { font-size:.85rem; font-weight:600; color:#1e293b; }

    /* ── Exámenes y comentarios ── */
    .detail-extra { margin-top:10px; padding-top:10px; border-top:1px solid #e2e8f0; }
    .detail-extra .d-lbl { font-size:.67rem; text-transform:uppercase; letter-spacing:.07em; color:#94a3b8; margin-bottom:5px; }
    .detail-comment { padding:5px 0; border-bottom:1px solid #f1f5f9; font-size:.82rem; }
    .detail-comment:last-child { border-bottom:none; }

    /* ── Documentos firmados ── */
    .docs-section { margin-top:10px; padding-top:10px; border-top:1px solid #e2e8f0; }
    .docs-lbl { font-size:.65rem; font-weight:700; text-transform:uppercase; letter-spacing:.07em; color:#94a3b8; margin-bottom:5px; }
    .doc-pill { display:inline-flex; align-items:center; gap:4px; padding:3px 10px; border-radius:99px;
                font-size:.73rem; font-weight:600; margin:2px 2px; text-decoration:none; transition:opacity .15s; }
    .doc-pill:hover { opacity:.8; }
    .doc-pill.firmado  { background:#dcfce7; color:#166534; border:1px solid #bbf7d0; }
    .doc-pill.enviado  { background:#fef9c3; color:#78350f; border:1px solid #fde68a; }
    .doc-pill.pendiente{ background:#f1f5f9; color:#64748b; border:1px solid #e2e8f0; }
    .docs-empty { font-size:.78rem; color:#94a3b8; font-style:italic; }
</style>

<!-- ── Encabezado ────────────────────────────────────────────── -->
<div class="page-header">
    <a href="<?= BASE_URL ?>erp.php?m=turnero&v=dashboard" class="text-muted text-decoration-none small">
        <i class="fas fa-arrow-left me-1"></i>Dashboard
    </a>
    <h1><i class="fas fa-history me-2 text-primary"></i>Historial de Turnos</h1>
    <button class="btn btn-outline-success btn-sm" id="btnExport" title="Exportar CSV">
        <i class="fas fa-file-csv me-1"></i>Exportar CSV
    </button>
</div>

<!-- ── Barra de filtros ──────────────────────────────────────── -->
<div class="filter-bar">
    <div class="filter-group">
        <label>Desde</label>
        <input type="date" id="fDesde" class="form-control form-control-sm">
    </div>
    <div class="filter-group">
        <label>Hasta</label>
        <input type="date" id="fHasta" class="form-control form-control-sm">
    </div>
    <div class="filter-group">
        <label>Estado</label>
        <select id="fEstado" class="form-select form-select-sm">
            <option value="">Todos</option>
            <option value="finalizado">Finalizado</option>
            <option value="ausente">Ausente</option>
            <option value="cancelado">Cancelado</option>
            <option value="en_servicio">En servicio</option>
            <option value="en_espera_lugar">Esp. lugar</option>
            <option value="en_recepcion">En recepción</option>
            <option value="espera">En espera</option>
        </select>
    </div>
    <div class="filter-group" id="wrapLugar">
        <label>Lugar</label>
        <select id="fLugar" class="form-select form-select-sm">
            <option value="0">Todos</option>
        </select>
    </div>
    <div class="filter-group" id="wrapPrioridad">
        <label>Prioridad</label>
        <select id="fPrioridad" class="form-select form-select-sm">
            <option value="0">Todas</option>
        </select>
    </div>
    <div class="filter-group wide">
        <label>Buscar paciente / código</label>
        <input type="text" id="fQ" class="form-control form-control-sm" placeholder="Nombre o código…">
    </div>
    <button class="btn btn-primary btn-sm align-self-end" id="btnBuscar">
        <i class="fas fa-search me-1"></i>Buscar
    </button>
    <button class="btn btn-outline-secondary btn-sm align-self-end" id="btnHoy" title="Solo hoy">
        Hoy
    </button>
    <button class="btn btn-outline-secondary btn-sm align-self-end" id="btn7d" title="Últimos 7 días">
        7 días
    </button>
    <button class="btn btn-outline-secondary btn-sm align-self-end" id="btn30d" title="Últimos 30 días">
        30 días
    </button>
</div>

<!-- ── Contenido ──────────────────────────────────────────────── -->
<div class="content-wrap">

    <!-- Resumen por estado del rango -->
    <div class="kpi-strip" id="kpiStrip" style="display:none"></div>

    <!-- Tabla principal -->
    <div class="section-card">
        <div class="table-responsive">
            <table class="table table-hover align-middle" id="tablaHistorial">
                <thead>
                    <tr>
                        <th>Fecha</th>
                        <th>Código</th>
                        <th>Prioridad</th>
                        <th>Paciente</th>
                        <th>Recepción</th>
                        <th>Lugar / Bacteriólogo</th>
                        <th>Exámenes</th>
                        <th>Estado</th>
                        <th>Espera</th>
                        <th>Servicio</th>
                        <th></th>
                    </tr>
                </thead>
                <tbody id="tbody">
                    <tr class="spinner-row">
                        <td colspan="11"><i class="fas fa-spinner fa-spin me-2"></i>Cargando…</td>
                    </tr>
                </tbody>
            </table>
        </div>

        <!-- Paginación -->
        <div class="pagination-wrap" id="paginacionWrap" style="display:none">
            <div class="pagination-info" id="paginacionInfo"></div>
            <div class="page-btns" id="pagBtns"></div>
        </div>
    </div>
</div>

<script>
/* ═══════════════════════════════════════════════════════════
   Historial de Turnos
   ═══════════════════════════════════════════════════════════ */
const API = '<?= BASE_URL ?>modules/turnero/api/';

let _state = {
    fechaDesde : '',
    fechaHasta : '',
    estado     : '',
    lugarId    : 0,
    prioridadId: 0,
    q          : '',
    page       : 1,
    perPage    : 50,
    totalPages : 1,
    total      : 0,
};

// ── Utilidades ────────────────────────────────────────────────
const esc = s => (s == null ? '' : String(s))
    .replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')
    .replace(/"/g,'&quot;').replace(/'/g,'&#39;');

function hoy()  { return new Date().toISOString().slice(0,10); }
function hace(n){ return new Date(Date.now()-n*86400000).toISOString().slice(0,10); }

// ── Inicialización ────────────────────────────────────────────
document.addEventListener('DOMContentLoaded', async () => {
    // Fecha por defecto: últimos 7 días
    document.getElementById('fDesde').value  = hace(6);
    document.getElementById('fHasta').value  = hoy();
    document.getElementById('fHasta').max    = hoy();

    // Cargar catálogos (lugares + prioridades)
    await cargarMeta();

    // Primera carga
    buscar();

    // Eventos
    document.getElementById('btnBuscar').addEventListener('click', buscar);
    document.getElementById('fQ').addEventListener('keydown', e => { if (e.key==='Enter') buscar(); });
    document.getElementById('btnExport').addEventListener('click', exportarCSV);

    document.getElementById('btnHoy').addEventListener('click', () => {
        document.getElementById('fDesde').value = hoy();
        document.getElementById('fHasta').value = hoy();
        buscar();
    });
    document.getElementById('btn7d').addEventListener('click', () => {
        document.getElementById('fDesde').value = hace(6);
        document.getElementById('fHasta').value = hoy();
        buscar();
    });
    document.getElementById('btn30d').addEventListener('click', () => {
        document.getElementById('fDesde').value = hace(29);
        document.getElementById('fHasta').value = hoy();
        buscar();
    });
});

// ── Catálogos ─────────────────────────────────────────────────
async function cargarMeta() {
    try {
        const res  = await fetch(`${API}get_historial.php?meta=1&fecha_desde=${hoy()}&fecha_hasta=${hoy()}&per_page=1`);
        const json = await res.json();
        if (!json.ok) return;

        const selLugar = document.getElementById('fLugar');
        (json.meta.lugares || []).forEach(l => {
            const o = document.createElement('option');
            o.value = l.id; o.textContent = l.nombre;
            selLugar.appendChild(o);
        });

        const selPri = document.getElementById('fPrioridad');
        (json.meta.prioridades || []).forEach(p => {
            const o = document.createElement('option');
            o.value = p.id;
            o.textContent = `${p.codigo} — ${p.nombre}`;
            selPri.appendChild(o);
        });
    } catch(_) {}
}

// ── Búsqueda principal ────────────────────────────────────────
function buscar(pageNum) {
    _state.fechaDesde  = document.getElementById('fDesde').value     || hace(6);
    _state.fechaHasta  = document.getElementById('fHasta').value     || hoy();
    _state.estado      = document.getElementById('fEstado').value;
    _state.lugarId     = parseInt(document.getElementById('fLugar').value)    || 0;
    _state.prioridadId = parseInt(document.getElementById('fPrioridad').value)|| 0;
    _state.q           = document.getElementById('fQ').value.trim();
    _state.page        = pageNum || 1;

    cargarPagina();
}

async function cargarPagina() {
    mostrarSpinner();
    const params = new URLSearchParams({
        fecha_desde  : _state.fechaDesde,
        fecha_hasta  : _state.fechaHasta,
        estado       : _state.estado,
        lugar_id     : _state.lugarId,
        prioridad_id : _state.prioridadId,
        q            : _state.q,
        page         : _state.page,
        per_page     : _state.perPage,
    });

    try {
        const res  = await fetch(`${API}get_historial.php?${params}`);
        const json = await res.json();
        if (!json.ok) { mostrarError(json.error || 'Error al cargar historial'); return; }

        _state.totalPages = json.total_pages;
        _state.total      = json.total;
        _state.page       = json.page;

        renderKpis(json.resumen_estados);
        renderTabla(json.turnos);
        renderPaginacion();
    } catch(e) {
        mostrarError('Error de conexión');
    }
}

// ── KPIs de resumen ───────────────────────────────────────────
const ESTADO_META = {
    finalizado      : { lbl:'Finalizados',    bg:'#f1f5f9', color:'#334155' },
    ausente         : { lbl:'Ausentes',       bg:'#fee2e2', color:'#991b1b' },
    cancelado       : { lbl:'Cancelados',     bg:'#f1f5f9', color:'#9ca3af' },
    en_servicio     : { lbl:'En servicio',    bg:'#dcfce7', color:'#166534' },
    en_espera_lugar : { lbl:'Esp. lugar',     bg:'#fde68a', color:'#92400e' },
    en_recepcion    : { lbl:'En recepción',   bg:'#dbeafe', color:'#1e40af' },
    espera          : { lbl:'En espera',      bg:'#fef9c3', color:'#78350f' },
};

function renderKpis(resumen) {
    const strip = document.getElementById('kpiStrip');
    let total = Object.values(resumen).reduce((a,b)=>a+(+b),0);
    if (!total) { strip.style.display='none'; return; }

    strip.style.display = 'flex';
    strip.innerHTML = `
        <div class="kpi-chip">
            <span class="chip-val">${total}</span>
            <span class="chip-lbl">turnos (rango)</span>
        </div>
        ${Object.entries(resumen).map(([est,cnt]) => {
            const m = ESTADO_META[est] || {lbl:est, bg:'#f1f5f9', color:'#334155'};
            return `<div class="kpi-chip" style="border-color:${m.color}22">
                <span class="chip-val" style="color:${m.color}">${cnt}</span>
                <span class="chip-lbl">${m.lbl}</span>
            </div>`;
        }).join('')}
    `;
}

// ── Tabla ─────────────────────────────────────────────────────
const ESTADO_CLS = {
    espera:'eb-espera', en_recepcion:'eb-en_recepcion', en_espera_lugar:'eb-en_espera_lugar',
    en_servicio:'eb-en_servicio', finalizado:'eb-finalizado', ausente:'eb-ausente', cancelado:'eb-cancelado',
};
const ESTADO_LBL = {
    espera:'Espera', en_recepcion:'Recepción', en_espera_lugar:'Esp. lugar',
    en_servicio:'En servicio', finalizado:'Finalizado', ausente:'Ausente', cancelado:'Cancelado',
};

function renderTabla(turnos) {
    const tbody = document.getElementById('tbody');
    if (!turnos.length) {
        tbody.innerHTML = `<tr><td colspan="11">
            <div class="empty-state"><i class="fas fa-search"></i>Sin resultados para los filtros aplicados</div>
        </td></tr>`;
        return;
    }

    tbody.innerHTML = turnos.map((t,i) => {
        const nombre  = esc(t.paciente_bd || t.paciente_nombre || '—');
        const lugar   = esc(t.lugar_nombre || '—');
        const fecha   = t.fecha_sesion || '—';
        const horaEnt = t.creado_at
            ? new Date(t.creado_at.replace(' ','T'))
                .toLocaleString('es-CO',{hour:'2-digit',minute:'2-digit'})
            : '—';
        const espMin  = t.espera_min    != null ? t.espera_min    + ' m' : '—';
        const srvMin  = t.servicio_min  != null ? t.servicio_min  + ' m' : '—';
        const tel     = esc(t.paciente_cel || '—');
        const priCls  = esc(t.prioridad_color || '#888');
        const cls     = ESTADO_CLS[t.estado] || 'eb-finalizado';
        const lbl     = ESTADO_LBL[t.estado] || t.estado;
        const rowId   = `det-${t.id}`;

        // Recepción: desk + recepcionista
        const desk     = esc(t.recepcion_desk_nombre || '—');
        const recep    = esc(t.atendido_recepcion_nombre || '—');
        const bacterio = esc(t.atendido_lugar_nombre || '—');

        // Exámenes: badges con código
        const examsHtml = (t.examenes && t.examenes.length)
            ? t.examenes.map(e => `<span class="badge bg-success-subtle text-success me-1 mb-1" style="font-size:.65rem">${esc(e.codigo)}</span>`).join('')
            : '<span class="text-muted small">—</span>';

        return `<tr data-id="${t.id}">
            <td class="text-nowrap text-muted small">${esc(fecha)}</td>
            <td><strong style="color:${priCls}">${esc(t.codigo)}</strong></td>
            <td>
                <span class="eb" style="background:${priCls}22;color:${priCls}">
                    ${esc(t.prioridad_codigo)}
                </span>
            </td>
            <td>${nombre}</td>
            <td class="small">
                <div class="text-muted" style="font-size:.72rem"><i class="fas fa-desktop me-1 opacity-50"></i>${desk}</div>
                <div><i class="fas fa-user-tie me-1 opacity-50" style="font-size:.72rem"></i>${recep}</div>
            </td>
            <td class="small">
                <div class="fw-semibold">${lugar}</div>
                <div class="text-muted" style="font-size:.72rem"><i class="fas fa-microscope me-1 opacity-50"></i>${bacterio}</div>
            </td>
            <td style="max-width:140px">${examsHtml}</td>
            <td><span class="eb ${cls}">${lbl}</span></td>
            <td class="text-nowrap">${espMin}</td>
            <td class="text-nowrap">${srvMin}</td>
            <td>
                <button class="btn btn-sm btn-outline-secondary py-0 px-2"
                        onclick="toggleDetalle('${rowId}', this, ${t.id})"
                        title="Ver detalles">
                    <i class="fas fa-chevron-down" style="font-size:.65rem"></i>
                </button>
            </td>
        </tr>
        <tr id="${rowId}" class="detail-row" style="display:none">
            <td colspan="11">
                <div class="detail-body">
                    ${renderDetalle(t)}
                </div>
            </td>
        </tr>`;
    }).join('');
}

function renderDetalle(t) {
    const fmt = dt => {
        if (!dt) return '—';
        const d = new Date(dt.replace(' ','T'));
        return d.toLocaleString('es-CO',{dateStyle:'short',timeStyle:'short'});
    };
    const items = [
        { lbl:'Creado',              val: fmt(t.creado_at) },
        { lbl:'Inicio recepción',    val: fmt(t.inicio_recepcion_at) },
        { lbl:'Fin recepción',       val: fmt(t.fin_recepcion_at) },
        { lbl:'Inicio servicio',     val: fmt(t.inicio_lugar_at) },
        { lbl:'Fin servicio',        val: fmt(t.fin_lugar_at) },
        { lbl:'Código completo',     val: esc(t.codigo) },
        { lbl:'Número en cola',      val: t.numero ?? '—' },
        { lbl:'Teléfono',            val: esc(t.paciente_cel || '—') },
        { lbl:'Recepción (desk)',     val: esc(t.recepcion_desk_nombre || '—') },
        { lbl:'Atendió recepción',   val: esc(t.atendido_recepcion_nombre || '—') },
        { lbl:'Atendió muestras',    val: esc(t.atendido_lugar_nombre || '—') },
        { lbl:'Notas',               val: esc(t.notas || '—') },
    ];
    // Exámenes
    let examHtml = '';
    if (t.examenes && t.examenes.length) {
        examHtml = `<div class="detail-extra">
            <div class="d-lbl"><i class="fas fa-vials me-1 text-success"></i>Exámenes (${t.examenes.length})</div>
            <div class="d-val">${t.examenes.map(e => `<span class="badge bg-success-subtle text-success me-1 mb-1">${esc(e.nombre)}</span>`).join('')}</div>
        </div>`;
    }

    // Comentarios
    let comHtml = '';
    if (t.comentarios && t.comentarios.length) {
        comHtml = `<div class="detail-extra">
            <div class="d-lbl"><i class="fas fa-comments me-1 text-primary"></i>Comentarios</div>
            <div>${t.comentarios.map(c => `
                <div class="detail-comment">
                    <span class="fw-semibold">${esc(c.usuario_nombre)}</span>
                    <span class="text-muted small ms-1">${c.creado_at ? new Date(c.creado_at.replace(' ','T')).toLocaleString('es-CO',{dateStyle:'short',timeStyle:'short'}) : ''}</span>
                    <div class="text-secondary">${esc(c.comentario)}</div>
                </div>`).join('')}
            </div>
        </div>`;
    }

    return `<div class="detail-grid">
        ${items.map(it=>`
            <div class="detail-item">
                <div class="d-lbl">${it.lbl}</div>
                <div class="d-val">${it.val}</div>
            </div>`).join('')}
    </div>
    ${examHtml}${comHtml}
    <div class="docs-section" id="docs-${t.id}">
        <div class="docs-lbl"><i class="fas fa-file-signature me-1"></i>Documentos</div>
        <span class="text-muted small"><i class="fas fa-spinner fa-spin me-1"></i>Cargando…</span>
    </div>`;
}

function toggleDetalle(rowId, btn, turnoId) {
    const row = document.getElementById(rowId);
    const icon = btn.querySelector('i');
    if (!row) return;
    const visible = row.style.display !== 'none';
    row.style.display = visible ? 'none' : '';
    icon.className = visible ? 'fas fa-chevron-down' : 'fas fa-chevron-up';
    icon.style.fontSize = '.65rem';
    if (!visible && turnoId) {
        const docsEl = document.getElementById(`docs-${turnoId}`);
        if (docsEl && !docsEl.dataset.loaded) {
            docsEl.dataset.loaded = '1';
            cargarDocumentosTurno(turnoId, docsEl);
        }
    }
}

const BASE_URL_ROOT = '<?= BASE_URL ?>';

async function cargarDocumentosTurno(turnoId, container) {
    try {
        const res  = await fetch(`${API}get_consentimientos.php?turno_id=${turnoId}`);
        const json = await res.json();
        if (!json.ok) { container.querySelector('span').textContent = 'Error al cargar'; return; }
        const list = json.consentimientos || [];
        if (!list.length) {
            container.innerHTML = '<div class="docs-lbl"><i class="fas fa-file-signature me-1"></i>Documentos</div>'
                + '<span class="docs-empty">Sin documentos para este turno</span>';
            return;
        }
        const LBLS = { firmado:'Firmado', enviado:'Enviado', visto:'Visto', pendiente:'Pendiente' };
        const pills = list.map(c => {
            const est    = c.estado || 'pendiente';
            const nombre = esc(c.formulario_nombre || 'Documento');
            if (est === 'firmado' && c.token) {
                const url = BASE_URL_ROOT + 'ver_formulario_enviado.php?token=' + encodeURIComponent(c.token);
                return `<a class="doc-pill firmado" href="${url}" target="_blank">
                    <i class="fas fa-check-circle"></i>${nombre}
                    <i class="fas fa-external-link-alt ms-1" style="font-size:.6rem;opacity:.6"></i>
                </a>`;
            }
            const cls = est === 'enviado' || est === 'visto' ? 'enviado' : 'pendiente';
            const ico = est === 'enviado' ? 'fa-paper-plane' : (est === 'visto' ? 'fa-eye' : 'fa-clock');
            return `<span class="doc-pill ${cls}"><i class="fas ${ico}"></i>${nombre}</span>`;
        }).join('');
        container.innerHTML = '<div class="docs-lbl"><i class="fas fa-file-signature me-1"></i>Documentos</div>' + pills;
    } catch(_) {
        const sp = container.querySelector('span');
        if (sp) sp.textContent = 'Error de conexión';
    }
}

// ── Paginación ────────────────────────────────────────────────
function renderPaginacion() {
    const wrap = document.getElementById('paginacionWrap');
    const info = document.getElementById('paginacionInfo');
    const btns = document.getElementById('pagBtns');

    wrap.style.display = '';

    const desde = (_state.page - 1) * _state.perPage + 1;
    const hasta = Math.min(_state.page * _state.perPage, _state.total);
    info.textContent = `Mostrando ${desde}–${hasta} de ${_state.total} turnos`;

    // Generar botones de página (máximo 7 visibles)
    const total   = _state.totalPages;
    const current = _state.page;
    let pages     = [];

    if (total <= 7) {
        pages = Array.from({length: total}, (_,i) => i+1);
    } else {
        pages = [1];
        if (current > 3)             pages.push('…');
        for (let p = Math.max(2, current-1); p <= Math.min(total-1, current+1); p++) pages.push(p);
        if (current < total-2)       pages.push('…');
        pages.push(total);
    }

    btns.innerHTML = `
        <button ${current<=1?'disabled':''} onclick="irPagina(${current-1})">
            <i class="fas fa-chevron-left"></i>
        </button>
        ${pages.map(p =>
            p === '…'
            ? `<button disabled>…</button>`
            : `<button class="${p===current?'active':''}" onclick="irPagina(${p})">${p}</button>`
        ).join('')}
        <button ${current>=total?'disabled':''} onclick="irPagina(${current+1})">
            <i class="fas fa-chevron-right"></i>
        </button>
    `;
}

function irPagina(n) {
    if (n < 1 || n > _state.totalPages) return;
    _state.page = n;
    cargarPagina();
    window.scrollTo({top:0, behavior:'smooth'});
}

// ── Exportar CSV ──────────────────────────────────────────────
function exportarCSV() {
    const params = new URLSearchParams({
        fecha    : _state.fechaDesde,           // export_csv actual usa 'fecha' — usamos fecha_desde
        m        : 'historial',                 // flag para que export_csv sepa que es multi-día
        fecha_desde  : _state.fechaDesde,
        fecha_hasta  : _state.fechaHasta,
        estado       : _state.estado,
        lugar_id     : _state.lugarId,
        prioridad_id : _state.prioridadId,
        q            : _state.q,
        per_page     : 9999,
        page         : 1,
    });
    // Generamos CSV en cliente a partir de los datos actuales si son pocos,
    // o mandamos al endpoint get_historial con per_page alto para descarga
    window.open(`${API}export_historial.php?${params}`, '_blank');
}

// ── Helpers visuales ──────────────────────────────────────────
function mostrarSpinner() {
    document.getElementById('tbody').innerHTML =
        '<tr class="spinner-row"><td colspan="11"><i class="fas fa-spinner fa-spin me-2"></i>Buscando…</td></tr>';
    document.getElementById('paginacionWrap').style.display = 'none';
    document.getElementById('kpiStrip').style.display = 'none';
}

function mostrarError(msg) {
    document.getElementById('tbody').innerHTML =
        `<tr><td colspan="11"><div class="empty-state text-danger">
            <i class="fas fa-exclamation-circle"></i>${esc(msg)}
        </div></td></tr>`;
}
</script>

<?php Layout::close(); ?>
