/* LabCharts — the Strategy Lab's charts (18 Sep 2026).

   Gianni asked for charts that make the drawdown visible, and pointed at shadcn/ui's chart components. Those are Recharts with a
   ChartContainer + a card-styled tooltip and CSS-variable colors, so that is exactly what
   this is: Recharts (UMD, pinned 2.15) wrapped in a small container of our own, painted
   with Reezer's tokens — money green/red, violet rationed, hairline borders, no gradients.

   Standing rule on every chart here (he had to ask three times): BOTH sides. A win
   figure never appears without its loss counterpart. */

const RC = window.Recharts || {};

/* ---------- shadcn-style container: title, subtitle, fixed height, legend row ---------- */
function NT_ChartCard({ title, subtitle, legend, height, children }) {
  return (
    <div style={{ background: "var(--surface)", border: "1px solid var(--border)", borderRadius: "var(--radius-lg)", padding: "16px 18px 10px" }}>
      <div style={{ display: "flex", alignItems: "baseline", justifyContent: "space-between", gap: 12, flexWrap: "wrap" }}>
        <div style={{ minWidth: 0 }}>
          <div style={{ font: "var(--w-semibold) var(--t-sm)/1.2 var(--font-sans)", color: "var(--text-primary)" }}>{title}</div>
          {subtitle ? <div style={{ font: "var(--w-regular) var(--t-sm)/1.45 var(--font-sans)", color: "var(--text-tertiary)", marginTop: 4 }}>{subtitle}</div> : null}
        </div>
        {legend && legend.length ? (
          <div style={{ display: "flex", gap: 14, flexWrap: "wrap" }}>
            {legend.map((l, i) => (
              <span key={i} style={{ display: "inline-flex", alignItems: "center", gap: 6, font: "var(--w-regular) var(--t-sm)/1 var(--font-sans)", color: "var(--text-tertiary)", whiteSpace: "nowrap" }}>
                <span style={{ width: 8, height: 8, borderRadius: 2, background: l.color, flex: "none" }} />{l.label}
              </span>
            ))}
          </div>
        ) : null}
      </div>
      <div style={{ height: height || 220, marginTop: 14, minWidth: 0 }}>{children}</div>
    </div>
  );
}

/* ---------- tooltip: a small Reezer card, never a browser default ---------- */
function NT_ChartTip({ active, payload, label, fmt, titleFmt }) {
  if (!active || !payload || !payload.length) return null;
  return (
    <div style={{ background: "var(--surface-raised, var(--surface))", border: "1px solid var(--border-strong, var(--border))", borderRadius: "var(--radius-sm)", padding: "9px 11px", boxShadow: "0 6px 20px rgba(0,0,0,0.28)" }}>
      <div style={{ font: "var(--w-medium) var(--t-sm)/1 var(--font-sans)", color: "var(--text-tertiary)", marginBottom: 7 }}>
        {titleFmt ? titleFmt(label) : label}
      </div>
      {payload.map((p, i) => (
        <div key={i} style={{ display: "flex", alignItems: "center", gap: 8, marginTop: i ? 5 : 0 }}>
          <span style={{ width: 8, height: 8, borderRadius: 2, background: p.color || p.fill, flex: "none" }} />
          <span style={{ font: "var(--w-regular) var(--t-sm)/1 var(--font-sans)", color: "var(--text-secondary)", flex: 1 }}>{p.name}</span>
          <span style={{ font: "var(--w-medium) var(--t-sm)/1 var(--font-mono)", color: "var(--text-primary)", fontVariantNumeric: "tabular-nums" }}>
            {fmt ? fmt(p.value) : p.value}
          </span>
        </div>
      ))}
    </div>
  );
}

const LC_money = (v) => (v == null || isNaN(v) ? "—" : (v < 0 ? "−$" : "+$") + Math.abs(Math.round(v)).toLocaleString("en-US"));
const LC_axis = { stroke: "var(--text-tertiary)", fontSize: 13, fontFamily: "var(--font-mono)", tickLine: false, axisLine: false };

