/* MIRAI — Dashboard de clientes · sección Inicio (modo lectura) */

const { useState: uS, useEffect: uE, useRef: uR, useMemo: uM } = React;

// ============ ICONOS (SVG inline, sin dependencias) ============
function Icon({ name, size = 18 }) {
  const p = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.8, strokeLinecap: "round", strokeLinejoin: "round" };
  switch (name) {
    case "home": return <svg {...p}><path d="M3 10.5 12 3l9 7.5" /><path d="M5 9.5V21h14V9.5" /></svg>;
    case "chart": return <svg {...p}><line x1="6" y1="20" x2="6" y2="13" /><line x1="12" y1="20" x2="12" y2="8" /><line x1="18" y1="20" x2="18" y2="11" /></svg>;
    case "gear": return <svg {...p}><circle cx="12" cy="12" r="3" /><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.9l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.9-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 0 1-4 0v-.1a1.7 1.7 0 0 0-1.1-1.5 1.7 1.7 0 0 0-1.9.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.9 1.7 1.7 0 0 0-1.5-1H3a2 2 0 0 1 0-4h.1a1.7 1.7 0 0 0 1.5-1.1 1.7 1.7 0 0 0-.3-1.9l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.9.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 0 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.9-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.9V9a1.7 1.7 0 0 0 1.5 1H21a2 2 0 0 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1Z" /></svg>;
    case "user": return <svg {...p}><circle cx="12" cy="8" r="4" /><path d="M4 20c0-4 4-6 8-6s8 2 8 6" /></svg>;
    case "calendar": return <svg {...p}><rect x="3" y="4" width="18" height="17" rx="2" /><line x1="3" y1="9" x2="21" y2="9" /><line x1="8" y1="2" x2="8" y2="6" /><line x1="16" y1="2" x2="16" y2="6" /></svg>;
    case "filter": return <svg {...p}><path d="M3 5h18" /><path d="M6 12h12" /><path d="M10 19h4" /></svg>;
    case "trend": return <svg {...p}><path d="M3 17l6-6 4 4 8-8" /><path d="M17 7h4v4" /></svg>;
    case "chevron": return <svg {...p}><path d="M6 9l6 6 6-6" /></svg>;
    case "close": return <svg {...p}><line x1="6" y1="6" x2="18" y2="18" /><line x1="18" y1="6" x2="6" y2="18" /></svg>;
    case "menu": return <svg {...p}><line x1="4" y1="7" x2="20" y2="7" /><line x1="4" y1="12" x2="20" y2="12" /><line x1="4" y1="17" x2="20" y2="17" /></svg>;
    case "search": return <svg {...p}><circle cx="11" cy="11" r="7" /><line x1="16.5" y1="16.5" x2="21" y2="21" /></svg>;
    case "radar": return <svg {...p}><circle cx="12" cy="12" r="9" /><circle cx="12" cy="12" r="4.6" /><circle cx="12" cy="12" r="1.2" fill="currentColor" stroke="none" /><path d="M12 3v3" /><path d="M12 18v3" /><path d="M3 12h3" /><path d="M18 12h3" /></svg>;
    case "heart": return <svg {...p}><path d="M20.8 7.6a4.6 4.6 0 0 0-7.8-2.2L12 6.3l-1-1A4.6 4.6 0 0 0 3.2 7.6c0 3.4 3.5 6 8.8 10.8 5.3-4.8 8.8-7.4 8.8-10.8z" /></svg>;
    case "heart-fill": return <svg {...p} fill="currentColor" stroke="currentColor"><path d="M20.8 7.6a4.6 4.6 0 0 0-7.8-2.2L12 6.3l-1-1A4.6 4.6 0 0 0 3.2 7.6c0 3.4 3.5 6 8.8 10.8 5.3-4.8 8.8-7.4 8.8-10.8z" /></svg>;
    case "external": return <svg {...p}><path d="M14 4h6v6" /><path d="M20 4 11 13" /><path d="M18 13v6a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h6" /></svg>;
    case "sparkle": return <svg {...p} fill="currentColor" stroke="none"><path d="M12 3l1.7 4.8L18.5 9.5l-4.8 1.7L12 16l-1.7-4.8L5.5 9.5l4.8-1.7z" /><path d="M18.5 14l.6 1.8 1.9.7-1.9.7-.6 1.8-.6-1.8-1.9-.7 1.9-.7z" /></svg>;
    case "info": return <svg {...p}><circle cx="12" cy="12" r="9" /><line x1="12" y1="11" x2="12" y2="16" /><line x1="12" y1="8" x2="12.01" y2="8" /></svg>;
    case "arrow": return <svg {...p}><line x1="5" y1="12" x2="19" y2="12" /><path d="M13 6l6 6-6 6" /></svg>;
    case "refresh": return <svg {...p}><path d="M21 12a9 9 0 1 1-2.64-6.36" /><path d="M21 3v5h-5" /></svg>;
    case "inbox": return <svg {...p}><path d="M3 12h5l2 3h4l2-3h5" /><path d="M5 6h14l2 6v6a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-6Z" /></svg>;
    case "pause": return <svg {...p} fill="currentColor" stroke="none"><rect x="6.5" y="5" width="3.6" height="14" rx="1.2" /><rect x="13.9" y="5" width="3.6" height="14" rx="1.2" /></svg>;
    case "play": return <svg {...p} fill="currentColor" stroke="none"><path d="M7 4.5v15l12-7.5z" /></svg>;
    case "dots": return <svg {...p} fill="currentColor" stroke="none"><circle cx="12" cy="5" r="1.7" /><circle cx="12" cy="12" r="1.7" /><circle cx="12" cy="19" r="1.7" /></svg>;
    case "smile": return <svg {...p}><circle cx="12" cy="12" r="9" /><path d="M8.5 14.5s1.4 1.8 3.5 1.8 3.5-1.8 3.5-1.8" /><line x1="9" y1="9.5" x2="9.01" y2="9.5" /><line x1="15" y1="9.5" x2="15.01" y2="9.5" /></svg>;
    case "clip": return <svg {...p}><path d="M21 11.5 12.3 20.2a5 5 0 0 1-7.1-7.1l8.5-8.5a3.3 3.3 0 1 1 4.7 4.7l-8.5 8.5a1.6 1.6 0 0 1-2.3-2.3l7.8-7.8" /></svg>;
    case "send": return <svg {...p}><path d="M22 2 11 13" /><path d="M22 2 15 22l-4-9-9-4z" /></svg>;
    case "phone": return <svg {...p}><path d="M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3.1 19.5 19.5 0 0 1-6-6A19.8 19.8 0 0 1 2.1 4.2 2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.7c.1 1 .4 1.9.7 2.8a2 2 0 0 1-.5 2.1L8.1 9.9a16 16 0 0 0 6 6l1.3-1.3a2 2 0 0 1 2.1-.4c.9.3 1.8.6 2.8.7a2 2 0 0 1 1.7 2z" /></svg>;
    case "at": return <svg {...p}><circle cx="12" cy="12" r="4" /><path d="M16 12v1.5a2.5 2.5 0 0 0 5 0V12a9 9 0 1 0-3.5 7.1" /></svg>;
    case "pin": return <svg {...p}><path d="M12 21s-7-5.6-7-11a7 7 0 0 1 14 0c0 5.4-7 11-7 11z" /><circle cx="12" cy="10" r="2.6" /></svg>;
    case "wallet": return <svg {...p}><rect x="3" y="6" width="18" height="13" rx="2.5" /><path d="M3 10.5h18" /><circle cx="16.5" cy="13.8" r="1.1" fill="currentColor" stroke="none" /></svg>;
    case "target": return <svg {...p}><circle cx="12" cy="12" r="8.5" /><circle cx="12" cy="12" r="3.3" /></svg>;
    case "edit": return <svg {...p}><path d="M12 20h9" /><path d="M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4z" /></svg>;
    case "clock": return <svg {...p}><circle cx="12" cy="12" r="9" /><path d="M12 7.5V12l3 2" /></svg>;
    case "sliders": return <svg {...p}><path d="M4 6h16" /><path d="M4 12h16" /><path d="M4 18h16" /><circle cx="9" cy="6" r="2.2" fill="var(--ibx-knob, #fff)" /><circle cx="15" cy="12" r="2.2" fill="var(--ibx-knob, #fff)" /><circle cx="8" cy="18" r="2.2" fill="var(--ibx-knob, #fff)" /></svg>;
    case "plus": return <svg {...p}><line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" /></svg>;
    case "user-plus": return <svg {...p}><circle cx="9" cy="8" r="4" /><path d="M2 20c0-3.8 3.5-5.8 7-5.8" /><line x1="17" y1="9" x2="17" y2="15" /><line x1="14" y1="12" x2="20" y2="12" /></svg>;
    case "check2": return <svg {...p} strokeWidth="2"><path d="M2 12.5 6 16l1.2-1.5" /><path d="M8.5 13.5 12.5 17 22 6.5" /></svg>;
    case "ticket": return <svg {...p}><rect x="4" y="3" width="16" height="18" rx="2" /><path d="M9 3v2.5M15 3v2.5" /><line x1="8" y1="10" x2="16" y2="10" /><line x1="8" y1="14" x2="13" y2="14" /></svg>;
    case "comment": return <svg {...p}><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" /></svg>;
    case "copy": return <svg {...p}><rect x="9" y="9" width="12" height="12" rx="2" /><path d="M5 15H4a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v1" /></svg>;
    case "tablero": return <svg {...p}><rect x="3" y="3" width="18" height="18" rx="2" /><line x1="3" y1="9" x2="21" y2="9" /><line x1="3" y1="15" x2="21" y2="15" /><line x1="9" y1="3" x2="9" y2="21" /><line x1="15" y1="3" x2="15" y2="21" /></svg>;
    default: return null;
  }
}

