// Dashboard page — single BTC/USDT bot overview.
const { useState: ucS, useEffect: ucE, useMemo: ucM } = React;

// =================== KPI tile ===================
function Kpi({ label, value, sub, tone = "text", icon, span }) {
  const c = { text: "var(--text)", profit: "var(--profit)", loss: "var(--loss)", warn: "var(--warn)", accent: "var(--accent)" }[tone];
  return (
    <div style={{
      padding: "18px 20px", borderRadius: 14,
      background: "linear-gradient(180deg, rgba(20,26,42,0.6), rgba(15,19,32,0.6))",
      border: "1px solid var(--line)", display: "flex", flexDirection: "column", gap: 6,
      gridColumn: span ? "span " + span : "auto", minWidth: 0,
    }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
        <div style={{ fontSize: 11, color: "var(--text-3)", letterSpacing: 0.5, textTransform: "uppercase" }}>{label}</div>
        {icon && <div style={{ color: "var(--text-3)" }}>{icon}</div>}
      </div>
      <div className="mono" style={{ fontSize: 26, fontWeight: 600, color: c, letterSpacing: -0.5 }}>{value}</div>
      {sub && <div style={{ fontSize: 12, color: "var(--text-3)" }}>{sub}</div>}
    </div>
  );
}

// =================== Open position card ===================
function OpenPositionCard({ accent, livePrices, activeExchange = "binance" }) {
  const trade = TRADES.find((t) => t.status === "open");
  const ex = EXCHANGES[activeExchange] || EXCHANGES.binance;
  const [price, dir] = livePrices
    ? useTicker(64210.50, { volatility: 0.0008, intervalMs: 1500 })
    : [64210.50, 0];
  const pnlPct = trade ? ((price - trade.entry) / trade.entry) * 100 : 0;
  const pnl = trade ? (price - trade.entry) * trade.qty * 10 : 0;
  return (
    <Card padded={false}>
      <div style={{ padding: "18px var(--pad) 16px", borderBottom: "1px solid var(--line)", display: "flex", alignItems: "center", gap: 12 }}>
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 14, fontWeight: 600 }}>Open position</div>
          <div style={{ fontSize: 12, color: "var(--text-3)", marginTop: 2, display: "inline-flex", alignItems: "center", gap: 6 }}>
            BTC/USDT · LONG · entered {fmtRel(trade.t)} ·
            <span style={{ display: "inline-flex", alignItems: "center", gap: 4, color: "var(--text-2)" }}>
              <ex.Icon size={11} />{ex.name}
            </span>
          </div>
        </div>
        <Badge variant="profit">● LIVE</Badge>
      </div>
      <div style={{ padding: "20px var(--pad)", display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 18 }}>
        <Field label="Entry" value={"$" + trade.entry.toLocaleString(undefined, { minimumFractionDigits: 2 })} />
        <Field label="Mark" value={"$" + price.toLocaleString(undefined, { minimumFractionDigits: 2 })} tickDir={dir} accent />
        <Field label="Quantity" value={trade.qty + " BTC"} sub={"~$" + (trade.qty * price).toFixed(0)} />
        <Field label={ex.stopLoss + " stop"} value={"$" + trade.stop.toLocaleString(undefined, { minimumFractionDigits: 2 })} sub={"−2.00% · " + ex.stopLossNote} tone="loss" />
      </div>
      <div style={{ padding: "0 var(--pad) 18px", display: "flex", alignItems: "center", gap: 14 }}>
        <div style={{
          flex: 1, padding: "12px 14px", borderRadius: 10,
          background: pnl >= 0 ? "rgba(25,229,166,0.08)" : "rgba(242,63,92,0.08)",
          border: "1px solid " + (pnl >= 0 ? "rgba(25,229,166,0.2)" : "rgba(242,63,92,0.2)"),
          display: "flex", alignItems: "center", gap: 14,
        }}>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 11, color: "var(--text-3)", letterSpacing: 0.4, textTransform: "uppercase" }}>Unrealized P&amp;L</div>
            <div className="mono" style={{ fontSize: 22, fontWeight: 600, marginTop: 4, color: pnl >= 0 ? "var(--profit)" : "var(--loss)" }}>
              {fmtUsd(pnl, { sign: true })} <span style={{ fontSize: 13, opacity: 0.7 }}>· {fmtPct(pnlPct)}</span>
            </div>
          </div>
          {/* Risk ladder visualization */}
          <RiskLadder entry={trade.entry} mark={price} stop={trade.stop} />
        </div>
        <PrimaryBtn ghost icon={<IconStop size={14} />} style={{ height: 40 }}>Close at market</PrimaryBtn>
      </div>
    </Card>
  );
}

