<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<title>Productos Cancelados — ARKHON</title>
<link rel="preconnect" href="https://fonts.googleapis.com"/>
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet"/>
<style>
:root{
  --bg:#f7f8fc;--surface:#fff;--border:#eaecf4;
  --text:#111827;--text-2:#4b5563;--text-3:#9ca3af;
  --orange:#f97316;--orange-lt:rgba(249,115,22,.10);
  --red:#ef4444;--red-lt:rgba(239,68,68,.10);
  --green:#10b981;--green-lt:rgba(16,185,129,.10);
  --blue:#2563eb;--blue-lt:rgba(37,99,235,.10);
  --shadow-sm:0 1px 3px rgba(17,24,39,.06);--r:10px;
}
*{margin:0;padding:0;box-sizing:border-box;}
html,body{font-family:'Plus Jakarta Sans',sans-serif;background:var(--bg);color:var(--text);min-height:100vh;font-size:13px;-webkit-font-smoothing:antialiased;}
button,input,select{font-family:'Plus Jakarta Sans',sans-serif;}
::-webkit-scrollbar{width:4px;}::-webkit-scrollbar-thumb{background:#d1d5db;border-radius:8px;}
@keyframes spin{to{transform:rotate(360deg);}}
@keyframes fadeUp{from{opacity:0;transform:translateY(8px);}to{opacity:1;transform:translateY(0);}}

.topbar{background:var(--surface);border-bottom:1px solid var(--border);height:58px;padding:0 20px;display:flex;align-items:center;gap:12px;box-shadow:var(--shadow-sm);position:sticky;top:0;z-index:20;}
.topbar-icon{width:34px;height:34px;border-radius:9px;flex-shrink:0;background:var(--red);display:flex;align-items:center;justify-content:center;box-shadow:0 3px 10px rgba(239,68,68,.28);}
.topbar-icon svg{width:16px;height:16px;stroke:#fff;stroke-width:2.2;fill:none;}
.topbar h1{font-size:15px;font-weight:800;color:var(--text);letter-spacing:-.3px;flex:1;}

.container{max-width:1000px;margin:0 auto;padding:18px 18px 40px;}
.filters-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--r);box-shadow:var(--shadow-sm);padding:14px 18px;margin-bottom:14px;display:flex;align-items:flex-end;gap:12px;flex-wrap:wrap;}
.fg{display:flex;flex-direction:column;gap:3px;}
.fl{font-size:9px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--text-3);}
input[type=date],input[type=text]{padding:7px 10px;border:1px solid var(--border);border-radius:8px;font-size:12px;font-weight:600;color:var(--text);outline:none;transition:.15s;background:var(--surface);}
input:focus{border-color:var(--orange);}
.btn-primary{display:flex;align-items:center;gap:6px;padding:8px 18px;background:var(--orange);color:#fff;border:none;border-radius:8px;font-size:12px;font-weight:700;cursor:pointer;box-shadow:0 2px 8px rgba(249,115,22,.28);transition:.15s;}
.btn-primary:hover{transform:translateY(-1px);}
.btn-primary svg{width:13px;height:13px;stroke:#fff;stroke-width:2.2;fill:none;}

.stats-row{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;margin-bottom:12px;}
@media(min-width:600px){.stats-row{grid-template-columns:repeat(4,1fr);}}
.stat-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--r);padding:14px 16px;box-shadow:var(--shadow-sm);}
.stat-label{font-size:10px;color:var(--text-3);font-weight:600;margin-bottom:4px;text-transform:uppercase;letter-spacing:.06em;}
.stat-val{font-size:20px;font-weight:800;letter-spacing:-.4px;color:var(--text);}
.stat-val.red{color:var(--red);}

.card{background:var(--surface);border:1px solid var(--border);border-radius:var(--r);box-shadow:var(--shadow-sm);overflow:hidden;margin-bottom:12px;animation:fadeUp .2s ease;}
.card-head{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--border);}
.card-title{font-size:12px;font-weight:800;color:var(--text);}
.card-badge{font-size:10px;font-weight:700;padding:2px 8px;border-radius:20px;background:var(--red-lt);color:var(--red);}

table{width:100%;border-collapse:collapse;font-size:12px;}
th{padding:9px 14px;text-align:left;font-size:10px;font-weight:700;color:var(--text-3);text-transform:uppercase;letter-spacing:.08em;border-bottom:1px solid var(--border);background:var(--bg);}
td{padding:9px 14px;border-bottom:1px solid var(--border);color:var(--text-2);}
tr:last-child td{border-bottom:none;}
tr:hover td{background:var(--bg);}
td.num{text-align:right;font-weight:700;color:var(--red);}
td.r{text-align:right;font-weight:700;}

