<!-- views/dashboard.ejs -->
<div class="d-flex align-items-center justify-content-between mb-3">
  <h1 class="h4 m-0">Dashboard Operativo</h1>
  <div class="d-flex align-items-center gap-2">
    <button id="dashRefresh" class="btn btn-outline-secondary btn-sm">Recargar</button>
    <span id="dashStatus" class="text-muted small"></span>
  </div>
</div>

<!-- KPIs -->
<div class="row g-3 mb-3">
  <div class="col-6 col-md-3">
    <div class="card shadow-sm">
      <div class="card-body">
        <div class="text-muted small">Comandas activas</div>
        <div class="h3 m-0" id="kpiActivas">—</div>
      </div>
    </div>
  </div>
  <div class="col-6 col-md-3">
    <div class="card shadow-sm">
      <div class="card-body">
        <div class="text-muted small">Ventas hoy</div>
        <div class="h3 m-0"><span id="kpiVentasHoy">—</span></div>
      </div>
    </div>
  </div>
  <div class="col-6 col-md-3">
    <div class="card shadow-sm">
      <div class="card-body">
        <div class="text-muted small">Ticket promedio (hoy)</div>
        <div class="h3 m-0"><span id="kpiTicketProm">—</span></div>
      </div>
    </div>
  </div>
  <div class="col-6 col-md-3">
    <div class="card shadow-sm">
      <div class="card-body">
        <div class="text-muted small">Productos distintos (hoy)</div>
        <div class="h3 m-0" id="kpiProdDist">—</div>
      </div>
    </div>
  </div>
</div>

<!-- Gráficos -->
<div class="row g-3">
  <div class="col-12 col-lg-6">
    <div class="card shadow-sm">
      <div class="card-header"><strong>Top 5 productos (hoy)</strong></div>
      <div class="card-body">
        <div class="chart-box">
            <canvas id="chartTopProductos"></canvas>
        </div>
        <div class="text-muted small mt-2">Basado en detalle de comandas de hoy.</div>
      </div>
    </div>
  </div>

  <div class="col-12 col-lg-6">
    <div class="card shadow-sm">
      <div class="card-header"><strong>Comandas por hora (últimas 12 h)</strong></div>
      <div class="card-body">
        <div class="chart-box">
            <canvas id="chartComandasHora"></canvas>
        </div>
        <div class="text-muted small mt-2">Se agrupa por hora de creación.</div>
      </div>
    </div>
  </div>

  <div class="col-12 col-lg-6">
    <div class="card shadow-sm">
      <div class="card-header"><strong>Estados de comandas (hoy)</strong></div>
      <div class="card-body">
        <div class="chart-box">
            <canvas id="chartEstados"></canvas>
        </div>
        <div class="text-muted small mt-2">Distribución por estado.</div>
      </div>
    </div>
  </div>

  <!-- Últimas comandas -->
  <div class="col-12 col-lg-6">
    <div class="card shadow-sm">
      <div class="card-header d-flex align-items-center">
        <strong>Últimas 10 comandas</strong>
        <div class="ms-auto text-muted small" id="ultAct">—</div>
      </div>
      <div class="card-body p-0">
        <div class="table-responsive">
          <table class="table table-sm align-middle mb-0">
            <thead class="table-light">
              <tr>
                <th>#</th>
                <th>Fecha</th>
                <th>Cierre</th> <!-- NUEVO -->
                <th>Estado</th>
                <th class="text-end">Total</th>
                <th>Acción</th> <!-- NUEVO -->
              </tr>
            </thead>
            <tbody id="ultimasTbody">
              <tr><td colspan="6" class="text-muted p-3">Cargando…</td></tr>
            </tbody>
          </table>
        </div>
      </div>
      <div class="card-footer text-muted small">
        Totales calculados como Σ (pre_unitario × cantidad) por comanda.
      </div>
    </div>
  </div>
</div>

<!-- Librería para gráficos -->
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>