function Field({ label, value, sub, tone, accent, tickDir }) {
  const c = tone === "loss" ? "var(--loss)" : tone === "profit" ? "var(--profit)" : "var(--text)";
  return (
    <div>
      <div style={{ fontSize: 11, color: "var(--text-3)", letterSpacing: 0.4, textTransform: "uppercase" }}>{label}</div>
      <div className={tickDir > 0 ? "tick-up mono" : tickDir < 0 ? "tick-dn mono" : "mono"}
        style={{ fontSize: 18, fontWeight: 600, marginTop: 4, color: accent ? "var(--accent)" : c, padding: tickDir ? "2px 6px" : 0, margin: tickDir ? "4px -6px 0" : "4px 0 0", borderRadius: 4, transition: "background .5s" }}>
        {value}
      </div>
      {sub && <div style={{ fontSize: 11, color: "var(--text-3)", marginTop: 2 }} className="mono">{sub}</div>}
    </div>
  );
}

function RiskLadder({ entry, mark, stop }) {
  // Visual showing distance: stop ← entry ← mark, scaled to fit
  const range = entry - stop; // total risk distance
  const upRange = range * 1.5; // top of visual
  const total = range + upRange;
  const stopPct = (range / total) * 100;
  const entryPct = ((entry - stop) / total) * 100;
  const markPct = Math.max(0, Math.min(100, ((mark - stop) / total) * 100));
  return (
    <div style={{ position: "relative", width: 12, height: 60, background: "rgba(255,255,255,0.06)", borderRadius: 6 }}>
      {/* fill from stop to mark */}
      <div style={{
        position: "absolute", left: 0, right: 0, bottom: 0, top: (100 - markPct) + "%",
        background: mark >= entry ? "linear-gradient(180deg, var(--profit), rgba(25,229,166,0.2))" : "linear-gradient(180deg, var(--warn), rgba(245,166,35,0.2))",
        borderRadius: 6, transition: "top .4s",
      }} />
      {/* entry tick */}
      <div style={{
        position: "absolute", left: -6, right: -6, top: (100 - entryPct) + "%",
        height: 2, background: "var(--text-2)",
      }} title="Entry" />
      {/* mark dot */}
      <div style={{
        position: "absolute", left: -3, top: `calc(${100 - markPct}% - 4px)`,
        width: 18, height: 8, background: "var(--text)", borderRadius: 4, border: "2px solid var(--bg)",
        transition: "top .4s",
      }} title="Mark" />
    </div>
  );
}