.bar-row{display:flex;align-items:center;gap:10px;padding:8px 16px;border-bottom:1px solid var(--border);}
.bar-row:last-child{border-bottom:none;}
.bar-rank{font-size:11px;font-weight:800;color:var(--text-3);width:20px;text-align:center;flex-shrink:0;}
.bar-rank.n1{color:var(--orange);}
.bar-label{font-size:11.5px;font-weight:700;color:var(--text);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.bar-track{width:100px;flex-shrink:0;height:6px;background:var(--bg);border-radius:6px;overflow:hidden;}
.bar-fill{height:100%;border-radius:6px;background:var(--red);}
.bar-qty{font-size:11px;font-weight:700;color:var(--text-3);flex-shrink:0;min-width:50px;text-align:center;}
.bar-val{font-size:11.5px;font-weight:800;color:var(--red);flex-shrink:0;min-width:80px;text-align:right;}

.empty{padding:32px;text-align:center;color:var(--text-3);font-size:12px;font-weight:600;}
.spinner{width:22px;height:22px;border:2.5px solid var(--border);border-top-color:var(--orange);border-radius:50%;animation:spin .7s linear infinite;margin:28px auto;display:block;}
.error-box{padding:16px 18px;background:var(--red-lt);border-radius:var(--r);color:var(--red);font-size:12px;font-weight:600;margin-bottom:12px;}
.ovwrap{overflow-x:auto;}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:12px;}
@media(max-width:640px){.grid2{grid-template-columns:1fr;}}
</style>
<link rel="stylesheet" href="/css/responsive.css?v=406r"/>
</head>
<body>
<div class="topbar">
  <div class="topbar-icon"><svg viewBox="0 0 24 24"><path d="M3 6h18"/><path d="M8 6V4h8v2"/><path d="M19 6l-1 14H6L5 6"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/></svg></div>
  <h1>Productos Cancelados</h1>
</div>

<div class="container">
  <div id="live-banner" style="display:none;background:var(--surface);border:1px solid var(--border);border-left:3px solid var(--green);border-radius:var(--r);padding:12px 16px;margin-bottom:12px;box-shadow:var(--shadow-sm);">
    <span style="width:8px;height:8px;border-radius:50%;background:var(--green);animation:fadeUp .2s ease;flex-shrink:0;display:inline-block;margin-right:10px;"></span>
    <div>
      <div style="font-size:12px;font-weight:700;color:var(--text)" id="live-banner-txt">Turno activo</div>
      <div style="font-size:10px;color:var(--text-3);font-weight:600;margin-top:1px" id="live-banner-sub">Actualizando automáticamente</div>
    </div>
  </div>

  <div style="display:flex;gap:6px;margin-bottom:12px;flex-wrap:wrap;">
    <button class="btn-primary" id="tab-filtros" onclick="setViewMode('filtros')" style="background:var(--orange);">Consulta manual</button>
    <button class="btn-primary" id="tab-live" onclick="setViewMode('live')" style="background:var(--green);box-shadow:0 2px 8px rgba(16,185,129,.28);">● Turno actual</button>
  </div>

  <div id="panel-filtros" class="filters-card">
    <div class="fg"><div class="fl">Fecha inicio</div><input type="date" id="f-ini"/></div>
    <div class="fg"><div class="fl">Fecha fin</div><input type="date" id="f-fin"/></div>
    <div class="fg" style="border-left:1px solid var(--border);padding-left:12px;margin-left:4px;">
      <div class="fl">Buscar turnos del día</div>
      <div style="display:flex;gap:6px;align-items:center;">
        <input type="date" id="f-fecha-turno" style="padding:7px 10px;border:1px solid var(--border);border-radius:var(--r);font-size:12px;background:var(--surface);color:var(--text);"/>
        <button onclick="cargarTurnos(document.getElementById('f-fecha-turno').value)" style="padding:7px 10px;background:var(--orange-lt);border:1px solid rgba(249,115,22,.3);border-radius:var(--r);color:var(--orange);font-size:11px;font-weight:700;cursor:pointer;white-space:nowrap;">Buscar</button>
      </div>
    </div>
    <div class="fg">
      <div class="fl">Turno</div>
      <select id="f-turno" style="padding:8px 10px;border:1px solid var(--border);border-radius:var(--r);font-size:13px;background:var(--surface);color:var(--text);min-width:200px;">
        <option value="">— Selecciona turno —</option>
      </select>
    </div>
    <button class="btn-primary" onclick="cargar()"><svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>Consultar</button>
  </div>

  <div id="error-box" class="error-box" style="display:none;"></div>
  <div id="spinner" class="spinner" style="display:none;"></div>
  <div id="resultado"></div>