// Íconos de marca (con su color como única señal de color)
function WhatsAppIcon({ size = 18, color = "#25D366" }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill={color} aria-hidden="true">
      <path d="M12.04 2C6.58 2 2.13 6.45 2.13 11.91c0 1.75.46 3.45 1.32 4.95L2 22l5.25-1.38a9.9 9.9 0 0 0 4.79 1.22h.01c5.46 0 9.91-4.45 9.91-9.91 0-2.65-1.03-5.14-2.9-7.01A9.82 9.82 0 0 0 12.04 2Zm5.8 14.06c-.24.68-1.4 1.3-1.94 1.38-.5.07-1.12.1-1.81-.11-.42-.13-.95-.31-1.64-.61-2.88-1.24-4.76-4.14-4.9-4.33-.14-.19-1.17-1.56-1.17-2.98 0-1.42.74-2.12 1.01-2.41.27-.29.58-.36.78-.36l.56.01c.18.01.42-.07.66.5.24.59.82 2.01.89 2.16.07.14.12.31.02.5-.1.19-.15.31-.29.48-.14.17-.3.38-.43.51-.14.14-.29.29-.12.58.17.29.74 1.22 1.59 1.98 1.09.97 2.01 1.27 2.3 1.41.29.14.46.12.63-.07.17-.19.73-.85.92-1.14.19-.29.39-.24.66-.14.27.1 1.69.8 1.98.94.29.14.48.22.55.34.07.12.07.69-.17 1.37Z" />
    </svg>
  );
}
function InstagramIcon({ size = 18, mono = false }) {
  if (mono) {
    return (
      <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="1.8" aria-hidden="true">
        <rect x="3" y="3" width="18" height="18" rx="5" />
        <circle cx="12" cy="12" r="4" />
        <circle cx="17" cy="7" r="1.1" fill="#fff" stroke="none" />
      </svg>
    );
  }
  const gid = "ig-grad";
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" aria-hidden="true">
      <defs>
        <radialGradient id={gid} cx="0.3" cy="1" r="1.1">
          <stop offset="0%" stopColor="#FFD776" />
          <stop offset="35%" stopColor="#F35369" />
          <stop offset="70%" stopColor="#C837AB" />
          <stop offset="100%" stopColor="#5B51D8" />
        </radialGradient>
      </defs>
      <rect x="2" y="2" width="20" height="20" rx="6" fill={`url(#${gid})`} />
      <rect x="6" y="6" width="12" height="12" rx="4" fill="none" stroke="#fff" strokeWidth="1.6" />
      <circle cx="12" cy="12" r="3" fill="none" stroke="#fff" strokeWidth="1.6" />
      <circle cx="16.4" cy="7.6" r="1.1" fill="#fff" />
    </svg>
  );
}
function ChannelIcon({ channel, size = 18 }) {
  return channel === "instagram" ? <InstagramIcon size={size} /> : <WhatsAppIcon size={size} />;
}

// ============ HOOK: medir ancho de contenedor (para charts responsivos) ============
function useMeasure() {
  const ref = uR(null);
  const [w, setW] = uS(0);
  uE(() => {
    if (!ref.current) return;
    const el = ref.current;
    const update = () => setW(el.clientWidth);
    update();
    let ro;
    if (typeof ResizeObserver !== "undefined") {
      ro = new ResizeObserver(update);
      ro.observe(el);
    } else {
      window.addEventListener("resize", update);
    }
    return () => { if (ro) ro.disconnect(); else window.removeEventListener("resize", update); };
  }, []);
  return [ref, w];
}

// ============ GRÁFICO DE LÍNEAS (SVG) ============
function ConsultationsLineChart({ data }) {
  const [ref, w] = useMeasure();
  const [hover, setHover] = uS(null);
  const H = 240;
  const padL = 32, padR = 14, padT = 16, padB = 28;
  const width = w || 600;
  const plotW = Math.max(10, width - padL - padR);
  const plotH = H - padT - padB;
  // Techo del eje Y: 60 por defecto (pensado para volúmenes por día), pero si
  // los datos lo superan escala hacia arriba en pasos "lindos" para no cortar la línea.
  const dataPeak = Math.max(0, ...data.consultas, ...data.leads);
  const step = dataPeak <= 60 ? 12 : dataPeak <= 120 ? 20 : 50;
  const maxY = dataPeak <= 60 ? 60 : Math.ceil(dataPeak * 1.1 / step) * step;
  const n = data.consultas.length;
  const xAt = (i) => padL + (n <= 1 ? 0 : (i * plotW) / (n - 1));
  const yAt = (v) => padT + (1 - v / maxY) * plotH;
  const toPath = (arr) => arr.map((v, i) => `${i === 0 ? "M" : "L"}${xAt(i).toFixed(1)},${yAt(v).toFixed(1)}`).join(" ");
  const grid = [0, 1, 2, 3, 4, 5].map((i) => Math.round((i * maxY) / 5));
  // etiquetas X: mostramos las definidas en data.labels, repartidas en el eje
  const labelEvery = Math.max(1, Math.round(n / data.labels.length));

  const onMove = (e) => {
    const rect = e.currentTarget.getBoundingClientRect();
    const mx = e.clientX - rect.left;
    let idx = Math.round(((mx - padL) / plotW) * (n - 1));
    idx = Math.max(0, Math.min(n - 1, idx));
    setHover(idx);
  };

  return (
    <div className="dash-chart" ref={ref}>
      <svg width={width} height={H} role="img" onMouseMove={onMove} onMouseLeave={() => setHover(null)}>
        {grid.map((g) => (
          <g key={g}>
            <line x1={padL} y1={yAt(g)} x2={width - padR} y2={yAt(g)} stroke="var(--chart-grid, rgba(0,0,0,0.07))" strokeWidth="1" />
            <text x={padL - 8} y={yAt(g) + 3} textAnchor="end" className="dash-chart__axis">{g}</text>
          </g>
        ))}
        {data.labels.map((lb, li) => {
          const i = Math.min(n - 1, li * labelEvery);
          return <text key={lb} x={xAt(i)} y={H - 8} textAnchor="middle" className="dash-chart__axis">{lb}</text>;
        })}
        <path d={toPath(data.leads)} fill="none" stroke="var(--chart-leads, #b6b6b6)" strokeWidth="2" />
        <path d={toPath(data.consultas)} fill="none" stroke="var(--chart-ink, #000)" strokeWidth="2.2" />
        {hover !== null && (
          <g>
            <line x1={xAt(hover)} y1={padT} x2={xAt(hover)} y2={padT + plotH} stroke="var(--chart-grid, rgba(0,0,0,0.18))" strokeWidth="1" strokeDasharray="3 3" />
            <circle cx={xAt(hover)} cy={yAt(data.consultas[hover])} r="3.5" fill="var(--chart-ink, #000)" />
            <circle cx={xAt(hover)} cy={yAt(data.leads[hover])} r="3.5" fill="var(--chart-leads, #b6b6b6)" />
          </g>
        )}
      </svg>
      {hover !== null && (
        <div
          className="dash-chart__tip"
          style={{ left: Math.min(width - 130, Math.max(0, xAt(hover) - 60)), top: 6 }}>
          <div className="dash-chart__tip-row"><span className="dot dot--dark"></span>Consultas <b>{data.consultas[hover]}</b></div>
          <div className="dash-chart__tip-row"><span className="dot dot--gray"></span>Leads <b>{data.leads[hover]}</b></div>
        </div>
      )}
    </div>
  );
}

// ============ GRÁFICO DE DONA (SVG) ============
function ConsultationResultsChart({ data }) {
  const size = 150, stroke = 22, r = (size - stroke) / 2, c = 2 * Math.PI * r;
  let acc = 0;
  return (
    <div className="dash-donut">
      <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
        <g transform={`rotate(-90 ${size / 2} ${size / 2})`}>
          {data.map((seg) => {
            const len = (seg.value / 100) * c;
            const el = (
              <circle
                className="dash-donut__seg"
                key={seg.label}
                cx={size / 2} cy={size / 2} r={r}
                fill="none" stroke={seg.color} strokeWidth={stroke}
                strokeDasharray={`${len} ${c - len}`} strokeDashoffset={-acc}>
                <title>{`${seg.label}: ${seg.value}%`}</title>
              </circle>
            );
            acc += len;
            return el;
          })}
        </g>
        <text x={size / 2} y={size / 2 - 2} textAnchor="middle" className="dash-donut__total">100%</text>
        <text x={size / 2} y={size / 2 + 14} textAnchor="middle" className="dash-donut__total-label">Total</text>
      </svg>
    </div>
  );
}