// =================== Equity + daily P&L composite ===================
function EquityAndDailyCard({ accent, scenario }) {
  const [range, setRange] = ucS("1M");
  const points = { "1D": 24, "1W": 60, "1M": 90, "3M": 120, "1Y": 180, "All": 240 }[range];
  const driftMap = { winning: 0.0024, losing: -0.0015, volatile: 0.0008 };
  const equity = ucM(() => generateSeries(points, {
    seed: 11 + range.length * 7,
    start: 10000,
    drift: driftMap[scenario] || 0.002,
    vol: scenario === "volatile" ? 0.018 : 0.010,
  }), [points, range, scenario]);
  const benchmark = ucM(() => generateSeries(points, {
    seed: 99 + range.length,
    start: 10000,
    drift: 0.0008,
    vol: 0.014,
  }), [points, range]);
  const totalRet = ((equity[equity.length-1] - equity[0]) / equity[0]) * 100;
  const benchRet = ((benchmark[benchmark.length-1] - benchmark[0]) / benchmark[0]) * 100;

  return (
    <Card padded={false}>
      <div style={{ display: "flex", alignItems: "center", padding: "18px var(--pad) 0", gap: 16, flexWrap: "wrap" }}>
        <div style={{ flex: 1, minWidth: 200 }}>
          <div style={{ fontSize: 14, fontWeight: 600 }}>Equity curve</div>
          <div style={{ fontSize: 12, color: "var(--text-3)", marginTop: 4, display: "flex", alignItems: "center", gap: 14 }}>
            <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
              <span style={{ width: 10, height: 2, background: accent.base, borderRadius: 2 }} />
              Bot equity
            </span>
            <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
              <span style={{ width: 10, height: 2, backgroundImage: "repeating-linear-gradient(90deg, var(--text-3) 0 3px, transparent 3px 6px)" }} />
              BTC HODL
            </span>
          </div>
        </div>
        <div style={{ display: "flex", gap: 2, background: "rgba(255,255,255,0.04)", borderRadius: 8, padding: 3 }}>
          {["1D","1W","1M","3M","1Y","All"].map((r) => (
            <button key={r} onClick={() => setRange(r)} style={{
              padding: "6px 12px", borderRadius: 6, fontSize: 11, fontWeight: 500, border: 0,
              background: range === r ? "rgba(255,255,255,0.08)" : "transparent",
              color: range === r ? "var(--text)" : "var(--text-2)", fontFamily: "JetBrains Mono",
            }}>{r}</button>
          ))}
        </div>
      </div>
      <div style={{ padding: "10px var(--pad) 0" }}>
        <EquityCurve portfolio={equity} benchmark={benchmark} accent={accent.base} h={240}
          yLabel={(v) => "$" + (v / 1000).toFixed(1) + "k"} />
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", borderTop: "1px solid var(--line)" }}>
        <SummaryStat label="Net P&L" value={fmtUsd(equity[equity.length-1] - equity[0], { sign: true })} delta={totalRet >= 0 ? "profit" : "loss"} />
        <SummaryStat label="Return" value={fmtPct(totalRet)} delta={totalRet >= 0 ? "profit" : "loss"} />
        <SummaryStat label="vs HODL" value={fmtPct(totalRet - benchRet)} delta={totalRet - benchRet >= 0 ? "profit" : "loss"} />
        <SummaryStat label="Trades" value="248" delta="neutral" />
      </div>
    </Card>
  );
}

function SummaryStat({ label, value, delta }) {
  const color = delta === "profit" ? "var(--profit)" : delta === "loss" ? "var(--loss)" : "var(--text)";
  return (
    <div style={{ padding: "14px var(--pad)", borderRight: "1px solid var(--line)" }}>
      <div style={{ fontSize: 11, color: "var(--text-3)", letterSpacing: 0.5, textTransform: "uppercase" }}>{label}</div>
      <div className="mono" style={{ fontSize: 20, fontWeight: 600, marginTop: 4, color }}>{value}</div>
    </div>
  );
}

// =================== Daily P&L bars + key stats ===================
function DailyPnLCard({ accent }) {
  return (
    <Card title="Daily P&L · last 14 days" subtitle="UTC days · resets 00:00"
      right={<Badge variant="profit">7-day net: +$612.40</Badge>}>
      <DailyPnLBars data={DAILY_PNL} h={180} />
    </Card>
  );
}

// =================== Signal feed (live) ===================
function SignalFeedCard({ accent }) {
  return (
    <Card title="Recent signals" subtitle="TradingView webhook → bot"
      right={<a href="#" onClick={(e) => e.preventDefault()} style={{ color: accent.base, fontSize: 12, fontWeight: 500, textDecoration: "none" }}>Open log →</a>}
      padded={false}>
      <div style={{ maxHeight: 320, overflowY: "auto" }}>
        {SIGNALS.slice(0, 7).map((s, i) => <SignalRow key={s.id} sig={s} last={i === 6} />)}
      </div>
    </Card>
  );
}

