/* ELC Dashboard — shared SVG charts and small helpers
   All components read from window.DATA; no external libs.
*/
const { useState, useEffect, useRef, useMemo } = React;

// ── helpers ────────────────────────────────────
const fmt = (n) => (n == null ? "—" : n.toLocaleString("en-US"));
const fmtThb = (n) => "฿" + Math.round(n / 100) * 100 === n ? "฿" + n.toLocaleString("en-US") : "฿" + Math.round(n).toLocaleString("en-US");
const fmtK = (n) => (n == null ? "—" : n >= 1000 ? (n / 1000).toFixed(n % 1000 === 0 ? 0 : 1) + "k" : String(n));
const delta = (v) => {
  if (v == null) return null;
  const cls = v > 0 ? "pos" : v < 0 ? "neg" : "neu";
  const arrow = v > 0 ? "▲" : v < 0 ? "▼" : "•";
  return <span className={`delta ${cls}`}>{arrow} {Math.abs(v)}%</span>;
};

function Sparkline({ data, accent = "purple", height = 34 }) {
  const pts = data;
  if (!pts || !pts.length) return null;
  const w = 120, h = height, pad = 2;
  const xs = pts.map((_, i) => pad + (i * (w - pad * 2)) / (pts.length - 1));
  const vals = pts.map((d) => d.v ?? d.value ?? d);
  const lo = Math.min(...vals), hi = Math.max(...vals);
  const ys = vals.map((v) => h - pad - ((v - lo) / (hi - lo || 1)) * (h - pad * 2));
  const line = xs.map((x, i) => `${i ? "L" : "M"}${x.toFixed(1)},${ys[i].toFixed(1)}`).join(" ");
  const area = line + ` L${xs[xs.length - 1].toFixed(1)},${h} L${xs[0].toFixed(1)},${h} Z`;
  return (
    <svg className={`spark ${accent === "gold" ? "gold" : ""}`} viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none">
      <path className="area" d={area} />
      <path className="line" d={line} />
    </svg>
  );
}

// ── line chart (trend, up to 3 overlays) ──────
function LineChart({ series, labels, height = 240, yFmt = (v) => v, color, showDots = true }) {
  const w = 780, h = height, pad = { t: 20, r: 20, b: 34, l: 48 };
  const innerW = w - pad.l - pad.r, innerH = h - pad.t - pad.b;
  const all = series.flatMap((s) => s.data.filter((v) => v != null));
  const lo = 0, hi = Math.max(...all) * 1.08;
  const xAt = (i) => pad.l + (i * innerW) / (labels.length - 1);
  const yAt = (v) => pad.t + innerH - ((v - lo) / (hi - lo || 1)) * innerH;
  const ticks = 4;
  const yTicks = Array.from({ length: ticks + 1 }, (_, i) => lo + (i * (hi - lo)) / ticks);

  return (
    <svg className="chart" viewBox={`0 0 ${w} ${h}`}>
      {yTicks.map((t, i) => (
        <g key={i}>
          <line x1={pad.l} x2={w - pad.r} y1={yAt(t)} y2={yAt(t)} stroke="#EFEEE9" strokeWidth="1" />
          <text x={pad.l - 8} y={yAt(t) + 3} fontSize="10.5" fill="#9a9a9d" textAnchor="end">{yFmt(Math.round(t))}</text>
        </g>
      ))}
      {labels.map((l, i) => (
        <text key={i} x={xAt(i)} y={h - 12} fontSize="10.5" fill="#9a9a9d" textAnchor="middle">{l}</text>
      ))}
      {series.map((s, si) => {
        const pts = s.data.map((v, i) => (v == null ? null : [xAt(i), yAt(v)]));
        const segs = [];
        let cur = [];
        pts.forEach((p) => {
          if (p) cur.push(p);
          else { if (cur.length) segs.push(cur); cur = []; }
        });
        if (cur.length) segs.push(cur);
        return (
          <g key={si}>
            {segs.map((seg, idx) => (
              <path key={idx} d={seg.map((p, i) => `${i ? "L" : "M"}${p[0].toFixed(1)},${p[1].toFixed(1)}`).join(" ")}
                fill="none" stroke={s.color} strokeWidth={s.width || 2} strokeDasharray={s.dash || "0"} strokeLinecap="round" strokeLinejoin="round" />
            ))}
            {showDots && pts.map((p, i) => p && (
              <circle key={i} cx={p[0]} cy={p[1]} r={s.dotR || 3} fill={s.color} stroke="#fff" strokeWidth="1.5" />
            ))}
          </g>
        );
      })}
    </svg>
  );
}