// ============ DONA INTERACTIVA + LEYENDA (tarjeta "Resultado de las consultas") ============
const RESULT_SHORT_LABEL = {
  "Resueltas por Emma": "Emma",
  "Derivadas correctamente": "Derivadas",
  "En conversación": "En curso",
  "No resueltas": "No resueltas",
  "Resueltas manualmente": "Manual",
};

function ConsultationResultsCard({ data }) {
  const [sel, setSel] = uS(null);
  const [ready, setReady] = uS(false);
  uE(() => {
    setReady(false);
    const t = requestAnimationFrame(() => requestAnimationFrame(() => setReady(true)));
    return () => cancelAnimationFrame(t);
  }, [data]);

  // `pad` deja lugar dentro del lienzo SVG para que el aro más grueso del
  // segmento activo (hover) no quede recortado contra el borde del viewBox.
  const size = 150, stroke = 22, pad = 6, canvas = size + pad * 2, r = (size - stroke) / 2, c = 2 * Math.PI * r;
  let acc = 0;
  const active = sel != null ? data[sel] : null;
  // Los valores reales (redondeados por separado en el backend) no siempre suman
  // exactamente 100 — normalizamos contra la suma real al calcular los arcos para
  // que siempre cierren el círculo sin superponerse ni dejar hueco, sin tocar el
  // % que se muestra en la leyenda/tooltip/centro.
  const totalValue = data.reduce((s, seg) => s + (seg.value || 0), 0) || 100;

  return (
    <div className="dash-card">
      <h3 className="dash-card__title">Resultado de las consultas</h3>
      <div className="dash-results dash-results--interactive">
        <div className="dash-donut" onMouseLeave={() => setSel(null)}>
          <svg width={canvas} height={canvas} viewBox={`0 0 ${canvas} ${canvas}`} overflow="visible">
            <g transform={`rotate(-90 ${canvas / 2} ${canvas / 2})`}>
              {data.map((seg, i) => {
                const fullLen = (seg.value / totalValue) * c;
                const len = ready ? fullLen : 0;
                const segStart = acc;
                acc += fullLen;
                return (
                  <circle
                    key={seg.label}
                    className={`dash-donut__seg ${sel != null && sel !== i ? "is-dim" : ""} ${sel === i ? "is-active" : ""}`}
                    cx={canvas / 2} cy={canvas / 2} r={r}
                    fill="none" stroke={seg.color} strokeWidth={stroke}
                    strokeDasharray={`${len} ${c - len}`} strokeDashoffset={-segStart}
                    onMouseEnter={() => setSel(i)}
                    onClick={() => setSel((cur) => (cur === i ? null : i))}>
                    <title>{`${seg.label}: ${seg.value}%`}</title>
                  </circle>
                );
              })}
            </g>
            <text x={canvas / 2} y={canvas / 2 - 2} textAnchor="middle" className="dash-donut__total">
              {active ? `${active.value}%` : "100%"}
            </text>
            <text x={canvas / 2} y={canvas / 2 + 14} textAnchor="middle" className="dash-donut__total-label">
              {active ? (RESULT_SHORT_LABEL[active.label] || active.label) : "Total"}
            </text>
          </svg>
        </div>
        <ul className="dash-results__legend">
          {data.map((seg, i) => (
            <li key={seg.label}
              className={`dash-results__row ${sel != null && sel !== i ? "is-dim" : ""} ${sel === i ? "is-active" : ""}`}
              onMouseEnter={() => setSel(i)} onMouseLeave={() => setSel(null)}
              onClick={() => setSel((cur) => (cur === i ? null : i))}>
              <span className="dash-results__dot" style={{ background: seg.color }}></span>
              <span className="dash-results__name">{seg.label}</span>
              <span className="dash-results__bar"><span className="dash-results__bar-fill" style={{ width: ready ? `${seg.value}%` : "0%", background: seg.color }}></span></span>
              <span className="dash-results__pct">{seg.value}%</span>
            </li>
          ))}
        </ul>
      </div>
    </div>
  );
}

// ============ SIDEBAR ============
function DashboardSidebar({ active, onComingSoon, open, onClose, user }) {
  const [chPrefs] = useChannelPrefs(user);
  const items = [
    { key: "inicio", label: "Inicio", href: "#/dashboard", icon: (act) => <Icon name="home" /> },
    { key: "whatsapp", label: "WhatsApp", href: "#/dashboard/whatsapp", icon: (act) => <WhatsAppIcon color={act ? "#fff" : "#25D366"} />, show: chPrefs.whatsappEnabled },
    { key: "instagram", label: "Instagram", href: "#/dashboard/instagram", icon: (act) => <InstagramIcon mono={act} />, show: chPrefs.instagramEnabled },
    { key: "crm",      label: "CRM",      href: "#/dashboard/crm",      icon: (act) => <Icon name="user" />,   show: chPrefs.crmEnabled },
    { key: "tablero",  label: "Tablero",  href: "#/dashboard/tablero",  icon: (act) => <Icon name="tablero" /> },
    { key: "rastreo",  label: "Rastreo",  href: "#/dashboard/rastreo",  icon: (act) => <Icon name="radar" />,  show: chPrefs.rastreoEnabled },
    { key: "tickets",  label: "Tickets",  href: "#/dashboard/tickets",  icon: (act) => <Icon name="ticket" />, show: chPrefs.ticketsEnabled },
  ].filter((it) => it.show !== false);
  return (
    <>
      <div className={`dash-sb__scrim ${open ? "is-open" : ""}`} onClick={onClose}></div>
      <aside className={`dash-sb ${open ? "is-open" : ""}`}>
        <a href="#/" className="dash-sb__logo" aria-label="MIRAI">
          <img className="dash-sb__logo-light" src="assets/mirailogo3.png" alt="MIRAI" />
          <img className="dash-sb__logo-dark" src="assets/mirailogo3-blanco.png" alt="MIRAI" />
        </a>
        <nav className="dash-sb__nav">
          {items.map((it) => {
            const act = active === it.key;
            return (
              <a
                key={it.key}
                href={it.href}
                className={`dash-sb__item ${act ? `is-active is-${it.key}` : ""}`}
                onClick={onClose}>
                <span className="dash-sb__icon">{it.icon(act)}</span>
                <span>{it.label}</span>
              </a>
            );
          })}
        </nav>
        <div className="dash-sb__foot">
          <a
            href="#/dashboard/configuracion"
            className={`dash-sb__item ${active === "configuracion" ? "is-active is-configuracion" : ""}`}
            onClick={onClose}>
            <span className="dash-sb__icon"><Icon name="gear" /></span>
            <span>Configuración</span>
          </a>
        </div>
      </aside>
    </>
  );
}

// ============ MENÚ DESPLEGABLE / DROPDOWN GENÉRICO ============
// portal=true: el menú se renderiza en document.body con position:fixed en
// vez de quedar absoluto dentro de .dd — evita que se corte cuando el botón
// está cerca del borde de un contenedor con overflow:hidden/auto (p.ej. la
// última fila de una tabla dentro de una card).
function Dropdown({ button, children, align = "left", className = "", portal = false, closeOnItemClick = true }) {
  const [open, setOpen] = uS(false);
  const [pos, setPos] = uS(null);
  const ref = uR(null);
  const menuRef = uR(null);

  uE(() => {
    if (!open) return;
    const onDoc = (e) => {
      const insideTrigger = ref.current && ref.current.contains(e.target);
      const insideMenu = menuRef.current && menuRef.current.contains(e.target);
      if (!insideTrigger && !insideMenu) setOpen(false);
    };
    document.addEventListener("mousedown", onDoc);
    return () => document.removeEventListener("mousedown", onDoc);
  }, [open]);

  // useLayoutEffect (no uE/useEffect): calcula la posición antes del paint
  // para que el menú no "salte" de lugar en el primer frame. Si no entra
  // debajo del botón dentro de la ventana, lo abre hacia arriba.
  React.useLayoutEffect(() => {
    if (!open || !portal || !ref.current) return;
    const rect = ref.current.getBoundingClientRect();
    const ESTIMATED_MENU_H = 260;
    const openUp = window.innerHeight - rect.bottom < ESTIMATED_MENU_H && rect.top > ESTIMATED_MENU_H;
    // Siempre fijar top Y bottom (uno en "auto"): la clase .dd__menu trae un
    // top por defecto que si no se pisa explícitamente queda activo a la vez
    // que el bottom inline, y el navegador calcula la altura como la
    // distancia entre ambos en vez de ajustarla al contenido.
    const vertical = openUp
      ? { top: "auto", bottom: window.innerHeight - rect.top + 8 }
      : { top: rect.bottom + 8, bottom: "auto" };
    setPos({
      ...vertical,
      ...(align === "right" ? { right: window.innerWidth - rect.right } : { left: rect.left }),
    });
  }, [open, portal, align]);

  const menu = open && (
    <div
      ref={menuRef}
      className={`dd__menu dd__menu--${align}`}
      style={portal && pos ? { position: "fixed", top: pos.top, bottom: pos.bottom, left: pos.left, right: pos.right } : undefined}
      onClick={closeOnItemClick ? () => setOpen(false) : undefined}>
      {children}
    </div>
  );

  return (
    <div className={`dd ${className}`} ref={ref}>
      {button(open, () => setOpen((v) => !v))}
      {portal ? (open ? ReactDOM.createPortal(menu, document.body) : null) : menu}
    </div>
  );
}