function SignalRow({ sig, last }) {
  const statusCfg = {
    executed:     { c: "var(--profit)", lbl: "EXECUTED" },
    deduplicated: { c: "var(--text-3)", lbl: "DEDUP" },
    rejected:     { c: "var(--loss)",   lbl: "REJECTED" },
    stopped_out:  { c: "var(--warn)",   lbl: "STOPPED" },
  }[sig.status] || { c: "var(--text-3)", lbl: "—" };
  return (
    <div style={{
      display: "grid", gridTemplateColumns: "60px 60px 1fr auto auto",
      alignItems: "center", gap: 12, padding: "12px var(--pad)",
      borderBottom: last ? 0 : "1px solid var(--line)",
    }}>
      <div className="mono" style={{ fontSize: 11, color: "var(--text-3)" }}>{fmtRel(sig.t)}</div>
      <div>
        <span className="mono" style={{
          fontSize: 10, fontWeight: 700, padding: "2px 7px", borderRadius: 4,
          background: sig.side === "BUY" ? "rgba(25,229,166,0.12)" : "rgba(242,63,92,0.12)",
          color: sig.side === "BUY" ? "var(--profit)" : "var(--loss)",
        }}>{sig.side}</span>
      </div>
      <div style={{ minWidth: 0 }}>
        <div className="mono" style={{ fontSize: 12.5, fontWeight: 500 }}>BTC/USDT @ ${sig.price.toLocaleString()}</div>
        <div className="mono" style={{ fontSize: 10.5, color: "var(--text-3)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
          {sig.id} · {sig.reason || "ok"}
        </div>
      </div>
      <div style={{ textAlign: "right" }}>
        <div className="mono" style={{ fontSize: 10, color: statusCfg.c, fontWeight: 600, letterSpacing: 0.4 }}>● {statusCfg.lbl}</div>
        <div className="mono" style={{ fontSize: 10.5, color: "var(--text-3)", marginTop: 2 }}>{sig.latencyMs}ms</div>
      </div>
    </div>
  );
}

// =================== Bot config sidebar card ===================
function BotConfigCard({ accent, activeExchange = "binance", onSwap }) {
  const ex = EXCHANGES[activeExchange] || EXCHANGES.binance;
  const rows = [
    { l: "Pair",        v: "BTC/USDT" },
    { l: "Market",      v: "SPOT" },
    { l: "Timeframe",   v: "5m" },
    { l: "Strategy",    v: "EMA(9/21) + RSI(14)" },
    { l: "Signal src",  v: "TradingView · Pine v5" },
    { l: "Risk/trade",  v: "1.0% equity" },
    { l: "Stop loss",   v: "2.0% · " + ex.stopLoss },
    { l: "Taker fee",   v: ex.fees.taker.toFixed(2) + "%" },
    { l: "Take profit", v: "—", muted: true },
    { l: "Max position", v: "1 (no pyramid)" },
  ];
  return (
    <Card title="Bot configuration" subtitle={"MVP v1.1 · single pair · ACTIVE_EXCHANGE=" + ex.id}
      right={<a href="#set" style={{ color: accent.base, fontSize: 12, fontWeight: 500, textDecoration: "none" }}>Edit →</a>}>
      <div style={{
        marginBottom: 12, padding: "10px 12px", borderRadius: 10,
        background: "rgba(255,255,255,0.025)", border: "1px solid var(--line)",
        display: "flex", alignItems: "center", gap: 10,
      }}>
        <ex.Icon size={20} />
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 12.5, fontWeight: 500 }}>{ex.full}</div>
          <div className="mono" style={{ fontSize: 10.5, color: "var(--text-3)", marginTop: 1 }}>ccxt:{ex.ccxtId} · {ex.nativeSymbol} · {ex.rttMs}ms RTT</div>
        </div>
        <button onClick={onSwap} className="focus-ring" title="Switch exchange" style={{
          width: 28, height: 28, borderRadius: 7, border: "1px solid var(--line)",
          background: "rgba(255,255,255,0.02)", color: "var(--text-2)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
        }}><IconSwap size={14} /></button>
      </div>
      <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
        {rows.map((r) => (
          <div key={r.l} style={{ display: "flex", justifyContent: "space-between", fontSize: 12.5 }}>
            <span style={{ color: "var(--text-3)" }}>{r.l}</span>
            <span className="mono" style={{ color: r.muted ? "var(--text-3)" : "var(--text)", fontWeight: 500 }}>{r.v}</span>
          </div>
        ))}
      </div>
      <div style={{ marginTop: 16, padding: 12, borderRadius: 10, background: "rgba(245,166,35,0.08)", border: "1px solid rgba(245,166,35,0.20)", display: "flex", gap: 10, alignItems: "flex-start" }}>
        <IconAlert size={16} style={{ color: "var(--warn)", flex: "0 0 16px", marginTop: 1 }} />
        <div style={{ fontSize: 11.5, lineHeight: 1.5, color: "var(--text-2)" }}>
          Bot is running in <span style={{ color: "var(--warn)", fontWeight: 600 }}>{ex.testnet ? "TESTNET" : "PAPER"}</span> mode on {ex.name}.
          {ex.testnet ? " No real funds at risk." : " Kraken has no public testnet — paper-trade simulates against live market data."}
        </div>
      </div>
    </Card>
  );
}