</div>

<script src="/js/arkhon-utils.js"></script>
<script>
var LOCAL_API_KEY = '';
// token loaded via _initAuth()
// token loaded via _initAuth()
const fdt = s => { try{ return new Date(s).toLocaleString('es-MX',{dateStyle:'short',timeStyle:'short'}); }catch{return '—';} };
let viewMode = 'filtros';
let liveTimer = null;

document.getElementById('f-ini').value = hoy();
document.getElementById('f-fin').value = hoy();
document.getElementById('f-fecha-turno').value = hoy();

function setViewMode(m){
  viewMode = m;
  if(liveTimer){ clearInterval(liveTimer); liveTimer=null; }
  document.getElementById('panel-filtros').style.display = m==='filtros' ? 'flex' : 'none';
  document.getElementById('live-banner').style.display   = m==='live'    ? 'flex' : 'none';
  document.getElementById('resultado').innerHTML = '';
  document.getElementById('error-box').style.display = 'none';
  if(m==='live'){
    cargarTurnoActivo();
    // Fallback polling cada 10s por si el socket no está disponible
    liveTimer = setInterval(cargarTurnoActivo, 10000);
  }
}

// Renderiza directo desde payload del socket — sin fetch extra
function renderDesdeSocket(cancelaciones_turno) {
  if(!cancelaciones_turno) return;
  const det = cancelaciones_turno.detalle_productos || [];
  document.getElementById('live-banner-txt').textContent =
    `En vivo — hoy · ${cancelaciones_turno.total_cancelaciones||0} productos · ${cancelaciones_turno.cuentas_afectadas||0} cuentas`;
  document.getElementById('live-banner-sub').textContent =
    `Actualizado vía WebSocket · ${new Date().toLocaleTimeString('es-MX',{hour:'2-digit',minute:'2-digit',second:'2-digit'})}`;

  // Construir objeto compatible con renderResultado
  const data = {
    resumen: {
      productos_cancelados: cancelaciones_turno.total_cancelaciones || 0,
      importe_cancelado:    cancelaciones_turno.importe_cancelado   || 0,
      cuentas_afectadas:    cancelaciones_turno.cuentas_afectadas   || 0,
      meseros_involucrados: [...new Set(det.map(d=>d.idmesero).filter(Boolean))].length,
    },
    topProductos: cancelaciones_turno.top_productos  || [],
    motivos:      cancelaciones_turno.motivos        || [],
    porUsuario:   cancelaciones_turno.por_usuario    || [],
    detalle:      det,
  };
  renderResultado(data);
}

async function cargarTurnoActivo(){
  const primeraCarga = !document.getElementById('resultado').innerHTML.trim();
  if(primeraCarga) document.getElementById('spinner').style.display='block';
  try{
    if(window._lastSocketPayload && window._lastSocketPayload.cancelaciones_turno){
      renderDesdeSocket(window._lastSocketPayload.cancelaciones_turno);
      return;
    }
    // Buscar turno activo primero
    let ep;
    try{
      const r = await api('/turnos/hoy');
      const activo = (r||[]).find(t => !t.cierre);
      if(activo && activo.idturno){
        ep = `/reportes/productos-ind-cancelados?idturno=${activo.idturno}&pageSize=500`;
      }
    }catch(_){}
    if(!ep) ep = `/reportes/productos-ind-cancelados?inicio=${hoy()}&fin=${hoy()}&pageSize=500`;
    const d = await api(ep);
    const nProd = d.resumen?.productos_cancelados || 0;
    document.getElementById('live-banner-txt').textContent = `En vivo — Turno actual`;
    document.getElementById('live-banner-sub').textContent =
      `${nProd} productos cancelados · Actualiza cada 10s`;
    document.getElementById('live-banner').style.display = 'flex';
    renderResultado(d);
  }catch(e){ showError('Error: '+e.message); }
  finally{ if(primeraCarga) document.getElementById('spinner').style.display='none'; }
}