<script>
  // ===== Utilidades =====
  const $ = (s, r=document)=>r.querySelector(s);
  const fmtMoney = (n)=> isNaN(n) ? '—' : new Intl.NumberFormat('es-UY',{style:'currency',currency:'UYU'}).format(+n);
  const fmtTs = (s)=> { const d = new Date(s); return isNaN(d) ? '—' : d.toLocaleString('es-UY'); };
  const setStatus = (t)=> $('#dashStatus').textContent = t || '';
  const todayBounds = ()=> {
    const now = new Date();
    const start = new Date(now.getFullYear(), now.getMonth(), now.getDate());
    const end = new Date(start); end.setDate(end.getDate()+1);
    return {start, end};
  };
  const guessKey = (obj, candidates)=> (candidates.find(k => k in obj) || null);
  const toDate = (v)=> (v instanceof Date ? v : new Date(v));
  const inRange = (d, a, b)=> (d>=a && d<b);

  // ===== Estado =====
  let charts = {};
  const state = {
    comandas: [],
    deta: [],
    productos: [],
    keys: {
      comFecha: null, comFechaCierre: null, comEstado: null, comId: null, // <-- agregado comFechaCierre
      detIdCom: null, detPrecio: null, detCant: null,
      prodId: null, prodNombre: null
    }
  };

  // ===== Carga =====
  async function jget(u){ const r=await fetch(u); const j=await r.json().catch(()=>null); if(!r.ok) throw new Error(j?.error||r.statusText); return j; }

  async function loadData() {
    setStatus('Cargando datos…');
    const [comandas, deta, productos] = await Promise.all([
      jget('/api/table/comandas?limit=2000').catch(()=>[]),
      jget('/api/table/deta_comandas?limit=5000').catch(()=>[]),
      jget('/api/table/productos?limit=5000').catch(()=>[])
    ]);
    state.comandas = Array.isArray(comandas)? comandas : [];
    state.deta     = Array.isArray(deta)? deta : [];
    state.productos= Array.isArray(productos)? productos : [];

    // Descubrir claves
    const c0 = state.comandas[0] || {};
    // incluimos fec_creacion y fec_cierre como prioridades
    state.keys.comFecha       = guessKey(c0, ['fec_creacion','fecha','created_at','creado_en','ts','timestamp','hora','datetime']);
    state.keys.comFechaCierre = guessKey(c0, ['fec_cierre','cierre','closed_at','fecha_cierre','ts_cierre','hora_cierre']);
    state.keys.comEstado      = guessKey(c0, ['estado','status']);
    state.keys.comId          = guessKey(c0, ['id_comanda','id','comanda_id']);

    const d0 = state.deta[0] || {};
    state.keys.detIdCom  = guessKey(d0, ['id_comanda','comanda_id']);
    state.keys.detPrecio = guessKey(d0, ['pre_unitario','precio_unitario','precio','unit_price']);
    state.keys.detCant   = guessKey(d0, ['cantidad','qty','cantidad_total']);

    const p0 = state.productos[0] || {};
    state.keys.prodId     = guessKey(p0, ['id_producto','id','producto_id']);
    state.keys.prodNombre = guessKey(p0, ['nombre','descripcion','titulo','name']);

    renderAll();
    setStatus('');
  }

  // ===== Cálculos =====
  function isActiva(estadoRaw){
    const s = String(estadoRaw||'').toLowerCase();
    return ['abierta','activa','activo','open','pendiente','en curso'].some(x => s.includes(x));
  }
  function isAnulada(estadoRaw){
    const s = String(estadoRaw||'').toLowerCase();
    return ['anulada','anulado','cancelada','cancelado','void'].some(x => s.includes(x));
  }

  function computeKpis(){
    const {comFecha, comEstado, comId} = state.keys;
    const {detIdCom, detPrecio, detCant} = state.keys;
    const {start, end} = todayBounds();

    // activas
    const activas = state.comandas.filter(c => comEstado && isActiva(c[comEstado])).length;
    $('#kpiActivas').textContent = activas;

    // ventas hoy
    const byCom = new Map();
    state.deta.forEach(d => {
      const idc = d[detIdCom]; if (idc==null) return;
      const arr = byCom.get(idc) || []; arr.push(d); byCom.set(idc, arr);
    });

    let totalHoy = 0, ticketsHoy = 0;
    for (const c of state.comandas) {
      const when = comFecha ? toDate(c[comFecha]) : null;
      const st   = comEstado ? c[comEstado] : null;
      if (!when || !inRange(when, start, end) || (st && isAnulada(st))) continue;
      const dets = byCom.get(c[comId]) || [];
      const total = dets.reduce((acc,d)=> acc + Number(d[detPrecio]||0) * Number(d[detCant]||0), 0);
      if (total>0) { totalHoy += total; ticketsHoy++; }
    }

    $('#kpiVentasHoy').textContent = fmtMoney(totalHoy);
    $('#kpiTicketProm').textContent = ticketsHoy ? fmtMoney(totalHoy / ticketsHoy) : '—';

    // productos distintos hoy
    const setProd = new Set();
    for (const c of state.comandas) {
      const when = comFecha ? toDate(c[comFecha]) : null;
      const st   = comEstado ? c[comEstado] : null;
      if (!when || !inRange(when, start, end) || (st && isAnulada(st))) continue;
      const dets = byCom.get(c[comId]) || [];
      dets.forEach(d => setProd.add(d.id_producto ?? d.producto_id ?? d[state.keys.prodId]));
    }
    $('#kpiProdDist').textContent = setProd.size || '0';
  }

  function computeTopProductosHoy(){
    const {comFecha, comEstado, comId} = state.keys;
    const {detIdCom, detCant, detPrecio} = state.keys;
    const {prodId, prodNombre} = state.keys;
    const {start, end} = todayBounds();

    const byCom = new Map();
    state.deta.forEach(d => {
      const idc = d[detIdCom]; if (idc==null) return;
      const arr = byCom.get(idc) || []; arr.push(d); byCom.set(idc, arr);
    });

    const qtyByProd = new Map(); // id -> cantidad total
    const amtByProd = new Map(); // id -> importe total
    for (const c of state.comandas) {
      const when = comFecha ? toDate(c[comFecha]) : null;
      const st   = comEstado ? c[comEstado] : null;
      if (!when || !inRange(when, start, end) || (st && isAnulada(st))) continue;

      const dets = byCom.get(c[comId]) || [];
      dets.forEach(d => {
        const pid = d.id_producto ?? d.producto_id ?? d[prodId];
        if (pid==null) return;
        const q = Number(d[detCant]||0);
        const a = Number(d[detPrecio]||0) * q;
        qtyByProd.set(pid, (qtyByProd.get(pid)||0)+q);
        amtByProd.set(pid, (amtByProd.get(pid)||0)+a);
      });
    }

    // id -> label
    const nameById = new Map(state.productos.map(p => [p[prodId], p[prodNombre] || ('#'+p[prodId])]));

    // ordenar por cantidad
    const arr = [...qtyByProd.entries()]
      .map(([id,qty]) => ({ id, qty, amt: amtByProd.get(id)||0, name: nameById.get(id)||('#'+id) }))
      .sort((a,b)=> b.qty - a.qty)
      .slice(0,5);

    return arr;
  }

  function computeComandasPorHora12h(){
    const {comFecha} = state.keys;
    const now = new Date();
    const buckets = [];
    for (let i=11;i>=0;i--){
      const h = new Date(now); h.setHours(now.getHours()-i, 0, 0, 0);
      buckets.push({ label: h.getHours().toString().padStart(2,'0')+':00', ts: +h, count: 0 });
    }
    if (!comFecha) return buckets;

    state.comandas.forEach(c => {
      const d = toDate(c[comFecha]); if (isNaN(d)) return;
      const diffH = Math.floor((now - d) / (60*60*1000));
      if (diffH<12 && diffH>=0) {
        // bucket por hora exacta
        const hour = new Date(d); hour.setMinutes(0,0,0);
        const idx = buckets.findIndex(b => b.ts === +hour);
        if (idx>=0) buckets[idx].count++;
      }
    });
    return buckets;
  }

  function computeEstadosHoy(){
    const {comFecha, comEstado} = state.keys;
    const {start, end} = todayBounds();
    const map = new Map();
    state.comandas.forEach(c=>{
      const when = comFecha ? toDate(c[comFecha]) : null;
      if (!when || !inRange(when, start, end)) return;
      const st = (c[comEstado] ?? '—').toString().toLowerCase();
      map.set(st, (map.get(st)||0)+1);
    });
    return [...map.entries()].map(([estado,count])=>({estado, count}));
  }

  // ===== Render =====
  function renderAll(){
    computeKpis();

    // Top productos
    const top = computeTopProductosHoy();
    drawBar('chartTopProductos', top.map(x=>x.name), top.map(x=>x.qty));

    // Comandas por hora
    const porHora = computeComandasPorHora12h();
    drawLine('chartComandasHora', porHora.map(x=>x.label), porHora.map(x=>x.count));

    // Estados
    const estados = computeEstadosHoy();
    drawDoughnut('chartEstados', estados.map(x=>x.estado), estados.map(x=>x.count));

    // Últimas 10
    renderUltimas();
  }

  function renderUltimas(){
    const {comFecha, comFechaCierre, comEstado, comId} = state.keys;
    const {detIdCom, detPrecio, detCant} = state.keys;

    const byCom = new Map();
    state.deta.forEach(d => {
      const idc = d[detIdCom]; if (idc==null) return;
      const arr = byCom.get(idc) || []; arr.push(d); byCom.set(idc, arr);
    });

    const rows = state.comandas
      .slice()
      .sort((a,b)=> {
        const da = comFecha ? +new Date(a[comFecha]) : 0;
        const db = comFecha ? +new Date(b[comFecha]) : 0;
        return db - da;
      })
      .slice(0,10);

    const tb = $('#ultimasTbody'); tb.innerHTML = '';
    let lastTs = null;

    rows.forEach(c=>{
      const dets = byCom.get(c[comId]) || [];
      const total = dets.reduce((acc,d)=> acc + Number(d[detPrecio]||0) * Number(d[detCant]||0), 0);
      const ts  = comFecha       ? new Date(c[comFecha])       : null;
      const tsc = comFechaCierre ? new Date(c[comFechaCierre]) : null;
      if (ts) lastTs = (!lastTs || ts>lastTs) ? ts : lastTs;

      const activa = isActiva(c[comEstado]);
      const btn = activa
        ? `<button class="btn btn-outline-danger btn-sm js-cerrar" data-id="${c[comId]}">Cerrar</button>`
        : `<button class="btn btn-outline-success btn-sm js-abrir" data-id="${c[comId]}">Abrir</button>`;

      const tr = document.createElement('tr');
      tr.dataset.id = c[comId];
      tr.innerHTML = `
        <td>${c[comId] ?? '—'}</td>
        <td>${ts ? fmtTs(ts) : '—'}</td>
        <td class="c-cierre">${tsc && !isNaN(tsc) ? fmtTs(tsc) : '—'}</td>
        <td class="c-estado">${c[comEstado] ?? '—'}</td>
        <td class="text-end">${fmtMoney(total)}</td>
        <td class="c-accion">${btn}</td>
      `;
      tb.appendChild(tr);
    });

    $('#ultAct').textContent = lastTs ? ('Actualizado: ' + fmtTs(lastTs)) : '—';
  }

  // ===== Charts helpers =====
  function destroyChart(id){ if (charts[id]) { charts[id].destroy(); charts[id]=null; } }
  function drawBar(id, labels, data){
    destroyChart(id);
    const ctx = document.getElementById(id);
    charts[id] = new Chart(ctx, {
      type: 'bar',
      data: { labels, datasets: [{ label: 'Cantidad', data }] },
      options: { responsive:true, maintainAspectRatio:false, plugins:{legend:{display:false}} }
    });
  }
  function drawLine(id, labels, data){
    destroyChart(id);
    const ctx = document.getElementById(id);
    charts[id] = new Chart(ctx, {
      type: 'line',
      data: { labels, datasets: [{ label: 'Comandas', data, tension:.3, fill:false }] },
      options: { responsive:true, maintainAspectRatio:false, plugins:{legend:{display:false}} }
    });
  }
  function drawDoughnut(id, labels, data){
    destroyChart(id);
    const ctx = document.getElementById(id);
    charts[id] = new Chart(ctx, {
      type: 'doughnut',
      data: { labels, datasets: [{ data }] },
      options: { responsive:true, maintainAspectRatio:false, plugins:{legend:{position:'bottom'}} }
    });
  }

  // ===== Eventos =====
  $('#dashRefresh').addEventListener('click', loadData);
  window.addEventListener('sc:refresh-list', loadData); // desde el sidebar "Actualizar listado"

  // Abrir/Cerrar comanda (actualiza fila + estado interno + re-render KPIs/gráficos)
  document.addEventListener('click', async (ev) => {
    const btn = ev.target.closest('.js-cerrar, .js-abrir');
    if (!btn) return;

    const id = btn.dataset.id;
    const isCerrar = btn.classList.contains('js-cerrar');
    const url = isCerrar ? `/api/comandas/${id}/cerrar` : `/api/comandas/${id}/abrir`;

    btn.disabled = true;
    try {
      const r = await fetch(url, { method: 'POST' });
      if (!r.ok) throw new Error('HTTP ' + r.status);
      const data = await r.json();

      // Actualizar estado local
      const { comId, comEstado, comFechaCierre } = state.keys;
      const idx = state.comandas.findIndex(c => String(c[comId]) === String(id));
      if (idx >= 0) {
        state.comandas[idx][comEstado] = data.estado ?? state.comandas[idx][comEstado];
        if (comFechaCierre) state.comandas[idx][comFechaCierre] = data.fec_cierre ?? state.comandas[idx][comFechaCierre];
      }

      // Actualizar fila visual
      const tr = document.querySelector(`tr[data-id="${id}"]`);
      if (tr) {
        const tdEstado = tr.querySelector('.c-estado');
        const tdCierre = tr.querySelector('.c-cierre');
        if (tdEstado) tdEstado.textContent = data.estado ?? tdEstado.textContent;
        if (tdCierre) tdCierre.textContent = data.fec_cierre ? fmtTs(data.fec_cierre) : '—';

        const acc = tr.querySelector('.c-accion');
        if (acc) {
          acc.innerHTML = (data.estado && data.estado.toLowerCase().includes('cerr'))
            ? `<button class="btn btn-outline-success btn-sm js-abrir" data-id="${id}">Abrir</button>`
            : `<button class="btn btn-outline-danger btn-sm js-cerrar" data-id="${id}">Cerrar</button>`;
        }
      }

      // Recalcular KPIs y gráficos (sin “crecimiento infinito”, se destruyen antes de redibujar)
      renderAll();
    } catch (e) {
      alert('No se pudo actualizar la comanda: ' + (e.message || 'Error'));
    } finally {
      btn.disabled = false;
    }
  });

  // Go!
  loadData().catch(e => setStatus(e.message || 'Error'));

  // Exporta CSV con KPIs y cortes básicos
  window.scExportCsv = function () {
    const rows = [];
    rows.push(["kpi", "valor"]);
    rows.push(["comandas_activas", document.getElementById("kpiActivas").textContent.trim()]);
    rows.push(["ventas_hoy", document.getElementById("kpiVentasHoy").textContent.trim()]);
    rows.push(["ticket_promedio_hoy", document.getElementById("kpiTicketProm").textContent.trim()]);
    rows.push(["productos_distintos_hoy", document.getElementById("kpiProdDist").textContent.trim()]);
    const csv = rows.map(r => r.map(v => `"${String(v).replaceAll('"','""')}"`).join(",")).join("\n");
    const blob = new Blob([csv], { type: "text/csv;charset=utf-8" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = `dashboard_${new Date().toISOString().slice(0,10)}.csv`;
    document.body.appendChild(a);
    a.click();
    a.remove();
    URL.revokeObjectURL(url);
  };
</script>
