/* reportes.jsx — módulo REPORTES: KPIs históricos a lo largo del tiempo (no "del día": eso es el
   Dashboard). Filtros por rango de fechas y etiquetas de zona/servicio, tendencia con proyección,
   tabla día a día, y ANÁLISIS BI por el agente CRÁNEO (Hermes) con las estadísticas reales como
   contexto (fallback determinista si el puente no está). window.CR.screens.Reportes */
(function () {
  var React = window.React;
  var ui = window.CR.ui;
  var h = React.createElement;
  var useState = React.useState, useEffect = React.useEffect;

  function money(n) { return '$' + Number(n || 0).toLocaleString('es-AR'); }
  function moneyCorto(n) {
    n = Number(n || 0);
    if (n >= 1e6) return '$' + (n / 1e6).toFixed(1) + 'M';
    if (n >= 1e3) return '$' + Math.round(n / 1e3) + 'k';
    return '$' + n;
  }
  var ZONA_COLOR = { CABA: '#1a73e8', NORTE: '#7c4dff', OESTE: '#00acc1', SUR: '#ec407a', 'LA PLATA': '#43a047', ROSARIO: '#ff8f00', 'S/C': '#fbbc04' };
  var METRICAS = [
    { k: 'rutas', label: 'Rutas', color: 'var(--primary)', fmt: function (y) { return String(y); } },
    { k: 'costoTotal', label: 'Costo', color: '#ec407a', fmt: moneyCorto },
    { k: 'kmTotal', label: 'Km', color: '#00acc1', fmt: function (y) { return String(y); } },
    { k: 'cobertura', label: 'Cobertura %', color: '#34a853', fmt: function (y) { return y + '%'; } }
  ];
  var PRESETS = [
    '¿Dónde hay plata para ahorrar en este período?',
    '¿Qué día de la semana me conviene reforzar flota?',
    'Proyectame la semana que viene (rutas y costo).',
    '¿Qué zona me está costando más de lo que debería?'
  ];

  // markdown mínimo (negritas + líneas), igual que el copiloto
  function fmtTexto(text) {
    return String(text || '').split('\n').map(function (line, i) {
      var parts = line.split(/(\*\*[^*]+\*\*)/g).map(function (p, j) {
        var m = /^\*\*([^*]+)\*\*$/.exec(p);
        return m ? h('strong', { key: j }, m[1]) : p;
      });
      return h('div', { key: i }, line ? parts : h('span', { style: { display: 'block', height: 6 } }));
    });
  }

  function Reportes() {
    var backendOn = !!(window.CR.backend && window.CR.backend.enabled);
    var canSeeCosts = !!window.CR.canSeeCosts;
    var diasState = useState(null); var dias = diasState[0], setDias = diasState[1];
    var desdeState = useState(''); var desde = desdeState[0], setDesde = desdeState[1];
    var hastaState = useState(''); var hasta = hastaState[0], setHasta = hastaState[1];
    var zonaState = useState(''); var zona = zonaState[0], setZona = zonaState[1];
    var svcState = useState(''); var svc = svcState[0], setSvc = svcState[1];
    var metState = useState('rutas'); var met = metState[0], setMet = metState[1];
    var anState = useState(null); var analisis = anState[0], setAnalisis = anState[1];
    var qState = useState(''); var q = qState[0], setQ = qState[1];
    var busyState = useState(false); var busy = busyState[0], setBusy = busyState[1];
    var anSeq = React.useRef(0);   // descarta respuestas de análisis viejas si el filtro cambió en vuelo

    useEffect(function () {
      if (!backendOn) { setDias([]); return; }
      window.CR.backend.historial().then(setDias).catch(function () { setDias([]); });
    }, [backendOn]);


    useEffect(function () { setAnalisis(null); anSeq.current++; setBusy(false); }, [desde, hasta, zona, svc]);

    if (!backendOn) {
      return h('div', null, h(ui.Page, { title: 'Reportes', subtitle: 'KPIs históricos y análisis de CRÁNEO.' }),
        h(ui.Card, null, h(ui.EmptyState, { title: 'Necesito el backend prendido' },
          h('span', null, 'El histórico vive en el servidor. Levantá el dev-server y recargá.'))));
    }
    if (dias === null) return h('div', null, h(ui.Page, { title: 'Reportes' }), h(ui.Card, null, h('div', { className: 'muted' }, 'Cargando histórico…')));

    // ── filtros ─────────────────────────────────────────────────────────────
    var enRango = dias.filter(function (d) {
      if (desde && d.fecha < desde) return false;
      if (hasta && d.fecha > hasta) return false;
      return true;
    });
    // el recorte por zona/servicio reduce los números de cada día a esa etiqueta (rutas/costo/km);
    // cobertura y choferes son del día completo (no existen por zona) — la tabla lo aclara.
    function valoresDe(d) {
      if (zona) { var z = (d.porZona || {})[zona]; return z ? { rutas: z.rutas, costoTotal: Math.round(z.costo), kmTotal: Math.round(z.km) } : { rutas: 0, costoTotal: 0, kmTotal: 0 }; }
      if (svc) { var s = (d.porServicio || {})[svc]; return s ? { rutas: s.rutas, costoTotal: Math.round(s.costo), kmTotal: Math.round(s.km) } : { rutas: 0, costoTotal: 0, kmTotal: 0 }; }
      return { rutas: d.rutas, costoTotal: d.costoTotal, kmTotal: d.kmTotal };
    }
    var filas = enRango.map(function (d) {
      var v = valoresDe(d);
      return { fecha: d.fecha, fuente: d.fuente, rutas: v.rutas, costoTotal: v.costoTotal, kmTotal: v.kmTotal,
        cobertura: d.cobertura, choferes: d.choferes, notificados: d.notificados };
    });
    var conDatos = filas.filter(function (f) { return f.rutas > 0; });

    var tot = conDatos.reduce(function (a, f) { return { rutas: a.rutas + f.rutas, costo: a.costo + f.costoTotal, km: a.km + f.kmTotal }; }, { rutas: 0, costo: 0, km: 0 });
    var prom = function (arr) { return arr.length ? Math.round(arr.reduce(function (a, b) { return a + b; }, 0) / arr.length) : 0; };
    // cobertura/choferes son métricas DEL DÍA (no existen por etiqueta): se promedian sobre todo el rango,
    // ignorando null — coercerlos a 0 hundía el promedio (QA v0.6.0)
    var promCobertura = prom(enRango.filter(function (d) { return d.cobertura != null; }).map(function (d) { return d.cobertura; }));
    var promChoferes = prom(enRango.filter(function (d) { return d.choferes != null; }).map(function (d) { return d.choferes; }));

    var zonas = {}; dias.forEach(function (d) { Object.keys(d.porZona || {}).forEach(function (z) { zonas[z] = 1; }); });
    var servicios = {}; dias.forEach(function (d) { Object.keys(d.porServicio || {}).forEach(function (s) { servicios[s] = 1; }); });

    var metrica = METRICAS.filter(function (m) { return m.k === met; })[0];
    var etiquetaActiva = !!(zona || svc);
    // con etiqueta activa los días en 0 SÍ se dibujan (un hueco invisible miente la serie)
    var serieChart = etiquetaActiva ? filas : conDatos;
    var puntos = serieChart.map(function (f) { return { x: f.fecha.slice(5), y: f[met] || 0 }; });
    // proyección local (misma regresión que el backend) SOLO sobre el período completo sin etiquetas:
    // con etiqueta, los insumos divergirían del backend y la proyección sería de otra serie
    function proyectar(vs, n) {
      var N = vs.length; if (N < 2) return [];
      var sx = 0, sy = 0, sxy = 0, sxx = 0;
      vs.forEach(function (v, i) { sx += i; sy += v; sxy += i * v; sxx += i * i; });
      var den = N * sxx - sx * sx; var m = den ? (N * sxy - sx * sy) / den : 0; var b = (sy - m * sx) / N;
      var out = []; for (var k = 0; k < n; k++) out.push(Math.max(0, Math.round(m * (N + k) + b)));
      return out;
    }
    var proy = (met === 'cobertura' || etiquetaActiva) ? [] : proyectar(conDatos.map(function (f) { return f[met] || 0; }), 3);

    function analizar(pregunta) {
      var seq = ++anSeq.current;
      setBusy(true); setAnalisis(null);
      window.CR.backend.analizarCraneo(pregunta || '', desde, hasta, zona, svc)
        .then(function (res) { if (seq === anSeq.current) setAnalisis(res); })
        .catch(function (ex) { if (seq === anSeq.current) setAnalisis({ texto: 'No pude analizar: ' + (ex.message || 'sin conexión'), fuente: 'error' }); })
        .then(function () { if (seq === anSeq.current) setBusy(false); });
    }

    var chip = function (activo, label, onClick, color) {
      return h('button', { key: label, type: 'button', className: 'rep-chip' + (activo ? ' rep-chip--on' : ''),
        style: activo && color ? { borderColor: color, color: color } : null, 'aria-pressed': activo, onClick: onClick }, label);
    };

    return h('div', null,
      h(ui.Page, { title: 'Reportes — histórico', subtitle: 'La operación a lo largo del tiempo. El Dashboard muestra el día; acá ves la película: tendencias, comparaciones y el análisis de CRÁNEO.' }),

      // ── filtros ──
      h(ui.Card, null,
        h('div', { className: 'rep-filtros' },
          h('label', { className: 'rep-f' }, h('span', null, 'Desde'),
            h('input', { className: 'input', type: 'date', value: desde, onChange: function (e) { setDesde(e.target.value); } })),
          h('label', { className: 'rep-f' }, h('span', null, 'Hasta'),
            h('input', { className: 'input', type: 'date', value: hasta, onChange: function (e) { setHasta(e.target.value); } })),
          h('div', { className: 'rep-f', style: { flex: 1 } },
            h('span', null, 'Etiquetas (zona / servicio)'),
            h('div', { className: 'rep-chips' },
              Object.keys(zonas).sort().map(function (z) {
                return chip(zona === z, z, function () { setZona(zona === z ? '' : z); setSvc(''); }, ZONA_COLOR[z]);
              }),
              Object.keys(servicios).sort().map(function (s) {
                return chip(svc === s, s, function () { setSvc(svc === s ? '' : s); setZona(''); });
              }),
              (zona || svc || desde || hasta) ? h('button', { type: 'button', className: 'rep-chip rep-chip--x',
                onClick: function () { setZona(''); setSvc(''); setDesde(''); setHasta(''); } }, '✕ limpiar') : null)))),

      // ── KPIs del período ──
      h(ui.Card, { title: 'Período: ' + (conDatos.length || 0) + ' día' + (conDatos.length === 1 ? '' : 's') + (zona ? ' · zona ' + zona : '') + (svc ? ' · servicio ' + svc : '') },
        conDatos.length
          ? h('div', { className: 'resumen-row' },
            h(ui.StatCard, { label: 'Rutas', value: tot.rutas }),
            canSeeCosts ? h(ui.StatCard, { label: 'Costo total', value: money(tot.costo) }) : null,
            canSeeCosts ? h(ui.StatCard, { label: 'Costo por ruta', value: money(Math.round(tot.costo / Math.max(1, tot.rutas))) }) : null,
            h(ui.StatCard, { label: 'Km', value: tot.km }),
            h(ui.StatCard, { label: etiquetaActiva ? 'Cobertura prom. (día completo)' : 'Cobertura prom.', value: promCobertura + '%' }),
            h(ui.StatCard, { label: etiquetaActiva ? 'Choferes prom. (día completo)' : 'Choferes prom.', value: promChoferes }))
          : h(ui.EmptyState, { title: 'Sin días en este filtro' },
            h('span', null, 'Probá con otro rango o limpiá las etiquetas. El histórico se completa solo cada vez que confirmás una jornada.'))),

      // ── tendencia ──
      conDatos.length >= 2 ? h(ui.Card, { title: 'Tendencia' },
        h('div', { className: 'rep-mets' }, METRICAS.filter(function (m) { return canSeeCosts || m.k !== 'costoTotal'; }).map(function (m) {
          return chip(met === m.k, m.label, function () { setMet(m.k); }, m.color);
        })),
        h(window.CR.Tendencia, { puntos: puntos, proyeccion: proy, color: metrica.color, formato: metrica.fmt }),
        proy.length ? h('p', { className: 'muted', style: { fontSize: 12, margin: '8px 0 0' } },
          'La línea punteada es una proyección estadística (tendencia lineal de los próximos 3 días): sirve para dimensionar flota, no reemplaza el dato de MELI.') : null) : null,

      // ── análisis de CRÁNEO ──
      h(ui.Card, { title: '🧠 Análisis de CRÁNEO (BI)' },
        h('p', { className: 'muted', style: { fontSize: 13, margin: '0 0 10px' } },
          'CRÁNEO analiza el histórico real del período filtrado: costos, tendencias, zonas y proyecciones. Preguntale en criollo.'),
        h('div', { className: 'rep-presets' }, PRESETS.filter(function (p) { return canSeeCosts || !/plata|costo|costando/i.test(p); }).map(function (p) {
          return h('button', { key: p, type: 'button', className: 'rep-chip', disabled: busy, onClick: function () { setQ(p); analizar(p); } }, p);
        })),
        h('div', { className: 'rep-preg' },
          h('input', { className: 'input', value: q, placeholder: 'ej: ¿me conviene sumar una camioneta fija en OESTE?',
            'aria-label': 'Pregunta para CRÁNEO sobre el histórico',
            onChange: function (e) { setQ(e.target.value); },
            onKeyDown: function (e) { if (e.key === 'Enter' && q.trim()) analizar(q); } }),
          h(ui.Button, { variant: 'primary', disabled: busy, onClick: function () { analizar(q); } }, busy ? 'Analizando…' : 'Analizar')),
        busy ? h('div', { className: 'muted', style: { marginTop: 10 } }, '⏳ CRÁNEO está mirando los números…') : null,
        analisis ? h('div', { className: 'rep-analisis' },
          analisis.fuente === 'craneo' ? h('div', { className: 'cop-src' }, '🤖 respondió el agente CRÁNEO') : null,
          analisis.fuente === 'local' ? h('div', { className: 'cop-src', style: { opacity: .8 } }, 'análisis estadístico local (el agente no estaba disponible)') : null,
          analisis.stats ? h('div', { className: 'muted', style: { fontSize: 11.5, marginBottom: 6 } },
            'Período analizado: ' + analisis.stats.desde + ' → ' + analisis.stats.hasta + ' (' + analisis.stats.dias + ' días' + (analisis.stats.etiqueta ? ' · ' + analisis.stats.etiqueta : '') + ')') : null,
          fmtTexto(analisis.texto)) : null),

      // ── tabla día a día ──
      /* `data-novedad`: donde apunta el «Mostrame dónde» de la novedad de v1.0.15 (Reportes al día). Desde esa
         versión los días cerrados que no tienen foto guardada vienen armados de la liquidación (ver el backend,
         historialReportes): la pantalla no distingue, y no tiene por qué — la fuente sigue diciendo CRÁNEO. */
      conDatos.length ? h(ui.Card, { title: 'Día a día' + (zona || svc ? ' — rutas/costo/km de la etiqueta; cobertura y choferes son del día completo' : ''), 'data-novedad': 'reportes-al-dia' },
        h('div', { style: { overflowX: 'auto' } },
          h('table', { className: 'rep-tabla' },
            h('thead', null, h('tr', null, ['Fecha', 'Rutas'].concat(canSeeCosts ? ['Costo'] : []).concat(['Km', 'Cobertura', 'Choferes', 'Notif.', 'Fuente']).map(function (t) { return h('th', { key: t }, t); }))),
            h('tbody', null, filas.slice().reverse().map(function (f) {
              return h('tr', { key: f.fecha, className: f.rutas ? '' : 'rep-tabla__vacia' },
                h('td', null, f.fecha),
                h('td', null, f.rutas),
                canSeeCosts ? h('td', null, money(f.costoTotal)) : null,
                h('td', null, f.kmTotal),
                h('td', null, (f.cobertura != null ? f.cobertura + '%' : '—')),
                h('td', null, f.choferes != null ? f.choferes : '—'),
                h('td', null, f.notificados != null ? f.notificados : '—'),
                h('td', null, h('span', { className: 'badge badge--' + (f.fuente === 'craneo' ? 'info' : 'neutral'), style: { fontSize: 11 } },
                  f.fuente === 'craneo' ? 'CRÁNEO' : 'histórico real')));
            }))))) : null);
  }

  window.CR.screens = window.CR.screens || {};
  window.CR.screens.Reportes = Reportes;
})();