async function cargarTurnos(fechaBuscar){
  const sel=document.getElementById('f-turno');
  const fecha = fechaBuscar || hoy();
  try{
    let turnos = [];
    // Buscar por fecha — soporta hoy y días anteriores
    try {
      turnos = await api(`/turnos/por-fecha?fecha=${fecha}`);
    } catch(_) {}
    // Fallback: si no hay endpoint por-fecha usar /hoy
    if(!(turnos||[]).length && fecha===hoy()){
      try { turnos = await api('/turnos/hoy'); } catch(_) {}
    }
    turnos = turnos || [];
    sel.innerHTML='<option value="">— Selecciona turno —</option>';
    if(!turnos.length){
      sel.innerHTML+='<option value="" disabled>Sin turnos en esta fecha</option>';
      return;
    }
    turnos.forEach(t=>{
      const idStr  = String(t.idturno||'');
      const estado = t.cierre ? 'Cerrado' : 'Activo';
      let hora = '';
      try {
        if(t.apertura){
          const aperturaStr = String(t.apertura);
          const dt = aperturaStr.includes('T') && !aperturaStr.includes('Z') && !aperturaStr.includes('+')
            ? new Date(aperturaStr + 'Z') : new Date(aperturaStr);
          hora = dt.toLocaleTimeString('es-MX',{hour:'2-digit',minute:'2-digit'});
        }
      } catch(_){}
      const opt=document.createElement('option');
      opt.value = idStr;
      opt.textContent = `${t.nombre_turno||'Turno'} #${idStr} — ${hora} (${estado})`;
      if(!t.cierre) opt.style.fontWeight='700';
      sel.appendChild(opt);
    });
    // Auto-seleccionar el turno activo si existe
    const activo = turnos.find(t=>!t.cierre);
    if(activo) sel.value = activo.idturno;
  }catch(e){ sel.innerHTML='<option value="">Error al cargar turnos</option>'; }
}

  // Ocultar topbar si corre dentro de un iframe
  if (window.self !== window.top) {
    const tb = document.querySelector('.topbar');
    if (tb) tb.style.display = 'none';
  }
(async()=>{
  try {
    await _initAuth();
    cargarTurnos();

  // Inicializar socket DESPUÉS de tener el token
  const _s = document.createElement('script');
  _s.src = '/socket.io/socket.io.js';
  _s.onload = () => {
    const socket = io(window.location.origin,{auth:{token:LOCAL_API_KEY}});
    socket.on('connect', () => {
      if(viewMode === 'live') cargarTurnoActivo();
    });
    socket.on('actualizacion', (data) => {
      window._lastSocketPayload = data;
      if(data.cancelaciones_turno){
        if(viewMode === 'live'){
          if(liveTimer){ clearInterval(liveTimer); liveTimer=null; }
          renderDesdeSocket(data.cancelaciones_turno);
        } else if(viewMode === 'filtros'){
          const sel = document.getElementById('f-turno');
          const turnoVal = sel ? sel.value : '';
          if(turnoVal){
            const opt = sel.options[sel.selectedIndex];
            const esActivo = opt && opt.textContent.includes('Activo');
            if(esActivo) renderDesdeSocket(data.cancelaciones_turno);
          }
        }
      }
    });
  };
  document.head.appendChild(_s);
  } catch(e) { showError('Error al iniciar: ' + e.message); }
})();


async function cargar(){
  document.getElementById('error-box').style.display='none';
  document.getElementById('resultado').innerHTML='';
  document.getElementById('spinner').style.display='block';
  try{
    const turno = document.getElementById('f-turno').value;
    const ini   = document.getElementById('f-ini').value;
    const fin   = document.getElementById('f-fin').value;
    let ep;
    if(turno && turno.trim() && !isNaN(parseInt(turno))){
      // Consulta por turno específico
      ep = `/reportes/productos-ind-cancelados?idturno=${parseInt(turno)}&pageSize=500`;
    } else {
      // Consulta por rango de fechas
      if(!ini || !fin){
        throw new Error('Selecciona un turno del selector o ingresa un rango de fechas');
      }
      if(ini > fin){
        throw new Error('La fecha de inicio debe ser anterior o igual a la fecha fin');
      }
      ep = `/reportes/productos-ind-cancelados?inicio=${ini}&fin=${fin}&pageSize=500`;
    }
    const d = await api(ep);
    if(!d) throw new Error('Sin respuesta del servidor');
    renderResultado(d);
  }catch(e){ showError(e.message); }
  finally{ document.getElementById('spinner').style.display='none'; }
}

function showError(msg){
  document.getElementById('spinner').style.display='none';
  const eb=document.getElementById('error-box'); eb.textContent=msg; eb.style.display='block';
}