/* ---------- 1. equity curve with the drawdown underneath ---------- */
function LabEquityChart({ curve, worstLabel, height }) {
  if (!RC.ComposedChart || !curve || !curve.length) return null;
  const { ComposedChart, Area, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, ReferenceLine } = RC;
  const dd = Math.min.apply(null, curve.map((p) => p.dd));
  return (
    <NT_ChartCard
      title="Equity curve and drawdown"
      subtitle={"Each step is one trade. The red area is the drawdown: how far below your best result you stood at that moment" + (worstLabel ? " — deepest drawdown " + worstLabel : "") + "."}
      legend={[{ color: "var(--accent)", label: "running total" }, { color: "var(--loss)", label: "drawdown" }]}
      height={height || 260}>
      <ResponsiveContainer width="100%" height="100%">
        <ComposedChart data={curve} margin={{ top: 6, right: 6, left: 0, bottom: 0 }}>
          <CartesianGrid strokeDasharray="3 3" stroke="var(--border)" vertical={false} />
          <XAxis dataKey="i" {...LC_axis} minTickGap={24} />
          <YAxis {...LC_axis} width={52} tickFormatter={(v) => (v < 0 ? "−" : "") + "$" + Math.abs(v)} />
          <Tooltip content={<NT_ChartTip fmt={LC_money} titleFmt={(l) => "trade " + l} />} cursor={{ stroke: "var(--border-strong, var(--border))" }} />
          <ReferenceLine y={0} stroke="var(--border-strong, var(--border))" />
          <Area type="monotone" dataKey="dd" name="drawdown" stroke="var(--loss)" fill="var(--loss)" fillOpacity={0.16} strokeWidth={1} isAnimationActive={false} />
          <Line type="monotone" dataKey="eq" name="running total" stroke="var(--accent)" strokeWidth={2.2} dot={false} isAnimationActive={false} />
        </ComposedChart>
      </ResponsiveContainer>
    </NT_ChartCard>
  );
}

/* ---------- 2. every trade as a bar: winners and losers side by side ---------- */
function LabTradesChart({ curve, losses, height }) {
  if (!RC.BarChart || !curve || !curve.length) return null;
  const { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, ReferenceLine, Cell } = RC;
  // per-trade P&L from the running total, then sorted big win -> big loss so the SHAPE
  // of the distribution is the message (three towers vs eighteen even bars)
  const per = curve.map((p, i) => (i ? p.eq - curve[i - 1].eq : p.eq));
  const data = per.map((v, i) => ({ i: i + 1, v })).sort((a, b) => b.v - a.v).map((d, i) => ({ ...d, r: i + 1 }));
  const wins = data.filter((d) => d.v > 0).length;
  return (
    <NT_ChartCard
      title="Every trade, biggest win to biggest loss"
      subtitle={wins + " winners and " + (data.length - wins) + " losers. Towers on the right mean a handful of trades cause all of the loss."}
      legend={[{ color: "var(--profit)", label: "win" }, { color: "var(--loss)", label: "loss" }]}
      height={height || 220}>
      <ResponsiveContainer width="100%" height="100%">
        <BarChart data={data} margin={{ top: 6, right: 6, left: 0, bottom: 0 }}>
          <CartesianGrid strokeDasharray="3 3" stroke="var(--border)" vertical={false} />
          <XAxis dataKey="r" {...LC_axis} minTickGap={22} />
          <YAxis {...LC_axis} width={52} tickFormatter={(v) => (v < 0 ? "−" : "") + "$" + Math.abs(v)} />
          <Tooltip content={<NT_ChartTip fmt={LC_money} titleFmt={(l) => "no. " + l + " of " + data.length} />} cursor={{ fill: "var(--surface-inset)" }} />
          <ReferenceLine y={0} stroke="var(--border-strong, var(--border))" />
          <Bar dataKey="v" name="result" radius={[2, 2, 0, 0]} isAnimationActive={false}>
            {data.map((d, i) => <Cell key={i} fill={d.v >= 0 ? "var(--profit)" : "var(--loss)"} />)}
          </Bar>
        </BarChart>
      </ResponsiveContainer>
    </NT_ChartCard>
  );
}

