// Cash Flow & Insights — chart components (pure SVG, no library).
// All charts respect the Revenued tokens via inline color refs.

const { useMemo: useChartMemo, useState: useChartState } = React;

// ── Number formatting ─────────────────────────────────────────────────────
function fmtUSD(n, opts) {
  const abs = Math.abs(n);
  const sign = n < 0 ? "−" : "";
  if (opts && opts.short) {
    if (abs >= 1000) return sign + "$" + (abs / 1000).toFixed(abs >= 10000 ? 0 : 1) + "K";
    return sign + "$" + Math.round(abs);
  }
  return sign + "$" + abs.toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 0 });
}

function fmtAmt(n) {
  const sign = n < 0 ? "−" : "+";
  const abs = Math.abs(n);
  return sign + "$" + abs.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}

// ── Sparkline for stat cards ──────────────────────────────────────────────
function Sparkline({ values, color, height = 26, fill }) {
  const w = 96, h = height;
  const min = Math.min(...values), max = Math.max(...values);
  const range = (max - min) || 1;
  const pts = values.map((v, i) => {
    const x = (i / (values.length - 1)) * w;
    const y = h - ((v - min) / range) * (h - 4) - 2;
    return [x, y];
  });
  const d = pts.map((p, i) => (i === 0 ? "M" : "L") + p[0].toFixed(1) + " " + p[1].toFixed(1)).join(" ");
  const area = d + " L " + w + " " + h + " L 0 " + h + " Z";
  return (
    <svg width={w} height={h} className="cf-spark" aria-hidden="true">
      {fill ? <path d={area} fill={fill} /> : null}
      <path d={d} fill="none" stroke={color || "var(--growth-galaxy)"} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

// ── Daily balance area chart (90 days) ────────────────────────────────────
function BalanceChart({ balance, overdraftDays, todayLabel }) {
  const padL = 56, padR = 16, padT = 14, padB = 36;
  const W = 920, H = 280;
  const innerW = W - padL - padR, innerH = H - padT - padB;
  const min = Math.min(0, ...balance);
  const maxRaw = Math.max(...balance);
  const max = Math.ceil(maxRaw / 5000) * 5000;
  const range = (max - min) || 1;

  const x = (i) => padL + (i / (balance.length - 1)) * innerW;
  const y = (v) => padT + (1 - (v - min) / range) * innerH;
  const yZero = y(0);

  const pathD = balance.map((v, i) => (i === 0 ? "M" : "L") + x(i).toFixed(1) + " " + y(v).toFixed(1)).join(" ");
  const areaD = pathD + ` L ${x(balance.length - 1).toFixed(1)} ${yZero.toFixed(1)} L ${x(0).toFixed(1)} ${yZero.toFixed(1)} Z`;

  // Y ticks
  const ticks = [];
  const step = Math.ceil(max / 4 / 5000) * 5000;
  for (let v = 0; v <= max; v += step) ticks.push(v);

  // Month labels (Feb 21 → May 22). Anchor: index 0 = Feb 21, +7 ≈ Feb 28
  const monthStarts = [
    { i: 8,  label: "Mar 1" },
    { i: 39, label: "Apr 1" },
    { i: 69, label: "May 1" },
    { i: 89, label: todayLabel },
  ];

  const [hover, setHover] = useChartState(null);

  const handleMove = (e) => {
    const rect = e.currentTarget.getBoundingClientRect();
    // SVG renders scaled to fit; convert screen px → viewBox units so the
    // indicator sits exactly under the cursor regardless of render width.
    const scaleX = W / rect.width;
    const cx = (e.clientX - rect.left) * scaleX;
    const ratio = (cx - padL) / innerW;
    const idx = Math.max(0, Math.min(balance.length - 1, Math.round(ratio * (balance.length - 1))));
    setHover(idx);
  };

  // Date labels for hover
  function dateForIdx(i) {
    // Day 0 = Feb 21
    const d = new Date(2026, 1, 21);
    d.setDate(d.getDate() + i);
    return d.toLocaleString(undefined, { month: "short", day: "numeric" });
  }

  return (
    <div className="cf-chart-wrap">
      <svg viewBox={`0 0 ${W} ${H}`} className="cf-balance-svg" onMouseMove={handleMove} onMouseLeave={() => setHover(null)} preserveAspectRatio="none">
        <defs>
          <linearGradient id="cf-area" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0" stopColor="var(--funding-pool)" stopOpacity="0.32" />
            <stop offset="1" stopColor="var(--funding-pool)" stopOpacity="0.02" />
          </linearGradient>
          <linearGradient id="cf-line" x1="0" y1="0" x2="1" y2="0">
            <stop offset="0" stopColor="var(--growth-galaxy)" />
            <stop offset="1" stopColor="var(--funding-pool)" />
          </linearGradient>
        </defs>

        {/* Gridlines + Y axis */}
        {ticks.map((t) => (
          <g key={t}>
            <line x1={padL} x2={W - padR} y1={y(t)} y2={y(t)} stroke="var(--border-1)" strokeWidth="1" strokeDasharray={t === 0 ? "0" : "2 4"} />
            <text x={padL - 10} y={y(t) + 4} textAnchor="end" className="cf-axis-label">{fmtUSD(t, { short: true })}</text>
          </g>
        ))}

        {/* Zero line emphasis if negative space exists */}
        {min < 0 ? (
          <line x1={padL} x2={W - padR} y1={yZero} y2={yZero} stroke="var(--color-error)" strokeWidth="1" strokeDasharray="3 3" opacity="0.6" />
        ) : null}

        {/* Area + line */}
        <path d={areaD} fill="url(#cf-area)" />
        <path d={pathD} fill="none" stroke="url(#cf-line)" strokeWidth="2" strokeLinejoin="round" />

        {/* Overdraft dots */}
        {overdraftDays.map((d) => (
          <g key={d}>
            <circle cx={x(d)} cy={yZero} r="6" fill="#fff" stroke="var(--color-error)" strokeWidth="2" />
            <circle cx={x(d)} cy={yZero} r="2.4" fill="var(--color-error)" />
          </g>
        ))}

        {/* Today marker */}
        <g>
          <line x1={x(balance.length - 1)} x2={x(balance.length - 1)} y1={padT} y2={H - padB} stroke="var(--trust-tech)" strokeWidth="1" strokeDasharray="3 3" opacity="0.35" />
        </g>

        {/* X labels */}
        {monthStarts.map((m, i) => (
          <text key={i} x={x(m.i)} y={H - 14} textAnchor={i === monthStarts.length - 1 ? "end" : "start"} className="cf-axis-label">
            {m.label}
          </text>
        ))}

        {/* Hover */}
        {hover !== null ? (
          <g pointerEvents="none">
            <line x1={x(hover)} x2={x(hover)} y1={padT} y2={H - padB} stroke="var(--trust-tech)" strokeWidth="1" opacity="0.4" />
            <circle cx={x(hover)} cy={y(balance[hover])} r="5" fill="#fff" stroke="var(--growth-galaxy)" strokeWidth="2" />
            <g transform={`translate(${Math.min(x(hover) + 12, W - padR - 130)}, ${y(balance[hover]) - 28})`}>
              <rect width="130" height="42" rx="6" fill="var(--trust-tech)" />
              <text x="12" y="17" fill="#fff" className="cf-tooltip-lab">{dateForIdx(hover)}</text>
              <text x="12" y="33" fill="#fff" className="cf-tooltip-val">{fmtUSD(balance[hover])}</text>
            </g>
          </g>
        ) : null}
      </svg>

      <div className="cf-chart-legend">
        <span><span className="dot" style={{ background: "var(--funding-pool)" }} /> Daily ending balance</span>
        <span><span className="dot" style={{ background: "var(--color-error)" }} /> Overdraft / NSF event</span>
        <span style={{ color: "var(--fg-3)", marginLeft: "auto" }}>Hover the line for daily detail</span>
      </div>
    </div>
  );
}

// ── Inflow vs Outflow weekly bars ─────────────────────────────────────────
function FlowBars({ weekly }) {
  const padL = 44, padR = 8, padT = 10, padB = 34;
  const W = 460, H = 230;
  const innerW = W - padL - padR, innerH = H - padT - padB;

  const maxFlow = Math.max(...weekly.map(w => Math.max(w.inflow, w.outflow)));
  const top = Math.ceil(maxFlow / 5000) * 5000;
  const half = innerH / 2;
  const mid = padT + half;

  const barW = innerW / weekly.length * 0.34;
  const gap = innerW / weekly.length;

  // Net line
  const netMax = Math.max(...weekly.map(w => Math.abs(w.net))) || 1;
  const netY = (v) => mid - (v / top) * half * 0.9; // scale net to inflow space
  const netPath = weekly.map((w, i) => {
    const cx = padL + gap * i + gap / 2;
    return (i === 0 ? "M" : "L") + cx + " " + netY(w.net).toFixed(1);
  }).join(" ");

  return (
    <div className="cf-chart-wrap">
      <svg viewBox={`0 0 ${W} ${H}`} className="cf-flow-svg" preserveAspectRatio="none">
        {/* Zero line */}
        <line x1={padL} x2={W - padR} y1={mid} y2={mid} stroke="var(--border-strong)" strokeWidth="1" />

        {/* Y ticks - top half */}
        {[0.5, 1].map((f) => (
          <g key={"u" + f}>
            <line x1={padL} x2={W - padR} y1={mid - half * f} y2={mid - half * f} stroke="var(--border-1)" strokeDasharray="2 4" />
            <text x={padL - 8} y={mid - half * f + 3} textAnchor="end" className="cf-axis-label">{fmtUSD(top * f, { short: true })}</text>
          </g>
        ))}
        {/* Y ticks - bottom half */}
        {[0.5, 1].map((f) => (
          <g key={"d" + f}>
            <line x1={padL} x2={W - padR} y1={mid + half * f} y2={mid + half * f} stroke="var(--border-1)" strokeDasharray="2 4" />
            <text x={padL - 8} y={mid + half * f + 3} textAnchor="end" className="cf-axis-label">{fmtUSD(top * f, { short: true })}</text>
          </g>
        ))}

        {/* Bars */}
        {weekly.map((w, i) => {
          const cx = padL + gap * i + gap / 2;
          const inH = (w.inflow / top) * half;
          const outH = (w.outflow / top) * half;
          return (
            <g key={i}>
              <rect x={cx - barW - 1.5} y={mid - inH} width={barW} height={inH} rx="2" fill="var(--funding-pool)" />
              <rect x={cx + 1.5} y={mid} width={barW} height={outH} rx="2" fill="var(--color-warning)" opacity="0.85" />
            </g>
          );
        })}

        {/* Net line */}
        <path d={netPath} fill="none" stroke="var(--trust-tech)" strokeWidth="1.6" strokeDasharray="3 2.5" />
        {weekly.map((w, i) => {
          const cx = padL + gap * i + gap / 2;
          return <circle key={i} cx={cx} cy={netY(w.net)} r="2.5" fill="var(--trust-tech)" />;
        })}

        {/* X labels - sparse */}
        {weekly.map((w, i) => {
          if (i % 3 !== 0 && i !== weekly.length - 1) return null;
          const cx = padL + gap * i + gap / 2;
          const label = i === weekly.length - 1 ? "this wk" : "-" + (weekly.length - 1 - i) + "w";
          return <text key={i} x={cx} y={H - 16} textAnchor="middle" className="cf-axis-label">{label}</text>;
        })}
      </svg>

      <div className="cf-chart-legend">
        <span><span className="bar-key" style={{ background: "var(--funding-pool)" }} /> Inflow</span>
        <span><span className="bar-key" style={{ background: "var(--color-warning)" }} /> Outflow</span>
        <span><span className="dash-key" /> Net (weekly)</span>
      </div>
    </div>
  );
}

// ── Spending donut + peer-share comparison bars ───────────────────────────
function SpendingDonut({ spending }) {
  const cx = 110, cy = 110, r = 78, rIn = 54;
  let acc = 0;
  const total = spending.total;
  const arcs = spending.map((s) => {
    const start = (acc / total) * Math.PI * 2;
    acc += s.amount;
    const end = (acc / total) * Math.PI * 2;
    const large = end - start > Math.PI ? 1 : 0;
    const sx = cx + Math.cos(start - Math.PI / 2) * r;
    const sy = cy + Math.sin(start - Math.PI / 2) * r;
    const ex = cx + Math.cos(end - Math.PI / 2) * r;
    const ey = cy + Math.sin(end - Math.PI / 2) * r;
    const sxi = cx + Math.cos(end - Math.PI / 2) * rIn;
    const syi = cy + Math.sin(end - Math.PI / 2) * rIn;
    const exi = cx + Math.cos(start - Math.PI / 2) * rIn;
    const eyi = cy + Math.sin(start - Math.PI / 2) * rIn;
    return {
      key: s.key,
      d: `M ${sx} ${sy} A ${r} ${r} 0 ${large} 1 ${ex} ${ey} L ${sxi} ${syi} A ${rIn} ${rIn} 0 ${large} 0 ${exi} ${eyi} Z`,
      color: s.color,
    };
  });

  return (
    <div className="cf-donut-wrap">
      <div className="cf-donut-svg-wrap">
        <svg viewBox="0 0 220 220" className="cf-donut-svg">
          {arcs.map((a) => (
            <path key={a.key} d={a.d} fill={a.color} stroke="#fff" strokeWidth="1.5" />
          ))}
          <text x={cx} y={cy - 6} textAnchor="middle" className="cf-donut-num">{fmtUSD(total, { short: true })}</text>
          <text x={cx} y={cy + 14} textAnchor="middle" className="cf-donut-sub">spent · 30d</text>
        </svg>
      </div>
      <div className="cf-donut-legend">
        <div className="cf-donut-legend-hd">
          <span>Category</span>
          <span>You</span>
          <span>Peer</span>
        </div>
        {spending.map((s) => {
          const diff = s.share - s.peerShare;
          const tone = diff > 4 ? "bad" : diff > 1 ? "warn" : diff < -2 ? "good" : "neutral";
          return (
            <div key={s.key} className="cf-donut-row">
              <span className="cf-donut-cat">
                <span className="swatch" style={{ background: s.color }} />
                <span>{s.label}</span>
              </span>
              <span className="cf-donut-share">{s.share.toFixed(0)}%</span>
              <span className={"cf-donut-peer cf-tone-" + tone}>
                {s.peerShare}%
                {diff !== 0 ? <span className="cf-donut-delta">{diff > 0 ? "+" : ""}{diff.toFixed(0)}</span> : null}
              </span>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ── Peer histogram with "you" marker ──────────────────────────────────────
function PeerHistogram({ metric }) {
  const padL = 6, padR = 6, padT = 12, padB = 28;
  const W = 320, H = 130;
  const innerW = W - padL - padR, innerH = H - padT - padB;

  const max = Math.max(...metric.bins);
  const binW = innerW / metric.bins.length;

  // marker position by percentile (0–100)
  const markerX = padL + (metric.youPctile / 100) * innerW;

  const toneColor = {
    good: "var(--funding-pool)",
    neutral: "var(--growth-galaxy)",
    warn: "var(--color-warning)",
    bad: "var(--color-error)"
  }[metric.tone];

  return (
    <svg viewBox={`0 0 ${W} ${H}`} className="cf-hist-svg" preserveAspectRatio="none">
      {/* Histogram bars */}
      {metric.bins.map((b, i) => {
        const h = (b / max) * innerH;
        const x = padL + binW * i + 1;
        const y = padT + (innerH - h);
        // Highlight bin that contains "you" by percentile
        const cumStart = metric.bins.slice(0, i).reduce((s, x) => s + x, 0);
        const cumEnd = cumStart + b;
        const total = metric.bins.reduce((s, x) => s + x, 0);
        const youCum = (metric.youPctile / 100) * total;
        const isYouBin = youCum >= cumStart && youCum <= cumEnd;
        return (
          <rect
            key={i}
            x={x}
            y={y}
            width={binW - 2}
            height={Math.max(2, h)}
            rx="2"
            fill={isYouBin ? toneColor : "var(--gg-10)"}
            opacity={isYouBin ? 1 : 1}
          />
        );
      })}

      {/* You marker */}
      <g>
        <line x1={markerX} x2={markerX} y1={padT - 2} y2={H - padB + 6} stroke={toneColor} strokeWidth="2" />
        <polygon
          points={`${markerX},${padT - 6} ${markerX - 5},${padT - 14} ${markerX + 5},${padT - 14}`}
          fill={toneColor}
        />
        <text x={markerX} y={padT - 18} textAnchor="middle" className="cf-hist-marker-lab" fill={toneColor}>
          you · p{metric.youPctile}
        </text>
      </g>

      {/* Median guide */}
      <g>
        <text x={padL} y={H - 10} className="cf-hist-axis">peers</text>
        <text x={W - padR} y={H - 10} textAnchor="end" className="cf-hist-axis">p25 · p50 · p75</text>
      </g>
    </svg>
  );
}

// ── Percentile rings (concentric, brand motif) ────────────────────────────
function PercentileRings({ metrics }) {
  // 4 rings, outermost to innermost
  const colors = {
    good: "var(--funding-pool)",
    neutral: "var(--growth-galaxy)",
    warn: "var(--color-warning)",
    bad: "var(--color-error)"
  };
  const cx = 130, cy = 130;
  const baseR = 110, ringGap = 22;
  return (
    <svg viewBox="0 0 260 260" className="cf-rings-svg">
      {metrics.map((m, i) => {
        const r = baseR - i * ringGap;
        const circ = 2 * Math.PI * r;
        const pct = m.youPctile / 100;
        // For "good" metrics higher is better; for "bad" metrics lower is better.
        // We always draw a fraction proportional to youPctile and let tone color tell the story.
        const dash = circ * pct;
        const rest = circ - dash;
        return (
          <g key={m.key} transform={`rotate(-90 ${cx} ${cy})`}>
            <circle cx={cx} cy={cy} r={r} fill="none" stroke="var(--tt-5)" strokeWidth="10" />
            <circle
              cx={cx} cy={cy} r={r}
              fill="none"
              stroke={colors[m.tone]}
              strokeWidth="10"
              strokeDasharray={`${dash} ${rest}`}
              strokeLinecap="round"
            />
          </g>
        );
      })}
      <text x={cx} y={cy - 6} textAnchor="middle" className="cf-rings-num">vs.</text>
      <text x={cx} y={cy + 14} textAnchor="middle" className="cf-rings-sub">247 peers</text>
    </svg>
  );
}

// Export to window
Object.assign(window, {
  CFSparkline: Sparkline,
  BalanceChart,
  FlowBars,
  SpendingDonut,
  PeerHistogram,
  PercentileRings,
  cfFmtUSD: fmtUSD,
  cfFmtAmt: fmtAmt,
});