// =================== Risk overview (compact) ===================
function RiskOverviewCard({ accent, scenario }) {
  const s = SCENARIOS[scenario] || SCENARIOS.winning;
  const maxDD = 15;
  const dailyMax = 3.0;
  const dailyUsed = s.dailyLoss;
  return (
    <Card title="Risk overview" subtitle="Pre-trade checks · auto-validated">
      <div style={{ display: "flex", flexDirection: "column", gap: 18 }}>
        <div>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 6 }}>
            <span style={{ fontSize: 12, color: "var(--text-2)" }}>Current drawdown</span>
            <span className="mono" style={{ fontSize: 12 }}>
              <span style={{ color: "var(--profit)", fontWeight: 600 }}>{s.drawdown}%</span>
              <span style={{ color: "var(--text-3)" }}> / {maxDD}% kill</span>
            </span>
          </div>
          <DrawdownGauge value={s.drawdown} max={maxDD} />
        </div>

        <div>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 6 }}>
            <span style={{ fontSize: 12, color: "var(--text-2)" }}>Daily loss budget</span>
            <span className="mono" style={{ fontSize: 12 }}>
              <span style={{ color: dailyUsed >= dailyMax * 0.7 ? "var(--warn)" : "var(--text)", fontWeight: 600 }}>−{dailyUsed.toFixed(2)}%</span>
              <span style={{ color: "var(--text-3)" }}> / −{dailyMax}% cap</span>
            </span>
          </div>
          <div style={{ position: "relative", height: 10, borderRadius: 999, background: "rgba(255,255,255,0.05)", overflow: "hidden" }}>
            <div style={{
              position: "absolute", inset: 0, width: ((dailyUsed/dailyMax) * 100) + "%",
              background: dailyUsed >= dailyMax * 0.7 ? "linear-gradient(90deg, var(--warn), var(--loss))" : "linear-gradient(90deg, var(--profit), var(--accent))",
              borderRadius: 999, transition: "width .5s",
            }} />
          </div>
          <div className="mono" style={{ fontSize: 10, color: "var(--text-3)", marginTop: 4 }}>resets 00:00 UTC · in 11h 42m</div>
        </div>

        <div style={{ borderTop: "1px solid var(--line)", paddingTop: 14, display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
          <Metric label="Win rate" value="66%" hint="last 30d" />
          <Metric label="Consec losses" value="1 / 5" hint="circuit @ 5" />
          <Metric label="Sharpe" value="1.84" hint="annualized" />
          <Metric label="Avg latency" value="486ms" hint="webhook→fill" />
        </div>
      </div>
    </Card>
  );
}

function Metric({ label, value, hint }) {
  return (
    <div>
      <div style={{ fontSize: 11, color: "var(--text-3)", letterSpacing: 0.5, textTransform: "uppercase" }}>{label}</div>
      <div className="mono" style={{ fontSize: 17, fontWeight: 600, marginTop: 4 }}>{value}</div>
      {hint && <div style={{ fontSize: 11, color: "var(--text-3)", marginTop: 2 }}>{hint}</div>}
    </div>
  );
}