// ── stacked bar (monthly, 3 series) ────────────
function StackedBar({ rows, keys, colors, labels, height = 260, yFmt = (v) => v }) {
  const w = 780, h = height, pad = { t: 16, r: 16, b: 30, l: 42 };
  const innerW = w - pad.l - pad.r, innerH = h - pad.t - pad.b;
  const totals = rows.map((r) => keys.reduce((a, k) => a + (r[k] || 0), 0));
  const hi = Math.max(...totals) * 1.12;
  const nBars = rows.length;
  const bw = (innerW / nBars) * 0.66;
  const step = innerW / nBars;
  const xAt = (i) => pad.l + step * i + (step - bw) / 2;
  const yAt = (v) => pad.t + innerH - (v / (hi || 1)) * innerH;

  const ticks = 4;
  const yTicks = Array.from({ length: ticks + 1 }, (_, i) => (i * hi) / ticks);

  return (
    <svg className="chart" viewBox={`0 0 ${w} ${h}`}>
      {yTicks.map((t, i) => (
        <g key={i}>
          <line x1={pad.l} x2={w - pad.r} y1={yAt(t)} y2={yAt(t)} stroke="#EFEEE9" />
          <text x={pad.l - 6} y={yAt(t) + 3} fontSize="10.5" fill="#9a9a9d" textAnchor="end">{yFmt(Math.round(t))}</text>
        </g>
      ))}
      {rows.map((r, i) => {
        let acc = 0;
        return (
          <g key={i}>
            {keys.map((k, ki) => {
              const v = r[k] || 0;
              const y1 = yAt(acc + v), y2 = yAt(acc);
              acc += v;
              return <rect key={k} x={xAt(i)} y={y1} width={bw} height={Math.max(0, y2 - y1)} fill={colors[ki]} rx="1.5" />;
            })}
            <text x={xAt(i) + bw / 2} y={h - 10} fontSize="10.5" fill="#9a9a9d" textAnchor="middle">{labels[i]}</text>
            <text x={xAt(i) + bw / 2} y={yAt(totals[i]) - 5} fontSize="10.5" fill="#6b6b6f" textAnchor="middle" fontWeight="600">{totals[i]}</text>
          </g>
        );
      })}
    </svg>
  );
}

// ── grouped horizontal bars (year-level forced vs unforced) ──
function HBarStack({ rows, keys, colors, labels, height = 240 }) {
  const w = 780, h = height, pad = { t: 10, r: 100, b: 18, l: 60 };
  const innerW = w - pad.l - pad.r, innerH = h - pad.t - pad.b;
  const totals = rows.map((r) => keys.reduce((a, k) => a + (r[k] || 0), 0));
  const hi = Math.max(...totals) * 1.05 || 1;
  const bh = (innerH / rows.length) * 0.62;
  const step = innerH / rows.length;
  return (
    <svg className="chart" viewBox={`0 0 ${w} ${h}`}>
      {rows.map((r, i) => {
        const y = pad.t + step * i + (step - bh) / 2;
        let acc = 0;
        const total = totals[i];
        return (
          <g key={i}>
            <text x={pad.l - 8} y={y + bh / 2 + 4} fontSize="11.5" fill="#39393B" textAnchor="end" fontWeight="600">{labels[i]}</text>
            {keys.map((k, ki) => {
              const v = r[k] || 0;
              const x = pad.l + (acc / hi) * innerW;
              const wSeg = (v / hi) * innerW;
              acc += v;
              return <rect key={k} x={x} y={y} width={wSeg} height={bh} fill={colors[ki]} rx="1.5" />;
            })}
            <text x={pad.l + (total / hi) * innerW + 8} y={y + bh / 2 + 4} fontSize="11" fill="#6b6b6f" fontWeight="600">{total}</text>
          </g>
        );
      })}
    </svg>
  );
}

// ── dual trend line (CPL + CPQL) ──────────────
function DualLine({ labels, a, b, aLabel, bLabel, aColor, bColor, height = 220 }) {
  return <LineChart
    labels={labels}
    series={[{ data: a, color: aColor, width: 2 }, { data: b, color: bColor, width: 2 }]}
    height={height}
    yFmt={(v) => "฿" + (v / 1000).toFixed(1) + "k"}
  />;
}

// ── horizontal bar ────────────────────────────
function HBar({ value, max, color = "var(--purple)" }) {
  const pct = Math.max(0, Math.min(100, (value / max) * 100));
  return (
    <div className="b-track">
      <span className="b-fill-app" style={{ width: pct + "%", background: color }} />
    </div>
  );
}

Object.assign(window, { fmt, fmtK, delta, Sparkline, LineChart, StackedBar, HBarStack, DualLine, HBar });