/* ---------- 3. the landscape: dip-buy depth x count ---------- */
function LabLandscapeChart({ landscape, acct, height }) {
  if (!RC.BarChart || !landscape || !landscape.length) return null;
  const { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, ReferenceLine, Cell } = RC;
  const data = landscape.map((r) => ({
    name: r.depth === 0 ? "none" : "−" + r.depth + "% ×" + r.count,
    result: r.richest.pnl, dip: r.richest.mdd,
    shaped: r.shaped.pnl, shapedDip: r.shaped.mdd,
    label: r.richest.label,
  }));
  return (
    <NT_ChartCard
      title="The landscape: how deep and how often to dip-buy"
      subtitle={"Per combination the best result and the drawdown hanging under it. Everything below the line is what you have to sit through" + (acct ? " — your account is $" + Math.round(acct).toLocaleString("en-US") : "") + "."}
      legend={[{ color: "var(--profit)", label: "result" }, { color: "var(--loss)", label: "worst drawdown" }]}
      height={height || 260}>
      <ResponsiveContainer width="100%" height="100%">
        <BarChart data={data} margin={{ top: 6, right: 6, left: 0, bottom: 0 }} barGap={2}>
          <CartesianGrid strokeDasharray="3 3" stroke="var(--border)" vertical={false} />
          <XAxis dataKey="name" {...LC_axis} interval={0} angle={-30} textAnchor="end" height={54} />
          <YAxis {...LC_axis} width={52} tickFormatter={(v) => (v < 0 ? "−" : "") + "$" + Math.abs(v)} />
          <Tooltip content={<NT_ChartTip fmt={LC_money} />} cursor={{ fill: "var(--surface-inset)" }} />
          <ReferenceLine y={0} stroke="var(--border-strong, var(--border))" />
          <Bar dataKey="result" name="result" fill="var(--profit)" fillOpacity={0.22} stroke="var(--profit)" strokeWidth={1} barSize={16} radius={[2, 2, 0, 0]} isAnimationActive={false} />
          <Bar dataKey="dip" name="worst drawdown" fill="var(--loss)" fillOpacity={0.22} stroke="var(--loss)" strokeWidth={1} barSize={16} radius={[0, 0, 2, 2]} isAnimationActive={false} />
        </BarChart>
      </ResponsiveContainer>
    </NT_ChartCard>
  );
}

/* ---------- 4. how bad a bad stretch really gets (the reshuffles) ---------- */
function LabBootstrapChart({ bootstrap, observed, acct, height }) {
  if (!RC.BarChart || !bootstrap) return null;
  const { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Cell } = RC;
  const data = [
    { name: "the order that happened", v: observed || 0 },
    { name: "most orders", v: bootstrap.p50 },
    { name: "1 order in 20", v: bootstrap.p95 },
    { name: "1 in 100", v: bootstrap.p99 },
    { name: "worst of 2,000", v: bootstrap.extreme },
  ];
  const pct = (v) => (acct ? Math.round(Math.abs(v) / acct * 100) + "% of your account" : "");
  return (
    <NT_ChartCard
      title="What if the losses had clustered?"
      subtitle="Your trades happened in one particular order. Deal the SAME trades in a different order and the losing ones sometimes land close together — that is when a drawdown gets deep. Dealt 2,000 ways: this is how bad it gets. Plan for the unlucky order, not the one you happened to get."
      legend={[{ color: "var(--loss)", label: "drawdown" }]}
      height={height || 200}>
      <ResponsiveContainer width="100%" height="100%">
        <BarChart data={data} margin={{ top: 6, right: 6, left: 0, bottom: 0 }}>
          <CartesianGrid strokeDasharray="3 3" stroke="var(--border)" vertical={false} />
          <XAxis dataKey="name" {...LC_axis} interval={0} />
          <YAxis {...LC_axis} width={52} domain={[(d) => Math.round(d * 1.08), 0]} tickFormatter={(v) => (v < 0 ? "−" : "") + "$" + Math.abs(v)} />
          <Tooltip content={<NT_ChartTip fmt={(v) => LC_money(v) + (acct ? "  ·  " + pct(v) : "")} />} cursor={{ fill: "var(--surface-inset)" }} />
          <Bar dataKey="v" name="drawdown" radius={[0, 0, 2, 2]} barSize={34}
               isAnimationActive={false} strokeWidth={1}>
            {data.map((d, i) => (
              <Cell key={i} fill={i === 0 ? "var(--text-tertiary)" : "var(--loss)"} fillOpacity={i === 0 ? 0.18 : 0.22}
                    stroke={i === 0 ? "var(--text-tertiary)" : "var(--loss)"} />))}
          </Bar>
        </BarChart>
      </ResponsiveContainer>
    </NT_ChartCard>
  );
}

Object.assign(window, { NT_ChartCard, NT_ChartTip, LabEquityChart, LabTradesChart, LabLandscapeChart, LabBootstrapChart, LC_money });