// ============ FILTROS ============
const CHANNEL_OPTS = [
  { key: "all",       label: "Todos" },
  { key: "whatsapp",  label: "WhatsApp" },
  { key: "instagram", label: "Instagram" },
  { key: "crm",       label: "CRM" },
];

function ChannelDropdown({ filters, setFilters }) {
  const sel = CHANNEL_OPTS.find((c) => c.key === filters.channel) || CHANNEL_OPTS[0];

  let triggerStyle = {};
  if (sel.key === "whatsapp")  triggerStyle = { background: "#25D366", color: "#fff", borderColor: "#25D366" };
  if (sel.key === "instagram") triggerStyle = { background: "linear-gradient(90deg, #8134AF 0%, #C837AB 38%, #F35369 70%, #F58529 100%)", color: "#fff", borderColor: "transparent" };
  if (sel.key === "crm")       triggerStyle = { background: "#C0003B", color: "#fff", borderColor: "#C0003B" };

  return (
    <Dropdown
      align="right"
      button={(open, toggle) => (
        <button className="dash-pill" style={triggerStyle} onClick={toggle}>
          {sel.key === "whatsapp"  && <WhatsAppIcon size={15} color="#fff" />}
          {sel.key === "instagram" && <InstagramIcon size={15} mono={true} />}
          {sel.key === "crm"       && <Icon name="user" size={14} />}
          {sel.label}
          <Icon name="chevron" size={16} />
        </button>
      )}>
      {CHANNEL_OPTS.map((c) => (
        <button
          key={c.key}
          className={`dd__opt ${filters.channel === c.key ? "is-sel" : ""}`}
          onClick={() => setFilters({ ...filters, channel: c.key })}>
          <span style={{ display: "inline-flex", alignItems: "center", gap: 8 }}>
            {c.key === "whatsapp"  && <WhatsAppIcon size={15} color="#25D366" />}
            {c.key === "instagram" && <InstagramIcon size={15} />}
            {c.key === "crm"       && <Icon name="user" size={14} style={{ color: "#C0003B" }} />}
            {c.label}
          </span>
        </button>
      ))}
    </Dropdown>
  );
}

function DashboardFilters({ filters, setFilters, env, setEnv, showEnvSwitch }) {
  const periodLabel = (DASH_PERIODS.find((p) => p.key === filters.period) || {}).label;
  return (
    <div className="dash-filters">
      <Dropdown
        align="right"
        button={(open, toggle) => (
          <button className="dash-pill" onClick={toggle}>
            <Icon name="calendar" size={16} /> {periodLabel} <Icon name="chevron" size={16} />
          </button>
        )}>
        {DASH_PERIODS.map((p) => (
          <button key={p.key} className={`dd__opt ${filters.period === p.key ? "is-sel" : ""}`} onClick={() => setFilters({ ...filters, period: p.key })}>{p.label}</button>
        ))}
      </Dropdown>

      <ChannelDropdown filters={filters} setFilters={setFilters} />

      {showEnvSwitch && <EnvSwitch env={env} setEnv={setEnv} />}
    </div>
  );
}

// ============ SELECTOR DE ENTORNO (tester / producción) ============
function EnvSwitch({ env, setEnv }) {
  const sel = MIRAI_ENVIRONMENTS.find((e) => e.key === env) || MIRAI_ENVIRONMENTS[0];
  return (
    <Dropdown
      align="right"
      button={(open, toggle) => (
        <button className="dash-pill" onClick={toggle}>
          <Icon name="radar" size={16} /> {sel.label} <Icon name="chevron" size={16} />
        </button>
      )}>
      {MIRAI_ENVIRONMENTS.map((e) => (
        <button key={e.key} className={`dd__opt ${env === e.key ? "is-sel" : ""}`} onClick={() => setEnv(e.key)}>{e.label}</button>
      ))}
    </Dropdown>
  );
}

// ============ BOTÓN DE ACTUALIZACIÓN MANUAL + ÚLTIMA ACTUALIZACIÓN ============
function RefreshControl({ onRefresh, loading, lastUpdated }) {
  return (
    <div className="dash-refresh">
      {lastUpdated && (
        <span className="dash-refresh__time" title="Última actualización">
          Actualizado {miraiFmtTime(lastUpdated)}
        </span>
      )}
      <button
        className={`dash-iconbtn dash-refresh__btn ${loading ? "is-spinning" : ""}`}
        onClick={onRefresh}
        disabled={loading}
        aria-label="Actualizar datos"
        title="Actualizar datos">
        <Icon name="refresh" size={18} />
      </button>
    </div>
  );
}