function renderResultado(d){
  const res = document.getElementById('resultado');
  if(!d){ res.innerHTML='<div class="empty">Sin datos</div>'; return; }

  
  const items   = d.topProductos || [];
  const resumen = d.resumen      || {};
  const detalle = d.detalle      || [];
  const motivos = d.motivos      || [];
  const porUser = d.porUsuario   || [];

  if(!items.length && !detalle.length){
    res.innerHTML='<div class="empty">Sin productos cancelados en este período</div>';
    return;
  }

  const totalCant = resumen.productos_cancelados || items.reduce((a,i)=>a+(i.cantidad_total||0),0);
  const totalImp  = resumen.importe_cancelado    || items.reduce((a,i)=>a+(i.importe_total||0),0);
  const cuentas   = resumen.cuentas_afectadas    || 0;
  const maxCant   = Math.max(...items.map(i=>i.cantidad_total||0), 1);

  let html = `
    <div class="stats-row">
      <div class="stat-card"><div class="stat-label">Productos únicos</div><div class="stat-val">${items.length}</div></div>
      <div class="stat-card"><div class="stat-label">Cantidad total</div><div class="stat-val">${totalCant}</div></div>
      <div class="stat-card"><div class="stat-label">Importe cancelado</div><div class="stat-val red">${fmt(totalImp)}</div></div>
      <div class="stat-card"><div class="stat-label">Cuentas afectadas</div><div class="stat-val">${cuentas}</div></div>
    </div>`;

  
  if(items.length){
    html += `<div class="card">
      <div class="card-head">
        <span class="card-title">Ranking de cancelaciones</span>
        <span class="card-badge">${items.length} productos</span>
      </div>
      ${items.map((it,i)=>{
        const cant = it.cantidad_total||0;
        const pct  = Math.round((cant/maxCant)*100);
        return `<div class="bar-row">
          <div class="bar-rank ${i===0?'n1':''}">${i+1}</div>
          <div class="bar-label">${it.producto||'—'}</div>
          <div class="bar-track"><div class="bar-fill" style="width:${pct}%"></div></div>
          <div class="bar-qty">${cant} pcs</div>
          <div class="bar-val">${fmt(it.importe_total||0)}</div>
        </div>`;
      }).join('')}
    </div>`;
  }

  
  if(motivos.length || porUser.length){
    html += `<div class="grid2">`;
    if(motivos.length){
      html += `<div class="card">
        <div class="card-head"><span class="card-title">Por motivo</span></div>
        <div class="ovwrap"><table>
          <thead><tr><th>Motivo</th><th style="text-align:right">Cantidad</th></tr></thead>
          <tbody>${motivos.map(m=>`<tr>
            <td style="font-weight:600;color:var(--text)">${m.motivo}</td>
            <td class="r">${m.cantidad}</td>
          </tr>`).join('')}</tbody>
        </table></div>
      </div>`;
    }
    if(porUser.length){
      html += `<div class="card">
        <div class="card-head"><span class="card-title">Por usuario</span></div>
        <div class="ovwrap"><table>
          <thead><tr><th>Usuario</th><th style="text-align:right">Cant.</th><th style="text-align:right">Importe</th></tr></thead>
          <tbody>${porUser.map(u=>`<tr>
            <td style="font-weight:700;color:var(--text)">${u.usuario}</td>
            <td class="r" style="color:var(--text-2)">${u.cantidad}</td>
            <td class="r" style="color:var(--red)">${fmt(u.importe||0)}</td>
          </tr>`).join('')}</tbody>
        </table></div>
      </div>`;
    }
    html += `</div>`;
  }

  
  if(detalle.length){
    html += `<div class="card">
      <div class="card-head">
        <span class="card-title">Detalle de cancelaciones</span>
        <span class="card-badge">${detalle.length} registros</span>
      </div>
      <div class="ovwrap"><table>
        <thead><tr><th>Folio</th><th>Producto</th><th>Mesa</th><th>Cant.</th><th>P.Unit.</th><th style="text-align:right">Importe</th><th>Motivo</th><th>Usuario</th><th>Fecha</th></tr></thead>
        <tbody>${detalle.map(r=>`<tr>
          <td style="color:var(--text-3);font-size:11px">${r.folio||'—'}</td>
          <td style="font-weight:700;color:var(--text)">${r.producto||'—'}</td>
          <td>${r.mesa||'—'}</td>
          <td style="text-align:center;font-weight:700">${r.cantidad||0}</td>
          <td>${fmt(r.precio_unitario||0)}</td>
          <td class="r" style="color:var(--red)">${fmt(r.importe_total||0)}</td>
          <td style="font-size:11px;color:var(--text-3)">${r.motivo||'—'}</td>
          <td style="font-size:11px">${r.usuario_cancelo||'—'}</td>
          <td style="font-size:11px;white-space:nowrap;color:var(--text-3)">${fdt(r.fecha)}</td>
        </tr>`).join('')}</tbody>
      </table></div>
    </div>`;
  }

  res.innerHTML = html;
}


</script>
</body>
</html>