// =================== /health endpoint preview ===================
function HealthEndpointCard({ activeExchange = "binance", scenario, mode = "testnet" }) {
  const ex = EXCHANGES[activeExchange] || EXCHANGES.binance;
  const s = SCENARIOS[scenario] || SCENARIOS.winning;
  return (
    <Card title="Health endpoint" subtitle="GET /health · used by Docker + monitors"
      right={<Badge variant="profit">200 OK</Badge>}>
      <pre style={{
        margin: 0, padding: "14px 16px", borderRadius: 8,
        background: "#06080F", border: "1px solid var(--line)",
        fontFamily: "JetBrains Mono", fontSize: 11.5, lineHeight: 1.65,
        color: "var(--text-2)", whiteSpace: "pre", overflow: "auto",
      }}>
{"{\n"}
{"  "}<span style={{ color: "#FCD34D" }}>"status"</span>:             <span style={{ color: "var(--profit)" }}>"ok"</span>,{"\n"}
{"  "}<span style={{ color: "#FCD34D" }}>"uptime_seconds"</span>:     <span style={{ color: "var(--accent)" }}>184302</span>,{"\n"}
{"  "}<span style={{ color: "#FCD34D" }}>"active_exchange"</span>:    <span style={{ color: "var(--profit)" }}>"{ex.id}"</span>,{"\n"}
{"  "}<span style={{ color: "#FCD34D" }}>"exchange_connected"</span>: <span style={{ color: "var(--profit)" }}>true</span>,{"\n"}
{"  "}<span style={{ color: "#FCD34D" }}>"last_signal_time"</span>:   <span style={{ color: "var(--profit)" }}>"2026-05-15T08:14:32Z"</span>,{"\n"}
{"  "}<span style={{ color: "#FCD34D" }}>"open_positions"</span>:     <span style={{ color: "var(--accent)" }}>1</span>,{"\n"}
{"  "}<span style={{ color: "#FCD34D" }}>"daily_pnl_pct"</span>:      <span style={{ color: s.changePct >= 0 ? "var(--profit)" : "var(--loss)" }}>{s.changePct.toFixed(2)}</span>,{"\n"}
{"  "}<span style={{ color: "#FCD34D" }}>"trading_mode"</span>:       <span style={{ color: mode === "live" ? "var(--loss)" : "var(--warn)" }}>"{mode}"</span>{"\n"}
{"}"}
      </pre>
      <div style={{ display: "flex", gap: 8, marginTop: 12 }}>
        <PrimaryBtn ghost icon={<IconCopy size={13} />} style={{ flex: 1, justifyContent: "center" }}>Copy curl</PrimaryBtn>
        <PrimaryBtn ghost icon={<IconRefresh size={13} />} style={{ flex: 1, justifyContent: "center" }}>Probe now</PrimaryBtn>
      </div>
    </Card>
  );
}