// ============ TARJETA DE MÉTRICA ============
// Anima de 0 al valor numérico cuando éste cambia (count-up). Para valores de
// texto (p.ej. "WhatsApp") o con unidades raras, muestra el texto tal cual.
function useCountUp(target, active, duration = 900) {
  const [val, setVal] = uS(target);
  const prev = uR(target);
  uE(() => {
    if (!active) { setVal(target); return; }
    const from = prev.current || 0;
    const to = target;
    prev.current = to;
    if (from === to) { setVal(to); return; }
    let raf;
    const start = performance.now();
    const tick = (t) => {
      const p = Math.min(1, (t - start) / duration);
      const eased = 1 - Math.pow(1 - p, 3);
      setVal(from + (to - from) * eased);
      if (p < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [target, active, duration]);
  return val;
}

function MetricCard({ m }) {
  const dirCls = m.dir === "up" ? "is-up" : m.dir === "down-good" ? "is-up" : m.dir === "up-bad" ? "is-down" : "";
  const raw = String(m.value);
  const isText = /[A-Za-z]/.test(raw);
  // Detecta valores puramente numéricos (con separadores de miles y % opcional).
  const numMatch = /^([\d.]+)\s*(%?)$/.exec(raw.replace(/\./g, "").replace(",", "."));
  const animate = !isText && numMatch != null;
  const targetNum = animate ? parseFloat(numMatch[1]) : 0;
  const suffix = animate ? numMatch[2] : "";
  const reduced = typeof matchMedia !== "undefined" && matchMedia("(prefers-reduced-motion: reduce)").matches;
  const animVal = useCountUp(targetNum, animate && !reduced);
  const shown = animate
    ? `${Math.round(animVal).toLocaleString("es-AR")}${suffix}`
    : raw;
  return (
    <div className="dash-metric">
      <span className="dash-metric__label">{m.label}</span>
      <span className={`dash-metric__value ${isText ? "dash-metric__value--text" : ""}`}>{shown}</span>
      {m.delta && <span className={`dash-metric__delta ${dirCls}`}>{m.delta}</span>}
      {m.note && <span className="dash-metric__note">{m.note}</span>}
    </div>
  );
}

// ============ DESGLOSE DE CANALES ============
function ChannelBreakdown({ channels }) {
  return (
    <div className="dash-channels">
      {channels.map((ch, i) => (
        <div key={ch.key} className={`dash-channels__row ${i > 0 ? "has-sep" : ""}`}>
          <span className="dash-channels__icon"><ChannelIcon channel={ch.key} size={26} /></span>
          <div className="dash-channels__body">
            <span className="dash-channels__name">{ch.label}</span>
            <span className="dash-channels__pct">{ch.pct}%</span>
            <span className="dash-channels__sub">{ch.count.toLocaleString("es-AR")} consultas</span>
          </div>
        </div>
      ))}
    </div>
  );
}

// ============ PASTILLA DE ESTADO ============
function StatusPill({ status }) {
  const cfg = DASH_STATUS[status] || { label: status, cls: "" };
  return <span className={`dash-tag ${cfg.cls}`}>{cfg.label}</span>;
}

// ============ TABLA DE CONSULTAS ============
function RecentConsultationsTable({ rows, onSelect }) {
  return (
    <div className="dash-table-wrap">
      <table className="dash-table">
        <thead>
          <tr>
            <th>Cliente</th><th>Canal</th><th>Intención</th><th>Zona</th><th>Presupuesto</th><th>Estado</th><th>Fecha</th>
          </tr>
        </thead>
        <tbody>
          {rows.map((r) => (
            <tr key={r.id} onClick={() => onSelect(r)} tabIndex={0}
              onKeyDown={(e) => { if (e.key === "Enter") onSelect(r); }}>
              <td className="dash-table__name">{r.name}</td>
              <td><span className="dash-table__channel"><ChannelIcon channel={r.channel} size={16} /> {r.channel === "instagram" ? "Instagram" : "WhatsApp"}</span></td>
              <td>{r.intent}</td>
              <td>{r.zone}</td>
              <td>{r.budget}</td>
              <td><StatusPill status={r.status} /></td>
              <td className="dash-table__date">{r.dateLabel}</td>
            </tr>
          ))}
          {rows.length === 0 && (
            <tr><td colSpan={7} className="dash-table__empty">No hay consultas para los filtros seleccionados.</td></tr>
          )}
        </tbody>
      </table>
    </div>
  );
}

// ============ DRAWER DE DETALLE (modo lectura) ============
function ConsultationDetailDrawer({ row, onClose, onGoToChat, onCopyDiagnosis, onAssign }) {
  uE(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    document.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => { document.removeEventListener("keydown", onKey); document.body.style.overflow = ""; };
  }, []);
  if (!row) return null;
  const d = row.detail;
  const fields = [
    ["Nombre", row.name], ["Canal", row.channel === "instagram" ? "Instagram" : "WhatsApp"],
    [row.channel === "instagram" ? "Usuario" : "Teléfono", d.contact],
    ["Intención", row.intent], ["Zona", row.zone], ["Tipo de propiedad", d.propertyType],
    ["Ambientes", d.ambientes], ["Presupuesto", row.budget], ["Forma de pago", d.payment],
    ["Características", d.features], ["Hora de ingreso", d.entryTime], ["Hora de derivación", d.derivTime],
  ];
  const diagnosisText = d.summary && miraiFormatDiagnosis({
    name: row.name, operator: (row.derivedTo || []).join(", "), phone: d.contact, intent: row.intentRaw || row.intent, summary: d.summary,
  });
  return (
    <div className="dash-drawer" role="dialog" aria-modal="true">
      <div className="dash-drawer__scrim" onClick={onClose}></div>
      <div className="dash-drawer__panel">
        <header className="dash-drawer__head">
          <div className="dash-drawer__head-main">
            <span className="dash-drawer__icon"><ChannelIcon channel={row.channel} size={22} /></span>
            <div>
              <h3 className="dash-drawer__name">{row.name}</h3>
              <div className="dash-drawer__meta">
                <StatusPill status={row.status} />
                <span className="dash-drawer__time">{d.contact}</span>
              </div>
            </div>
          </div>
          <button className="dash-iconbtn" onClick={onClose} aria-label="Cerrar"><Icon name="close" /></button>
        </header>

        <div className="dash-drawer__body">
          <section className="dash-drawer__section">
            <div className="dash-drawer__field dash-tb__derivedfield">
              <span className="dash-drawer__field-k">Derivado a</span>
              <TableroAssignDropdown current={row.derivedTo} onAssign={(p) => onAssign(row, p)} />
            </div>
            <div className="dash-tb__quickactions">
              <button type="button" className={`dash-tb__gochat is-${row.channel}`} onClick={() => onGoToChat(row)}>
                <Icon name="send" size={15} /> Ir a la conversación de {row.channel === "instagram" ? "Instagram" : "WhatsApp"}
              </button>
              <button type="button" className="dash-ibx__btn dash-ibx__btn--diagnosis" onClick={() => onCopyDiagnosis(row)}>
                <Icon name="copy" size={15} /> Copiar diagnóstico
              </button>
            </div>
          </section>

          <section className="dash-drawer__section">
            <h4 className="dash-drawer__title">Diagnóstico</h4>
            <p className="dash-drawer__summary">{diagnosisText}</p>
          </section>

          <section className="dash-drawer__section">
            <h4 className="dash-drawer__title">Datos del lead</h4>
            <div className="dash-drawer__grid">
              {fields.map(([k, v]) => (
                <div key={k} className="dash-drawer__field">
                  <span className="dash-drawer__field-k">{k}</span>
                  <span className="dash-drawer__field-v">{v || "—"}</span>
                </div>
              ))}
            </div>
          </section>
        </div>

        <footer className="dash-drawer__foot">
          <button className="btn btn--ghost btn--sm" onClick={onClose}>Cerrar</button>
        </footer>
      </div>
    </div>
  );
}

// ============ PANEL: ZONAS MÁS BUSCADAS ============
function TopZonesCard({ zones, onMore }) {
  return (
    <div className="dash-card dash-list-card">
      <h3 className="dash-card__title">Zonas más buscadas</h3>
      <ol className="dash-rank">
        {zones.map((z, i) => (
          <li key={z.zone} className="dash-rank__row">
            <span className="dash-rank__name">{i + 1}. {z.zone}</span>
            <span className="dash-rank__val">{z.count.toLocaleString("es-AR")}</span>
          </li>
        ))}
      </ol>
      <button className="dash-link" onClick={onMore}>Ver todas las zonas <Icon name="arrow" size={15} /></button>
    </div>
  );
}

// ============ PANEL: CONSULTAS NO RESUELTAS ============
function UnresolvedConsultationsCard({ items, onMore }) {
  return (
    <div className="dash-card dash-list-card">
      <h3 className="dash-card__title">Consultas no resueltas</h3>
      <ol className="dash-rank">
        {items.map((it, i) => (
          <li key={it.reason} className="dash-rank__row">
            <span className="dash-rank__name">{i + 1}. {it.reason}</span>
            <span className="dash-rank__val dash-rank__val--muted">{it.pct}%</span>
          </li>
        ))}
      </ol>
      <button className="dash-link" onClick={onMore}>Ver detalle <Icon name="arrow" size={15} /></button>
    </div>
  );
}

// ============ MODAL GENÉRICO ============
function Modal({ title, onClose, children }) {
  uE(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, []);
  return (
    <div className="dash-modal" role="dialog" aria-modal="true">
      <div className="dash-modal__scrim" onClick={onClose}></div>
      <div className="dash-modal__box">
        <header className="dash-modal__head">
          <h3>{title}</h3>
          <button className="dash-iconbtn" onClick={onClose} aria-label="Cerrar"><Icon name="close" /></button>
        </header>
        <div className="dash-modal__body">{children}</div>
      </div>
    </div>
  );
}

// ============ AVISO "PRÓXIMAMENTE" (toast discreto) ============
function ComingSoonNotice({ msg }) {
  if (!msg) return null;
  return <div className="dash-toast" role="status">{msg}</div>;
}

// ============ ENCABEZADO ============
function DashboardHeader({ filters, setFilters, onLogout, onMenu, onAccount, onRefresh, loading, lastUpdated, env, setEnv, showEnvSwitch }) {
  return (
    <header className="dash-head">
      <div className="dash-head__left">
        <button className="dash-iconbtn dash-head__menu" onClick={onMenu} aria-label="Abrir menú"><Icon name="menu" /></button>
        <div className="dash-head__heading">
          <h1 className="dash-head__title">Dashboard</h1>
        </div>
      </div>
      <div className="dash-head__right">
        <DashboardFilters filters={filters} setFilters={setFilters} env={env} setEnv={setEnv} showEnvSwitch={showEnvSwitch} />
        <RefreshControl onRefresh={onRefresh} loading={loading} lastUpdated={lastUpdated} />
        <Dropdown
          align="right"
          className="dash-profile"
          button={(open, toggle) => (
            <button className="dash-avatar" onClick={toggle} aria-label="Perfil"><Icon name="user" size={18} /></button>
          )}>
          <button className="dd__opt" onClick={onAccount}>Mi cuenta</button>
          <button className="dd__opt" onClick={onLogout}>Cerrar sesión</button>
        </Dropdown>
      </div>
    </header>
  );
}

// ============ HOOK: toast "próximamente" reutilizable ============
function useToast() {
  const [toast, setToast] = uS("");
  const show = (msg) => {
    setToast(msg);
    window.clearTimeout(show._t);
    show._t = window.setTimeout(() => setToast(""), 2600);
  };
  return [toast, show];
}
const COMING_SOON = "Esta sección estará disponible próximamente.";

// ============ PANTALLA INICIO ============
function DashboardHomePage({ user, onLogout, env, setEnv, showEnvSwitch }) {
  const [filters, setFilters] = uS({ period: "30d", channel: "all", compare: false });
  const [selected, setSelected] = uS(null);
  const [modal, setModal] = uS(null); // 'zones' | 'unresolved'
  const [sbOpen, setSbOpen] = uS(false);
  const [toast, showToast] = useToast();

  // Datos del dashboard: mock para cuentas demo, backend en vivo para cuentas
  // con datos en Supabase (p.ej. "deleo"). Misma forma en ambos casos.
  const data = useDashboardData(user, filters, env);
  const { metrics, series, results, channels, rows, zones, unresolved } = data;
  // Clave que cambia con cada actualización/filtro para reanimar la entrada de tarjetas.
  const animKey = `${filters.period}-${filters.channel}-${data.lastUpdated ? data.lastUpdated.getTime() : 0}`;

  // "Ir a la conversación": guarda qué chat abrir y navega al Inbox de ese canal
  // (mismo mecanismo que usa el Tablero — ver mirai_setPendingChat en dashboard-inbox.jsx).
  const goToChat = (row) => {
    mirai_setPendingChat(row.channel, row.detail.contact);
    window.location.hash = `#/dashboard/${row.channel}`;
  };

  const copyDiagnosis = async (row) => {
    const summary = row.detail.summary;
    if (!summary) return;
    const text = miraiFormatDiagnosis({
      name: row.name, operator: (row.derivedTo || []).join(", "), phone: row.detail.contact, intent: row.intentRaw || row.intent, summary,
    });
    try { await navigator.clipboard.writeText(text); } catch (e) { /* clipboard no disponible */ }
    showToast("Diagnóstico copiado");
  };

  // "Derivado a": admite varias personas a la vez. Optimista siempre; en
  // cuentas en vivo además lo guarda en Supabase (mismo endpoint que usa el
  // Tablero) — si falla, se revierte.
  const assignDerivedTo = async (row, derivedToList) => {
    const prev = row.derivedTo;
    setSelected((r) => (r && r.id === row.id ? { ...r, derivedTo: derivedToList } : r));
    const label = derivedToList.length ? `Derivado a ${derivedToList.join(", ")}` : "Derivado desasignado";
    if (!data.isLive) {
      showToast(label);
      return;
    }
    try {
      await mirai_assignDerivedTo(row.detail.contact, derivedToList, env);
      showToast(label);
    } catch (e) {
      setSelected((r) => (r && r.id === row.id ? { ...r, derivedTo: prev } : r));
      showToast("No se pudo guardar la asignación.");
    }
  };

  return (
    <div className="dboard">
      <DashboardSidebar active="inicio" user={user} onComingSoon={() => showToast(COMING_SOON)} open={sbOpen} onClose={() => setSbOpen(false)} />

      <div className="dash-main">
        <DashboardHeader
          filters={filters} setFilters={setFilters}
          onLogout={onLogout}
          onMenu={() => setSbOpen(true)}
          onAccount={() => showToast(COMING_SOON)}
          onRefresh={data.refresh} loading={data.loading} lastUpdated={data.lastUpdated}
          env={env} setEnv={setEnv} showEnvSwitch={showEnvSwitch} />

        {/* Fila 1 — métricas */}
        <div className={`dash-metrics dash-fade ${data.loading ? "is-updating" : ""}`} key={animKey}>
          {metrics.map((m) => <MetricCard key={m.label} m={m} />)}
        </div>

        {/* Fila 2 — gráficos */}
        <div className={`dash-charts dash-fade ${data.loading ? "is-updating" : ""}`} key={"c-" + animKey}>
          <div className="dash-card dash-card--chart">
            <h3 className="dash-card__title">Evolución de consultas y leads</h3>
            <div className="dash-legend">
              <span className="dash-legend__item"><span className="dot dot--dark"></span>Consultas</span>
              <span className="dash-legend__item"><span className="dot dot--gray"></span>Leads</span>
            </div>
            <ConsultationsLineChart data={series} />
          </div>

          <ConsultationResultsCard data={results} />

          <div className="dash-card">
            <h3 className="dash-card__title">Canales</h3>
            <ChannelBreakdown channels={channels} />
          </div>
        </div>

        {/* Fila 3 — tabla + paneles */}
        <div className={`dash-bottom dash-fade ${data.loading ? "is-updating" : ""}`} key={"b-" + animKey}>
          <div className="dash-card dash-card--table">
            <h3 className="dash-card__title">Últimas consultas</h3>
            <RecentConsultationsTable rows={rows} onSelect={setSelected} />
          </div>
          <TopZonesCard zones={zones} onMore={() => setModal("zones")} />
          <UnresolvedConsultationsCard items={unresolved} onMore={() => setModal("unresolved")} />
        </div>
      </div>

      {selected && (
        <ConsultationDetailDrawer
          row={selected} onClose={() => setSelected(null)}
          onGoToChat={goToChat} onCopyDiagnosis={copyDiagnosis} onAssign={assignDerivedTo} />
      )}

      {modal === "zones" && (
        <Modal title="Zonas más buscadas" onClose={() => setModal(null)}>
          <ul className="dash-rank dash-rank--full">
            {data.zonesFull.map((z, i) => (
              <li key={z.zone} className="dash-rank__row">
                <span className="dash-rank__name">{i + 1}. {z.zone}</span>
                <span className="dash-rank__val">{z.count.toLocaleString("es-AR")}</span>
              </li>
            ))}
          </ul>
        </Modal>
      )}

      {modal === "unresolved" && (
        <Modal title="Consultas no resueltas — detalle" onClose={() => setModal(null)}>
          <table className="dash-modal-table">
            <thead><tr><th>Motivo</th><th>Incidencia</th><th>Descripción</th></tr></thead>
            <tbody>
              {data.unresolvedFull.map((it) => (
                <tr key={it.reason}>
                  <td>{it.reason}</td>
                  <td className="dash-modal-table__pct">{it.pct}%</td>
                  <td className="dash-modal-table__desc">{it.desc}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </Modal>
      )}

      <ComingSoonNotice msg={toast} />
    </div>
  );
}

// ============ INTENCIONES MÁS FRECUENTES (barras horizontales) ============
const BAR_SHADES = ["#000000", "#3d3d3d", "#6b6b6b", "#9a9a9a", "#c9c9c9"];
function TopIntentionsCard({ items }) {
  return (
    <div className="dash-card">
      <h3 className="dash-card__title">Intenciones más frecuentes</h3>
      <ol className="dash-intents">
        {items.map((it, i) => (
          <li key={it[0]} className="dash-intents__row">
            <span className="dash-intents__rank">{i + 1}.</span>
            <span className="dash-intents__label">{it[0]}</span>
            <span className="dash-intents__bar">
              <span className="dash-intents__fill" style={{ width: `${it[1]}%`, background: BAR_SHADES[i] }}></span>
            </span>
            <span className="dash-intents__pct">{it[1]}%</span>
          </li>
        ))}
      </ol>
    </div>
  );
}

// ============ PANEL "MÁS INFORMACIÓN" (colapsable) ============
function MoreInformationPanel({ cfg }) {
  const [open, setOpen] = uS(false);
  const strip = cfg.gradient || cfg.accent;
  return (
    <div className={`dash-more ${open ? "is-open" : ""}`}>
      <button className="dash-more__head" onClick={() => setOpen((v) => !v)} aria-expanded={open}>
        <span className="dash-more__strip" style={{ background: strip }}></span>
        <span className="dash-more__icon" style={{ background: cfg.accentSoft, color: cfg.accent }}><Icon name="trend" size={20} /></span>
        <span className="dash-more__text">
          <span className="dash-more__title">Más información</span>
          <span className="dash-more__sub">Ver últimas consultas, horarios de mayor demanda y más detalles</span>
        </span>
        <span className="dash-more__arrow" style={{ color: cfg.accent }}><Icon name="arrow" size={22} /></span>
      </button>
      <div className="dash-more__wrap">
        <div className="dash-more__inner">
          <div className="dash-more__grid">
            <section className="dash-more__sec">
              <h4 className="dash-more__sectitle">Últimas consultas</h4>
              <ul className="dash-more__list">
                {cfg.recent.map((r, i) => (
                  <li key={i} className="dash-more__consult">
                    <span className="dash-more__cname">{r.name}</span>
                    <span className="dash-more__cmeta">{r.intent} · {r.zone}</span>
                    <StatusPill status={r.status} />
                    <span className="dash-more__ctime">{r.time}</span>
                  </li>
                ))}
              </ul>
            </section>

            <section className="dash-more__sec">
              <h4 className="dash-more__sectitle">Horarios con mayor demanda</h4>
              <ul className="dash-peak">
                {cfg.peakHours.map((h) => (
                  <li key={h[0]} className="dash-peak__row">
                    <span className="dash-peak__label">{h[0]}</span>
                    <span className="dash-peak__bar"><span className="dash-peak__fill" style={{ width: `${h[1]}%`, background: cfg.accent }}></span></span>
                  </li>
                ))}
              </ul>
            </section>

            <section className="dash-more__sec">
              <h4 className="dash-more__sectitle">Zonas más consultadas</h4>
              <ol className="dash-rank">
                {cfg.zones.map((z, i) => (
                  <li key={z[0]} className="dash-rank__row">
                    <span className="dash-rank__name">{i + 1}. {z[0]}</span>
                    <span className="dash-rank__val">{z[1].toLocaleString("es-AR")}</span>
                  </li>
                ))}
              </ol>
            </section>

            <section className="dash-more__sec">
              <h4 className="dash-more__sectitle">Consultas no resueltas</h4>
              <ol className="dash-rank">
                {cfg.unresolved.map((u, i) => (
                  <li key={u[0]} className="dash-rank__row">
                    <span className="dash-rank__name">{i + 1}. {u[0]}</span>
                    <span className="dash-rank__val dash-rank__val--muted">{u[1]}%</span>
                  </li>
                ))}
              </ol>
            </section>
          </div>
        </div>
      </div>
    </div>
  );
}

// ============ HEADER DE CANAL ============
function ChannelDashboardHeader({ cfg, filters, setFilters, onLogout, onMenu, onAccount, onRefresh, loading, lastUpdated, env, setEnv, showEnvSwitch }) {
  return (
    <header className="dash-head">
      <div className="dash-head__left">
        <button className="dash-iconbtn dash-head__menu" onClick={onMenu} aria-label="Abrir menú"><Icon name="menu" /></button>
        <div className="dash-head__heading">
          <div className="dash-head__titlerow">
            <span className="dash-head__channel-icon">
              {cfg.key === "instagram" ? <InstagramIcon size={36} />
                : cfg.key === "crm" ? (
                  <span className="dash-head__crm-ico" style={{ background: "#C0003B" }}>
                    <Icon name="user" size={20} />
                  </span>
                ) : <WhatsAppIcon size={36} />}
            </span>
            <h1 className="dash-head__title">{cfg.name}</h1>
          </div>
        </div>
      </div>
      <div className="dash-head__right">
        {showEnvSwitch && <EnvSwitch env={env} setEnv={setEnv} />}
        <RefreshControl onRefresh={onRefresh} loading={loading} lastUpdated={lastUpdated} />
        <Dropdown
          align="right"
          className="dash-profile"
          button={(open, toggle) => (
            <button className="dash-avatar" onClick={toggle} aria-label="Perfil"><Icon name="user" size={18} /></button>
          )}>
          <button className="dd__opt" onClick={onAccount}>Mi cuenta</button>
          <button className="dd__opt" onClick={onLogout}>Cerrar sesión</button>
        </Dropdown>
      </div>
    </header>
  );
}

// ============ EMPTY STATE (canal sin datos) ============
function ChannelEmptyState({ cfg }) {
  return (
    <div className="dash-empty">
      <span className="dash-empty__icon" style={{ background: cfg.accentSoft, color: cfg.accent }}>
        <Icon name="inbox" size={28} />
      </span>
      <p className="dash-empty__text">Todavía no hay datos disponibles para este canal.</p>
    </div>
  );
}

// ============ PÁGINA DE CANAL (WhatsApp / Instagram) ============
function ChannelDashboardPage({ channel, user, onLogout }) {
  const cfg = dashGetChannelCfg(channel);
  const [filters, setFilters] = uS({ period: "30d", channel, compare: false });
  const [sbOpen, setSbOpen] = uS(false);
  const [toast, showToast] = useToast();

  // Datos reales (deleo) o mock (cuentas demo). El filtro de canal va al backend.
  const data = useDashboardData(user, { period: filters.period, channel, compare: filters.compare });

  // Fuente de datos según cuenta. Para datos reales mantenemos la identidad
  // visual del canal (cfg) pero los datos vienen del backend.
  const isLive = data.isLive;
  const metrics = isLive ? data.metrics : dashGetChannelMetrics(channel, filters);
  const series = isLive ? data.series : dashGetChannelSeries(channel, filters);
  const results = isLive ? data.results : dashGetChannelResults(channel);
  const intentions = isLive ? data.intentions : cfg.intentions;
  const panelCfg = isLive
    ? {
        ...cfg,
        recent: data.recent,
        peakHours: data.peakHours,
        zones: (data.zones || []).map((z) => [z.zone, z.count]),
        unresolved: (data.unresolved || []).map((u) => [u.reason, u.pct]),
      }
    : cfg;
  const showEmpty = isLive && data.empty;
  const animKey = `${channel}-${filters.period}-${data.lastUpdated ? data.lastUpdated.getTime() : 0}`;

  return (
    <div className="dboard">
      <DashboardSidebar active={channel} user={user} onComingSoon={() => showToast(COMING_SOON)} open={sbOpen} onClose={() => setSbOpen(false)} />

      <div className="dash-main">
        <ChannelDashboardHeader
          cfg={cfg} filters={filters} setFilters={setFilters}
          onLogout={onLogout} onMenu={() => setSbOpen(true)} onAccount={() => showToast(COMING_SOON)}
          onRefresh={data.refresh} loading={data.loading} lastUpdated={data.lastUpdated} />

        <div className={`dash-metrics dash-metrics--6 dash-cmetrics is-${channel} dash-fade ${data.loading ? "is-updating" : ""}`} key={"m-" + animKey}>
          {metrics.map((m) => <MetricCard key={m.label} m={m} />)}
        </div>

        {showEmpty ? (
          <ChannelEmptyState cfg={cfg} />
        ) : (
          <>
            <div className={`dash-charts dash-fade ${data.loading ? "is-updating" : ""}`} key={"c-" + animKey}>
              <div className="dash-card dash-card--chart">
                <h3 className="dash-card__title">Evolución de consultas de {cfg.name}</h3>
                <div className="dash-legend">
                  <span className="dash-legend__item"><span className="dot dot--dark"></span>Consultas</span>
                  <span className="dash-legend__item"><span className="dot dot--gray"></span>Leads calificados</span>
                </div>
                <ConsultationsLineChart data={series} />
              </div>

              <div className="dash-card">
                <h3 className="dash-card__title">Estado de las consultas</h3>
                <div className="dash-results">
                  <ConsultationResultsChart data={results} />
                  <ul className="dash-results__legend">
                    {results.map((seg) => (
                      <li key={seg.label}>
                        <span className="dash-results__dot" style={{ background: seg.color }}></span>
                        <span className="dash-results__name">{seg.label}</span>
                        <span className="dash-results__pct">{seg.value}%</span>
                      </li>
                    ))}
                  </ul>
                </div>
              </div>

              <TopIntentionsCard items={intentions} />
            </div>

            <MoreInformationPanel cfg={panelCfg} />
          </>
        )}
      </div>

      <ComingSoonNotice msg={toast} />
    </div>
  );
}

// ============ DARK MODE (preferencia persistida en el navegador) ============
const MIRAI_DARK_KEY = "mirai_dark";
function miraiReadDark() {
  try { return localStorage.getItem(MIRAI_DARK_KEY) === "1"; } catch (e) { return false; }
}
function miraiApplyDark(on) {
  const el = document.documentElement;
  if (on) el.classList.add("mirai-dark"); else el.classList.remove("mirai-dark");
}
function useDarkMode() {
  const [dark, setDark] = uS(miraiReadDark);
  uE(() => {
    miraiApplyDark(dark);
    try { localStorage.setItem(MIRAI_DARK_KEY, dark ? "1" : "0"); } catch (e) {}
  }, [dark]);
  // Al desmontar el dashboard volvemos al tema claro (la landing es siempre clara).
  uE(() => () => miraiApplyDark(false), []);
  return [dark, setDark];
}

// ============ CANALES ACTIVOS (preferencia por usuario, persistida) ============
// Se guarda por usuario en el navegador (igual que la preferencia de Dark Mode),
// de modo que cada cuenta conserva su propia configuración tras cerrar sesión o
// recargar. NO toca datos ni la conexión con Google Sheets: es solo visual/acceso.
const miraiChKey = (user) => `mirai_channels_${(user || "").toLowerCase()}`;
const CH_FIELDS = {
  whatsapp: "whatsappEnabled", instagram: "instagramEnabled",
  crm: "crmEnabled", rastreo: "rastreoEnabled", tickets: "ticketsEnabled",
};
function miraiReadChannels(user) {
  try {
    const raw = JSON.parse(localStorage.getItem(miraiChKey(user)) || "null") || {};
    return {
      whatsappEnabled:  raw.whatsappEnabled  !== false,
      instagramEnabled: raw.instagramEnabled !== false,
      crmEnabled:       raw.crmEnabled       !== false,
      rastreoEnabled:   raw.rastreoEnabled   !== false,
      ticketsEnabled:   raw.ticketsEnabled   !== false,
    };
  } catch (e) {
    return { whatsappEnabled: true, instagramEnabled: true, crmEnabled: true, rastreoEnabled: true, ticketsEnabled: true };
  }
}
function useChannelPrefs(user) {
  const [prefs, setPrefs] = uS(() => miraiReadChannels(user));
  uE(() => { setPrefs(miraiReadChannels(user)); }, [user]);
  uE(() => {
    const onChange = () => setPrefs(miraiReadChannels(user));
    window.addEventListener("mirai-channels-changed", onChange);
    window.addEventListener("storage", onChange);
    return () => {
      window.removeEventListener("mirai-channels-changed", onChange);
      window.removeEventListener("storage", onChange);
    };
  }, [user]);
  const setChannel = (key, enabled) => {
    const cur = miraiReadChannels(user);
    const field = CH_FIELDS[key] || "whatsappEnabled";
    const next = { ...cur, [field]: enabled };
    try { localStorage.setItem(miraiChKey(user), JSON.stringify(next)); } catch (e) {}
    setPrefs(next);
    window.dispatchEvent(new Event("mirai-channels-changed"));
  };
  return [prefs, setChannel];
}

// ============ PÁGINA DE CONFIGURACIÓN ============
const MIRAI_ADMIN_WA = "5491128661164"; // +54 9 11 2866 1164

function ConfigurationPage({ user, onLogout, dark, setDark, env, setEnv, showEnvSwitch }) {
  const [sbOpen, setSbOpen] = uS(false);
  const [toast, showToast] = useToast();
  const [chPrefs, setChannel] = useChannelPrefs(user);
  const waLink = `https://wa.me/${MIRAI_ADMIN_WA}?text=${encodeURIComponent("Hola, quiero cambiar mi usuario o contraseña del dashboard de MirAI.")}`;

  return (
    <div className="dboard">
      <DashboardSidebar active="configuracion" user={user} onComingSoon={() => showToast(COMING_SOON)} open={sbOpen} onClose={() => setSbOpen(false)} />

      <div className="dash-main">
        <header className="dash-head">
          <div className="dash-head__left">
            <button className="dash-iconbtn dash-head__menu" onClick={() => setSbOpen(true)} aria-label="Abrir menú"><Icon name="menu" /></button>
            <div className="dash-head__heading">
              <h1 className="dash-head__title">Configuración</h1>
              <p className="dash-head__sub">Preferencias de tu cuenta</p>
            </div>
          </div>
          <div className="dash-head__right">
            <Dropdown
              align="right"
              className="dash-profile"
              button={(open, toggle) => (
                <button className="dash-avatar" onClick={toggle} aria-label="Perfil"><Icon name="user" size={18} /></button>
              )}>
              <button className="dd__opt" onClick={onLogout}>Cerrar sesión</button>
            </Dropdown>
          </div>
        </header>

        <div className="dash-config dash-fade is-in">
          {/* Cuenta */}
          <section className="dash-card dash-config__card">
            <h3 className="dash-card__title">Cuenta</h3>
            <div className="dash-config__row">
              <div className="dash-config__info">
                <span className="dash-config__label">Usuario</span>
                <span className="dash-config__value">{user}</span>
              </div>
            </div>
            <div className="dash-config__row">
              <div className="dash-config__info">
                <span className="dash-config__label">Usuario y contraseña</span>
                <span className="dash-config__hint">
                  Por seguridad, el cambio de usuario o contraseña lo realiza un administrador.
                </span>
              </div>
              <a className="btn btn--primary dash-config__wa" href={waLink} target="_blank" rel="noopener noreferrer">
                <WhatsAppIcon size={18} color="#fff" /> Contactar a un administrador
              </a>
            </div>
          </section>

          {/* Apariencia */}
          <section className="dash-card dash-config__card">
            <h3 className="dash-card__title">Apariencia</h3>
            <div className="dash-config__row">
              <div className="dash-config__info">
                <span className="dash-config__label">Modo oscuro</span>
                <span className="dash-config__hint">Cambia el tema del dashboard. La preferencia se guarda en este dispositivo.</span>
              </div>
              <button
                role="switch"
                aria-checked={dark}
                className={`dash-switch ${dark ? "is-on" : ""}`}
                onClick={() => setDark((v) => !v)}>
                <span className="dash-switch__knob"></span>
              </button>
            </div>
          </section>

          {/* Canales activos */}
          <section className="dash-card dash-config__card">
            <h3 className="dash-card__title">Canales activos</h3>

            <div className="dash-config__row">
              <div className="dash-config__info">
                <span className="dash-config__label dash-config__label--icon">
                  <WhatsAppIcon size={16} color="#25D366" /> WhatsApp
                </span>
                <span className="dash-config__hint">Activar o desactivar canal</span>
              </div>
              <button role="switch" aria-checked={chPrefs.whatsappEnabled}
                className={`dash-switch dash-switch--wa ${chPrefs.whatsappEnabled ? "is-on" : ""}`}
                onClick={() => setChannel("whatsapp", !chPrefs.whatsappEnabled)}>
                <span className="dash-switch__knob"></span>
              </button>
            </div>

            <div className="dash-config__row">
              <div className="dash-config__info">
                <span className="dash-config__label dash-config__label--icon">
                  <InstagramIcon size={16} /> Instagram
                </span>
                <span className="dash-config__hint">Activar o desactivar canal</span>
              </div>
              <button role="switch" aria-checked={chPrefs.instagramEnabled}
                className={`dash-switch dash-switch--ig ${chPrefs.instagramEnabled ? "is-on" : ""}`}
                onClick={() => setChannel("instagram", !chPrefs.instagramEnabled)}>
                <span className="dash-switch__knob"></span>
              </button>
            </div>

            <div className="dash-config__row">
              <div className="dash-config__info">
                <span className="dash-config__label dash-config__label--icon">
                  <span className="dash-config__ch-dot" style={{ background: "#C0003B" }}></span> CRM
                </span>
                <span className="dash-config__hint">Activar o desactivar canal</span>
              </div>
              <button role="switch" aria-checked={chPrefs.crmEnabled}
                className={`dash-switch dash-switch--crm ${chPrefs.crmEnabled ? "is-on" : ""}`}
                onClick={() => setChannel("crm", !chPrefs.crmEnabled)}>
                <span className="dash-switch__knob"></span>
              </button>
            </div>

            <div className="dash-config__row">
              <div className="dash-config__info">
                <span className="dash-config__label dash-config__label--icon">
                  <span className="dash-config__ch-dot" style={{ background: "#1E90FF" }}></span> Rastreo
                </span>
                <span className="dash-config__hint">Activar o desactivar canal</span>
              </div>
              <button role="switch" aria-checked={chPrefs.rastreoEnabled}
                className={`dash-switch dash-switch--rastreo ${chPrefs.rastreoEnabled ? "is-on" : ""}`}
                onClick={() => setChannel("rastreo", !chPrefs.rastreoEnabled)}>
                <span className="dash-switch__knob"></span>
              </button>
            </div>

            <div className="dash-config__row">
              <div className="dash-config__info">
                <span className="dash-config__label dash-config__label--icon">
                  <span className="dash-config__ch-dot" style={{ background: "#1F3A5C" }}></span> Tickets
                </span>
                <span className="dash-config__hint">Activar o desactivar canal</span>
              </div>
              <button role="switch" aria-checked={chPrefs.ticketsEnabled}
                className={`dash-switch dash-switch--tickets ${chPrefs.ticketsEnabled ? "is-on" : ""}`}
                onClick={() => setChannel("tickets", !chPrefs.ticketsEnabled)}>
                <span className="dash-switch__knob"></span>
              </button>
            </div>

          </section>
        </div>
      </div>

      <ComingSoonNotice msg={toast} />
    </div>
  );
}

// ============ ROUTER DEL DASHBOARD ============
function DashboardApp({ user, onLogout }) {
  const route = useRoute();
  const [dark, setDark] = useDarkMode();
  const [chPrefs] = useChannelPrefs(user);
  const { env, setEnv, showEnvSwitch } = useMiraiEnv(user);
  const envProps = { env, setEnv, showEnvSwitch };

  // Guard: si el canal está desactivado, redirigir a /dashboard (sin borrar datos).
  const blocked =
    (route === "/dashboard/whatsapp"  && !chPrefs.whatsappEnabled)  ||
    (route === "/dashboard/instagram" && !chPrefs.instagramEnabled) ||
    (route === "/dashboard/crm"       && !chPrefs.crmEnabled)       ||
    (route === "/dashboard/rastreo"   && !chPrefs.rastreoEnabled)   ||
    (route === "/dashboard/tickets"   && !chPrefs.ticketsEnabled);
  uE(() => {
    if (blocked && window.location.hash !== "#/dashboard") {
      window.location.hash = "#/dashboard";
    }
  }, [blocked]);

  if (!blocked && route === "/dashboard/whatsapp") return <ChannelInboxPage key="whatsapp" channel="whatsapp" user={user} onLogout={onLogout} {...envProps} />;
  if (!blocked && route === "/dashboard/instagram") return <ChannelInboxPage key="instagram" channel="instagram" user={user} onLogout={onLogout} {...envProps} />;
  if (route === "/dashboard/crm") return <ChannelInboxPage key="crm" channel="crm" user={user} onLogout={onLogout} {...envProps} />;
  if (route === "/dashboard/tablero") return <TableroPage user={user} onLogout={onLogout} {...envProps} />;
  if (route === "/dashboard/rastreo") return <RastreoPage user={user} onLogout={onLogout} {...envProps} />;
  if (route === "/dashboard/tickets") return <TicketsPage user={user} onLogout={onLogout} {...envProps} />;
  if (route === "/dashboard/configuracion") return <ConfigurationPage user={user} onLogout={onLogout} dark={dark} setDark={setDark} {...envProps} />;
  return <DashboardHomePage user={user} onLogout={onLogout} {...envProps} />;
}

Object.assign(window, { DashboardApp });
