// Charts — pure SVG, no external libs.
const { useMemo: useMemoC, useEffect: useEffectC, useRef: useRefC, useState: useStateC } = React;

// ============================================================
// Sparkline (line + optional area fill)
// ============================================================
function Sparkline({ data, w = 120, h = 32, color = "#19E5A6", fill = true, strokeW = 1.5, ariaLabel }) {
  const path = useMemoC(() => {
    if (!data || data.length < 2) return { line: "", area: "" };
    const min = Math.min(...data), max = Math.max(...data);
    const span = max - min || 1;
    const pts = data.map((v, i) => [
      (i / (data.length - 1)) * w,
      h - 2 - ((v - min) / span) * (h - 4),
    ]);
    const line = pts.map(([x, y], i) => (i === 0 ? `M${x},${y}` : `L${x},${y}`)).join(" ");
    const area = `${line} L${w},${h} L0,${h} Z`;
    return { line, area };
  }, [data, w, h]);
  const id = useMemoC(() => "spg-" + Math.random().toString(36).slice(2, 8), []);
  return (
    <svg width={w} height={h} role="img" aria-label={ariaLabel} style={{ display: "block" }}>
      <defs>
        <linearGradient id={id} x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%" stopColor={color} stopOpacity="0.35" />
          <stop offset="100%" stopColor={color} stopOpacity="0" />
        </linearGradient>
      </defs>
      {fill && <path d={path.area} fill={`url(#${id})`} />}
      <path d={path.line} fill="none" stroke={color} strokeWidth={strokeW} strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

// ============================================================
// Drawdown gauge (half-arc)
// ============================================================
function DrawdownGauge({ value, max, size = 180 }) {
  const pct = Math.min(1, value / max);
  const w = size, h = size * 0.62;
  const cx = w / 2, cy = h - 8;
  const r = w / 2 - 14;
  const startA = Math.PI, endA = 0;
  const arc = (a0, a1) => {
    const x0 = cx + r * Math.cos(a0), y0 = cy + r * Math.sin(a0);
    const x1 = cx + r * Math.cos(a1), y1 = cy + r * Math.sin(a1);
    const large = Math.abs(a1 - a0) > Math.PI ? 1 : 0;
    const sweep = a1 > a0 ? 1 : 0;
    return `M${x0},${y0} A${r},${r} 0 ${large} ${sweep} ${x1},${y1}`;
  };
  const angAt = (p) => startA - (startA - endA) * p;
  const color = pct < 0.5 ? "var(--profit)" : pct < 0.8 ? "var(--warn)" : "var(--loss)";
  return (
    <svg width="100%" height={h} viewBox={`0 0 ${w} ${h}`} style={{ display: "block" }}>
      <path d={arc(startA, endA)} fill="none" stroke="rgba(255,255,255,0.08)" strokeWidth="10" strokeLinecap="round" />
      <path d={arc(startA, angAt(pct))} fill="none" stroke={color} strokeWidth="10" strokeLinecap="round" style={{ transition: "all .6s ease" }} />
      {[0.25, 0.5, 0.75].map((t) => {
        const a = angAt(t);
        const x0 = cx + (r - 14) * Math.cos(a), y0 = cy + (r - 14) * Math.sin(a);
        const x1 = cx + (r - 4)  * Math.cos(a), y1 = cy + (r - 4)  * Math.sin(a);
        return <line key={t} x1={x0} y1={y0} x2={x1} y2={y1} stroke="rgba(255,255,255,0.15)" strokeWidth="1.5" />;
      })}
      <g style={{ transition: "transform .6s ease" }} transform={`rotate(${(180 - (180 * pct))} ${cx} ${cy})`}>
        <line x1={cx} y1={cy} x2={cx - r + 12} y2={cy} stroke={color} strokeWidth="2.5" strokeLinecap="round" />
        <circle cx={cx} cy={cy} r="5" fill="var(--bg)" stroke={color} strokeWidth="2" />
      </g>
    </svg>
  );
}

// ============================================================
// Equity curve with benchmark overlay + hover
// ============================================================
function EquityCurve({ portfolio, benchmark, h = 280, accent = "#00D4AA", yLabel = (v) => "$" + Math.round(v / 1000) + "k" }) {
  const wrapRef = useRefC(null);
  const [w, setW] = useStateC(800);
  const [hover, setHover] = useStateC(null);

  useEffectC(() => {
    if (!wrapRef.current) return;
    const ro = new ResizeObserver(([e]) => setW(Math.max(400, e.contentRect.width)));
    ro.observe(wrapRef.current);
    return () => ro.disconnect();
  }, []);

  const pad = { t: 18, r: 18, b: 26, l: 56 };
  const innerW = w - pad.l - pad.r;
  const innerH = h - pad.t - pad.b;

  const all = [...portfolio, ...(benchmark || [])];
  const min = Math.min(...all);
  const max = Math.max(...all);
  const span = max - min || 1;
  const n = portfolio.length;

  const toXY = (v, i) => [
    pad.l + (i / (n - 1)) * innerW,
    pad.t + innerH - ((v - min) / span) * innerH,
  ];

  const linePath = (arr) =>
    arr.map((v, i) => {
      const [x, y] = toXY(v, i);
      return (i === 0 ? "M" : "L") + x.toFixed(1) + "," + y.toFixed(1);
    }).join(" ");

  const areaPath = (arr) =>
    linePath(arr) + ` L${pad.l + innerW},${pad.t + innerH} L${pad.l},${pad.t + innerH} Z`;

  const yTicks = Array.from({ length: 5 }, (_, i) => min + (span * i) / 4);

  const onMove = (e) => {
    const rect = e.currentTarget.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const idx = Math.round(((x - pad.l) / innerW) * (n - 1));
    if (idx >= 0 && idx < n) setHover(idx); else setHover(null);
  };

  return (
    <div ref={wrapRef} style={{ position: "relative", width: "100%" }}>
      <svg width={w} height={h} onMouseMove={onMove} onMouseLeave={() => setHover(null)} style={{ display: "block", cursor: "crosshair" }}>
        <defs>
          <linearGradient id="eq-grad" x1="0" x2="0" y1="0" y2="1">
            <stop offset="0%" stopColor={accent} stopOpacity="0.28" />
            <stop offset="100%" stopColor={accent} stopOpacity="0" />
          </linearGradient>
        </defs>
        {yTicks.map((v, i) => {
          const y = pad.t + innerH - ((v - min) / span) * innerH;
          return (
            <g key={i}>
              <line x1={pad.l} x2={pad.l + innerW} y1={y} y2={y} stroke="rgba(255,255,255,0.05)" />
              <text x={pad.l - 8} y={y + 4} fill="var(--text-3)" fontSize="11" textAnchor="end" fontFamily="JetBrains Mono">
                {yLabel(v)}
              </text>
            </g>
          );
        })}
        {benchmark && <path d={linePath(benchmark)} fill="none" stroke="var(--text-3)" strokeWidth="1.5" strokeDasharray="4 4" opacity="0.7" />}
        <path d={areaPath(portfolio)} fill="url(#eq-grad)" />
        <path d={linePath(portfolio)} fill="none" stroke={accent} strokeWidth="2" />
        {["6mo", "5mo", "4mo", "3mo", "2mo", "1mo", "Now"].map((lab, i) => {
          const x = pad.l + (i / 6) * innerW;
          return <text key={i} x={x} y={h - 6} fill="var(--text-3)" fontSize="11" textAnchor="middle" fontFamily="JetBrains Mono">{lab}</text>;
        })}
        {hover != null && (() => {
          const [hx, hy] = toXY(portfolio[hover], hover);
          return (
            <g>
              <line x1={hx} x2={hx} y1={pad.t} y2={pad.t + innerH} stroke="rgba(255,255,255,0.18)" strokeDasharray="3 3" />
              {benchmark && (() => { const [, by] = toXY(benchmark[hover], hover); return <circle cx={hx} cy={by} r="4" fill="var(--bg)" stroke="var(--text-3)" strokeWidth="1.5" />; })()}
              <circle cx={hx} cy={hy} r="5" fill={accent} stroke="var(--bg)" strokeWidth="2" />
            </g>
          );
        })()}
      </svg>
      {hover != null && (() => {
        const x = pad.l + (hover / (n - 1)) * innerW;
        const left = Math.min(w - 180, Math.max(0, x + 12));
        return (
          <div style={{
            position: "absolute", top: 14, left, pointerEvents: "none",
            background: "rgba(8,11,20,0.92)", border: "1px solid var(--line-strong)",
            borderRadius: 8, padding: "8px 10px", fontSize: 12, color: "var(--text)",
            minWidth: 160, backdropFilter: "blur(8px)",
          }}>
            <div style={{ color: "var(--text-3)", marginBottom: 4 }} className="mono">{Math.round((1 - hover/(n-1)) * 6 * 30)}d ago</div>
            <div style={{ display: "flex", justifyContent: "space-between", gap: 12 }}>
              <span style={{ color: "var(--text-2)" }}>Equity</span>
              <span className="mono" style={{ color: accent }}>${portfolio[hover].toFixed(0)}</span>
            </div>
            {benchmark && (
              <div style={{ display: "flex", justifyContent: "space-between", gap: 12 }}>
                <span style={{ color: "var(--text-2)" }}>BTC HODL</span>
                <span className="mono" style={{ color: "var(--text-2)" }}>${benchmark[hover].toFixed(0)}</span>
              </div>
            )}
          </div>
        );
      })()}
    </div>
  );
}

// ============================================================
// Portfolio sparkline (medium size, no axis)
// ============================================================
function PortfolioSpark({ data, accent = "#00D4AA", w = 320, h = 80 }) {
  const min = Math.min(...data), max = Math.max(...data);
  const span = max - min || 1;
  const pts = data.map((v, i) => [
    (i / (data.length - 1)) * w,
    h - 4 - ((v - min) / span) * (h - 8),
  ]);
  const line = pts.map(([x, y], i) => (i === 0 ? `M${x},${y}` : `L${x},${y}`)).join(" ");
  const area = `${line} L${w},${h} L0,${h} Z`;
  return (
    <svg width="100%" viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none" style={{ display: "block" }}>
      <defs>
        <linearGradient id="ps-grad" x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%" stopColor={accent} stopOpacity="0.4" />
          <stop offset="100%" stopColor={accent} stopOpacity="0" />
        </linearGradient>
      </defs>
      <path d={area} fill="url(#ps-grad)" />
      <path d={line} fill="none" stroke={accent} strokeWidth="2" vectorEffect="non-scaling-stroke" />
      <circle cx={pts[pts.length-1][0]} cy={pts[pts.length-1][1]} r="3.5" fill={accent} />
    </svg>
  );
}

// ============================================================
// Daily P&L bar chart (gain/loss bars + win rate dots)
// ============================================================
function DailyPnLBars({ data, h = 200 }) {
  const wrapRef = useRefC(null);
  const [w, setW] = useStateC(800);
  useEffectC(() => {
    if (!wrapRef.current) return;
    const ro = new ResizeObserver(([e]) => setW(Math.max(300, e.contentRect.width)));
    ro.observe(wrapRef.current);
    return () => ro.disconnect();
  }, []);
  const pad = { t: 14, r: 16, b: 24, l: 50 };
  const iw = w - pad.l - pad.r;
  const ih = h - pad.t - pad.b;
  const max = Math.max(...data.map((d) => Math.abs(d.pnl)));
  const zero = pad.t + ih / 2;
  const halfH = ih / 2;
  const barW = (iw / data.length) * 0.7;
  const step = iw / data.length;
  return (
    <div ref={wrapRef} style={{ width: "100%" }}>
      <svg width={w} height={h} style={{ display: "block" }}>
        {/* y ticks */}
        {[-max, -max/2, 0, max/2, max].map((v, i) => {
          const y = zero - (v / max) * halfH;
          return (
            <g key={i}>
              <line x1={pad.l} x2={pad.l + iw} y1={y} y2={y} stroke="rgba(255,255,255,0.05)" />
              <text x={pad.l - 8} y={y + 4} fill="var(--text-3)" fontSize="10" textAnchor="end" fontFamily="JetBrains Mono">
                {(v >= 0 ? "+" : "−") + "$" + Math.abs(Math.round(v))}
              </text>
            </g>
          );
        })}
        <line x1={pad.l} x2={pad.l + iw} y1={zero} y2={zero} stroke="rgba(255,255,255,0.18)" />
        {data.map((d, i) => {
          const cx = pad.l + i * step + step / 2;
          const x = cx - barW / 2;
          const barH = Math.abs(d.pnl / max) * halfH;
          const y = d.pnl >= 0 ? zero - barH : zero;
          const fill = d.pnl >= 0 ? "var(--profit)" : "var(--loss)";
          return (
            <g key={i}>
              <rect x={x} y={y} width={barW} height={Math.max(2, barH)} rx="2" fill={fill} opacity="0.85">
                <title>{d.d === 0 ? "Today" : Math.abs(d.d) + "d ago"} · {(d.pnl >= 0 ? "+" : "−") + "$" + Math.abs(d.pnl).toFixed(2)} · {d.trades} trades · {Math.round(d.wr*100)}% wr</title>
              </rect>
              {i % 2 === 0 && (
                <text x={cx} y={h - 6} fill="var(--text-3)" fontSize="10" textAnchor="middle" fontFamily="JetBrains Mono">
                  {d.d === 0 ? "today" : Math.abs(d.d) + "d"}
                </text>
              )}
            </g>
          );
        })}
      </svg>
    </div>
  );
}

// ============================================================
// Latency histogram (signal → execution)
// ============================================================
function LatencyHistogram({ samples, h = 140 }) {
  const wrapRef = useRefC(null);
  const [w, setW] = useStateC(400);
  useEffectC(() => {
    if (!wrapRef.current) return;
    const ro = new ResizeObserver(([e]) => setW(Math.max(200, e.contentRect.width)));
    ro.observe(wrapRef.current);
    return () => ro.disconnect();
  }, []);
  // Bin samples into 8 buckets
  const max = 1000;
  const buckets = Array(8).fill(0);
  samples.forEach((v) => {
    const b = Math.min(7, Math.floor((v / max) * 8));
    buckets[b]++;
  });
  const peak = Math.max(...buckets, 1);
  const pad = { t: 8, r: 8, b: 24, l: 8 };
  const iw = w - pad.l - pad.r;
  const ih = h - pad.t - pad.b;
  const barW = iw / buckets.length;
  return (
    <div ref={wrapRef} style={{ width: "100%" }}>
      <svg width={w} height={h} style={{ display: "block" }}>
        {buckets.map((b, i) => {
          const barH = (b / peak) * ih;
          const x = pad.l + i * barW;
          const y = pad.t + ih - barH;
          const ms = i * (max / 8);
          const fill = ms < 500 ? "var(--profit)" : ms < 1000 ? "var(--warn)" : "var(--loss)";
          return (
            <g key={i}>
              <rect x={x + 2} y={y} width={barW - 4} height={Math.max(2, barH)} rx="3" fill={fill} opacity="0.75">
                <title>{ms}–{ms + max/8}ms · {b} signals</title>
              </rect>
              <text x={x + barW / 2} y={h - 8} fill="var(--text-3)" fontSize="10" textAnchor="middle" fontFamily="JetBrains Mono">
                {Math.round(ms)}
              </text>
            </g>
          );
        })}
      </svg>
    </div>
  );
}

// ============================================================
// Signal funnel — vertical bars showing dropoff
// ============================================================
function SignalFunnel({ stages }) {
  const max = Math.max(...stages.map((s) => s.value));
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
      {stages.map((s, i) => {
        const pct = (s.value / max) * 100;
        return (
          <div key={i}>
            <div style={{ display: "flex", justifyContent: "space-between", fontSize: 12, marginBottom: 4 }}>
              <span style={{ color: "var(--text-2)" }}>{s.label}</span>
              <span className="mono" style={{ color: s.color || "var(--text)" }}>{s.value}{s.suffix || ""}</span>
            </div>
            <div style={{ height: 10, background: "rgba(255,255,255,0.05)", borderRadius: 5, overflow: "hidden" }}>
              <div style={{ width: pct + "%", height: "100%", background: s.color || "var(--accent)", borderRadius: 5, transition: "width .6s" }} />
            </div>
          </div>
        );
      })}
    </div>
  );
}

// ============================================================
// Hourly heatmap — 24 cells
// ============================================================
function HourlyHeatmap({ data, h = 60 }) {
  const max = Math.max(...data.map((d) => Math.abs(d.pnl)));
  return (
    <div style={{ display: "grid", gridTemplateColumns: "repeat(24, 1fr)", gap: 3 }}>
      {data.map((d, i) => {
        const intensity = Math.abs(d.pnl) / max;
        const color = d.pnl >= 0
          ? `rgba(25,229,166,${0.10 + intensity * 0.75})`
          : `rgba(242,63,92,${0.10 + intensity * 0.75})`;
        return (
          <div key={i} style={{
            height: h, background: color, borderRadius: 3,
            display: "flex", alignItems: "flex-end", justifyContent: "center",
            padding: "0 0 3px", fontSize: 9, fontFamily: "JetBrains Mono",
            color: intensity > 0.5 ? "rgba(0,0,0,0.7)" : "var(--text-3)",
          }} title={`${d.hour.toString().padStart(2,"0")}:00 UTC · ${d.pnl >= 0 ? "+" : "−"}$${Math.abs(d.pnl).toFixed(0)} · ${d.trades} trades`}>
            {i % 3 === 0 ? d.hour.toString().padStart(2, "0") : ""}
          </div>
        );
      })}
    </div>
  );
}

// ============================================================
// Monthly returns heatmap (backtest)
// ============================================================
function MonthlyHeatmap({ data }) {
  const months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
  const all = data.flatMap((r) => r.vals).filter((v) => v != null);
  const max = Math.max(...all.map(Math.abs));
  return (
    <div style={{ overflowX: "auto" }}>
      <table style={{ width: "100%", borderCollapse: "separate", borderSpacing: 3 }}>
        <thead>
          <tr>
            <th style={{ fontSize: 11, color: "var(--text-3)", fontWeight: 500, textAlign: "left", padding: "0 6px" }}></th>
            {months.map((m) => <th key={m} style={{ fontSize: 10, color: "var(--text-3)", fontWeight: 500, padding: 2, fontFamily: "JetBrains Mono" }}>{m}</th>)}
            <th style={{ fontSize: 10, color: "var(--text-3)", fontWeight: 500, padding: 2, fontFamily: "JetBrains Mono" }}>YTD</th>
          </tr>
        </thead>
        <tbody>
          {data.map((row) => {
            const ytd = row.vals.filter((v) => v != null).reduce((a, b) => a + b, 0);
            return (
              <tr key={row.year}>
                <td style={{ fontSize: 11, color: "var(--text-2)", fontFamily: "JetBrains Mono", padding: "0 6px 0 0" }}>{row.year}</td>
                {row.vals.map((v, i) => {
                  if (v == null) return <td key={i} style={{ background: "rgba(255,255,255,0.02)", borderRadius: 3, height: 28 }} />;
                  const intensity = Math.abs(v) / max;
                  const bg = v >= 0
                    ? `rgba(25,229,166,${0.12 + intensity * 0.7})`
                    : `rgba(242,63,92,${0.12 + intensity * 0.7})`;
                  return (
                    <td key={i} style={{
                      background: bg, borderRadius: 3, height: 28,
                      textAlign: "center", fontSize: 10, fontFamily: "JetBrains Mono",
                      color: intensity > 0.45 ? "rgba(0,0,0,0.78)" : "var(--text)",
                    }}>{v > 0 ? "+" : ""}{v.toFixed(1)}</td>
                  );
                })}
                <td style={{
                  textAlign: "center", fontSize: 10, fontFamily: "JetBrains Mono", fontWeight: 600,
                  color: ytd >= 0 ? "var(--profit)" : "var(--loss)",
                  background: "rgba(255,255,255,0.04)", borderRadius: 3, padding: "0 6px",
                }}>{ytd > 0 ? "+" : ""}{ytd.toFixed(1)}%</td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

// ============================================================
// P&L distribution histogram (trade outcomes)
// ============================================================
function PnLHistogram({ trades, h = 160 }) {
  const wrapRef = useRefC(null);
  const [w, setW] = useStateC(400);
  useEffectC(() => {
    if (!wrapRef.current) return;
    const ro = new ResizeObserver(([e]) => setW(Math.max(200, e.contentRect.width)));
    ro.observe(wrapRef.current);
    return () => ro.disconnect();
  }, []);
  const vals = trades.filter((t) => t.pnl != null).map((t) => t.pnl);
  const min = Math.min(...vals, -120);
  const max = Math.max(...vals, 120);
  const n = 12;
  const buckets = Array(n).fill(0);
  vals.forEach((v) => {
    const b = Math.max(0, Math.min(n - 1, Math.floor(((v - min) / (max - min)) * n)));
    buckets[b]++;
  });
  const peak = Math.max(...buckets, 1);
  const pad = { t: 8, r: 8, b: 24, l: 8 };
  const iw = w - pad.l - pad.r;
  const ih = h - pad.t - pad.b;
  const barW = iw / n;
  return (
    <div ref={wrapRef} style={{ width: "100%" }}>
      <svg width={w} height={h} style={{ display: "block" }}>
        {buckets.map((b, i) => {
          const barH = (b / peak) * ih;
          const x = pad.l + i * barW;
          const y = pad.t + ih - barH;
          const v0 = min + (i / n) * (max - min);
          const fill = v0 >= 0 ? "var(--profit)" : "var(--loss)";
          return (
            <g key={i}>
              <rect x={x + 1.5} y={y} width={barW - 3} height={Math.max(2, barH)} rx="2" fill={fill} opacity="0.7">
                <title>{Math.round(v0)} – {Math.round(v0 + (max-min)/n)} · {b} trades</title>
              </rect>
            </g>
          );
        })}
        <text x={pad.l} y={h - 8} fill="var(--text-3)" fontSize="10" fontFamily="JetBrains Mono">−${Math.round(Math.abs(min))}</text>
        <text x={pad.l + iw / 2} y={h - 8} fill="var(--text-3)" fontSize="10" fontFamily="JetBrains Mono" textAnchor="middle">$0</text>
        <text x={pad.l + iw} y={h - 8} fill="var(--text-3)" fontSize="10" fontFamily="JetBrains Mono" textAnchor="end">+${Math.round(max)}</text>
      </svg>
    </div>
  );
}

// ============================================================
// Log volume line chart (last 24h, hourly buckets)
// ============================================================
function LogVolumeChart({ data, h = 80, accent = "#00D4AA" }) {
  const wrapRef = useRefC(null);
  const [w, setW] = useStateC(400);
  useEffectC(() => {
    if (!wrapRef.current) return;
    const ro = new ResizeObserver(([e]) => setW(Math.max(200, e.contentRect.width)));
    ro.observe(wrapRef.current);
    return () => ro.disconnect();
  }, []);
  const max = Math.max(...data, 1);
  const pad = { t: 6, r: 6, b: 14, l: 6 };
  const iw = w - pad.l - pad.r;
  const ih = h - pad.t - pad.b;
  const barW = iw / data.length;
  return (
    <div ref={wrapRef} style={{ width: "100%" }}>
      <svg width={w} height={h} style={{ display: "block" }}>
        {data.map((v, i) => {
          const barH = (v / max) * ih;
          return (
            <rect key={i} x={pad.l + i * barW + 1} y={pad.t + ih - barH}
              width={Math.max(1, barW - 2)} height={Math.max(1, barH)}
              fill={accent} opacity={0.4 + (v / max) * 0.6} rx="1" />
          );
        })}
        <text x={pad.l} y={h - 2} fill="var(--text-3)" fontSize="9" fontFamily="JetBrains Mono">24h ago</text>
        <text x={pad.l + iw} y={h - 2} fill="var(--text-3)" fontSize="9" fontFamily="JetBrains Mono" textAnchor="end">now</text>
      </svg>
    </div>
  );
}

Object.assign(window, {
  Sparkline, DrawdownGauge, EquityCurve, PortfolioSpark,
  DailyPnLBars, LatencyHistogram, SignalFunnel, HourlyHeatmap, MonthlyHeatmap, PnLHistogram, LogVolumeChart,
});