// =================== Exchange comparison + picker ===================
function ExchangeComparisonCard({ activeExchange = "binance", onSelect }) {
  const rows = [
    ["CCXT id",         (ex) => <span className="mono">{ex.ccxtId}</span>],
    ["Native symbol",   (ex) => <span className="mono">{ex.nativeSymbol}</span>],
    ["Maker / Taker",   (ex) => <span className="mono">{ex.fees.maker.toFixed(2)}% / {ex.fees.taker.toFixed(2)}%</span>],
    ["Rate limit",      (ex) => <span className="mono" style={{ fontSize: 11 }}>{ex.rateLimit}</span>],
    ["Stop loss",       (ex) => <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}><span style={{ width: 6, height: 6, borderRadius: 999, background: ex.oco ? "var(--profit)" : "var(--warn)" }} />{ex.stopLoss}</span>],
    ["Testnet",         (ex) => ex.testnet ? <Badge variant="profit">● available</Badge> : <Badge variant="warn">paper-trade only</Badge>],
    ["Round-trip",      (ex) => <span className="mono">{ex.rttMs}ms</span>],
  ];
  return (
    <Card title="Exchange routing" subtitle="Single-active per deploy · set via ACTIVE_EXCHANGE env">
      <div style={{ display: "grid", gridTemplateColumns: "140px 1fr 1fr", borderRadius: 10, overflow: "hidden", border: "1px solid var(--line)" }}>
        <div style={{ padding: "10px 12px", background: "rgba(255,255,255,0.02)", borderRight: "1px solid var(--line)", borderBottom: "1px solid var(--line)" }}></div>
        {["binance", "kraken"].map((k) => {
          const ex = EXCHANGES[k];
          const isActive = k === activeExchange;
          return (
            <button key={k} onClick={() => onSelect && onSelect(k)} className="focus-ring"
              style={{
                padding: "12px 14px", border: 0, textAlign: "left",
                background: isActive ? "var(--accent-soft)" : "rgba(255,255,255,0.02)",
                borderRight: k === "binance" ? "1px solid var(--line)" : 0,
                borderBottom: "1px solid var(--line)",
                color: "var(--text)", cursor: "pointer",
                display: "flex", alignItems: "center", gap: 10,
              }}>
              <ex.Icon size={20} />
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 13, fontWeight: 600 }}>{ex.name}</div>
                <div className="mono" style={{ fontSize: 10, color: "var(--text-3)", marginTop: 2, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{ex.full}</div>
              </div>
              {isActive
                ? <Badge variant="accent">● ACTIVE</Badge>
                : <span style={{ fontSize: 10, color: "var(--text-3)" }}>switch →</span>}
            </button>
          );
        })}
        {rows.map(([label, render], i) => (
          <React.Fragment key={label}>
            <div style={{ padding: "10px 12px", fontSize: 10.5, color: "var(--text-3)", letterSpacing: 0.4, textTransform: "uppercase", background: "rgba(255,255,255,0.012)", borderRight: "1px solid var(--line)", borderTop: "1px solid var(--line)" }}>{label}</div>
            {["binance", "kraken"].map((k) => {
              const ex = EXCHANGES[k];
              const isActive = k === activeExchange;
              return (
                <div key={k} style={{
                  padding: "10px 14px", fontSize: 12,
                  background: isActive ? "rgba(0,212,170,0.04)" : "transparent",
                  borderRight: k === "binance" ? "1px solid var(--line)" : 0,
                  borderTop: "1px solid var(--line)",
                  color: isActive ? "var(--text)" : "var(--text-2)",
                }}>{render(ex)}</div>
              );
            })}
          </React.Fragment>
        ))}
      </div>
    </Card>
  );
}

// =================== System health card ===================
function SystemHealthCard({ activeExchange = "binance" }) {
  const ex = EXCHANGES[activeExchange] || EXCHANGES.binance;
  const services = [
    { name: "FastAPI", status: "ok", val: "200 OK", sub: "8000/health · 12ms" },
    { name: ex.name + " API", status: "ok", val: "Connected", sub: "spot · " + (ex.testnet ? "testnet" : "paper") + " · ccxt:" + ex.ccxtId },
    { name: "TradingView", status: "ok", val: "Listening", sub: "/webhook · 10/min limit" },
    { name: "Telegram", status: "ok", val: "Bot active", sub: "@AutoTraderBot" },
    { name: "SQLite", status: "ok", val: "WAL mode", sub: "trades.db · 1.4 MB" },
  ];
  return (
    <Card title="System health" subtitle="Heartbeat every 30s · last 14s ago">
      <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
        {services.map((s) => (
          <div key={s.name} style={{ display: "flex", alignItems: "center", gap: 12, padding: "10px 12px", borderRadius: 8, background: "rgba(255,255,255,0.02)", border: "1px solid var(--line)" }}>
            <span className="pulse-dot" style={{ width: 8, height: 8, borderRadius: 999, background: "var(--profit)", color: "var(--profit)" }} />
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 12.5, fontWeight: 500 }}>{s.name}</div>
              <div className="mono" style={{ fontSize: 10.5, color: "var(--text-3)", marginTop: 1 }}>{s.sub}</div>
            </div>
            <div className="mono" style={{ fontSize: 11, color: "var(--profit)", fontWeight: 500 }}>{s.val}</div>
          </div>
        ))}
      </div>
    </Card>
  );
}

// =================== Dashboard page composition ===================
function DashboardPage({ scenario, accent, livePrices, activeExchange = "binance", setActiveExchange, mode = "testnet" }) {
  const s = SCENARIOS[scenario] || SCENARIOS.winning;
  const ex = EXCHANGES[activeExchange] || EXCHANGES.binance;
  const isUp = s.change24h >= 0;
  const [equity, dir] = livePrices
    ? useTicker(s.equity, { volatility: 0.0004, intervalMs: 2000, bias: isUp ? 0.0002 : -0.0002 })
    : [s.equity, 0];
  const animEquity = useCountUp(equity, 600);

  const modeTone = mode === "live" ? "loss" : mode === "paper" ? "accent" : "warn";

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--row-gap)" }}>
      {/* KPI strip */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(5, minmax(0, 1fr))", gap: "var(--row-gap)" }}>
        <Kpi
          label="Total equity"
          value={"$" + animEquity.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
          sub={(isUp ? "+" : "−") + "$" + Math.abs(s.change24h).toLocaleString() + " · " + fmtPct(s.changePct) + " · 24h"}
          tone={isUp ? "profit" : "loss"}
          icon={<ex.Icon size={16} />}
        />
        <Kpi label="Today P&L" value={fmtUsd(s.change24h, { sign: true })} sub={s.todayTrades + " trades · " + s.todayWin + " wins"} tone={isUp ? "profit" : "loss"} icon={<IconChart size={16} />} />
        <Kpi label="Open position" value="1 / 1" sub="BTC/USDT · LONG · entered 12s ago" icon={<IconBolt size={16} />} />
        <Kpi label="Drawdown" value={s.drawdown.toFixed(1) + "%"} sub={"max −15% · safe"} tone={s.drawdown < 10 ? "profit" : "warn"} icon={<IconShield size={16} />} />
        <Kpi label={"Mode · " + ex.name} value={mode.toUpperCase()} sub={ex.full + " · Dubai region"} tone={modeTone} icon={<IconKey size={16} />} />
      </div>

      {/* Open position */}
      <OpenPositionCard accent={accent} livePrices={livePrices} activeExchange={activeExchange} />

      {/* Equity + side col */}
      <div style={{ display: "grid", gridTemplateColumns: "minmax(0, 1.65fr) minmax(0, 1fr)", gap: "var(--row-gap)" }}>
        <EquityAndDailyCard accent={accent} scenario={scenario} />
        <RiskOverviewCard accent={accent} scenario={scenario} />
      </div>

      {/* Daily PnL bars + signal feed */}
      <div style={{ display: "grid", gridTemplateColumns: "minmax(0, 1.65fr) minmax(0, 1fr)", gap: "var(--row-gap)" }}>
        <DailyPnLCard accent={accent} />
        <SignalFeedCard accent={accent} />
      </div>

      {/* Exchange routing + health endpoint (new in v3) */}
      <div style={{ display: "grid", gridTemplateColumns: "minmax(0, 1.4fr) minmax(0, 1fr)", gap: "var(--row-gap)" }}>
        <ExchangeComparisonCard activeExchange={activeExchange} onSelect={setActiveExchange} />
        <HealthEndpointCard activeExchange={activeExchange} scenario={scenario} mode={mode} />
      </div>

      {/* Bot config + system health */}
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "var(--row-gap)" }}>
        <BotConfigCard accent={accent} activeExchange={activeExchange}
          onSwap={() => setActiveExchange && setActiveExchange(activeExchange === "binance" ? "kraken" : "binance")} />
        <SystemHealthCard activeExchange={activeExchange} />
      </div>
    </div>
  );
}

Object.assign(window, {
  DashboardPage, Kpi, OpenPositionCard, EquityAndDailyCard, DailyPnLCard,
  SignalFeedCard, BotConfigCard, RiskOverviewCard, SystemHealthCard, Metric,
  HealthEndpointCard, ExchangeComparisonCard,
});
