/* ============================================
   VELOX screens — part 2
   Positions, Algos, AlgoMonitor, Reports,
   Journal, Backtest, Settings
   ============================================ */

/* ---------------- POSITIONS — helpers ---------------- */
const parseOptionSym = (sym) => {
  if (!sym) return null;
  const spaced = sym.match(/^([A-Z&]+)\s+(\d+)\s+(CE|PE)$/i);
  if (spaced) return { underlying: spaced[1], strike: spaced[2], optType: spaced[3].toUpperCase() };
  const compact = sym.match(/^([A-Z&]+)(\d{4,6})(CE|PE)$/i);
  if (compact) return { underlying: compact[1], strike: compact[2], optType: compact[3].toUpperCase() };
  return null;
};

/* ---------------- PARTIAL EXIT MODAL ---------------- */
const PartialExitModal = ({ position, onClose, onConfirm }) => {
  const [qty, setQty] = React.useState(1);
  const maxQty = position.qty;
  const dir = position.side === "BUY" ? 1 : -1;
  const estPnl = ((position.ltp - position.avg) * qty * dir).toFixed(2);
  return (
    <div style={{ position: "fixed", inset: 0, background: "rgba(15,20,25,.55)", zIndex: 100, display: "grid", placeItems: "center", padding: 24 }} onClick={onClose}>
      <div style={{ background: "var(--surface)", borderRadius: 16, width: "100%", maxWidth: 400, boxShadow: "var(--shadow-lg)", padding: 24 }} onClick={e => e.stopPropagation()}>
        <div className="row-between" style={{ marginBottom: 16 }}>
          <div style={{ fontSize: 16, fontWeight: 700 }}>Partial Exit</div>
          <button className="btn-icon btn-ghost" onClick={onClose}><Icon name="x" size={16}/></button>
        </div>
        <div style={{ background: "var(--surface-2)", borderRadius: 10, padding: 12, marginBottom: 16, fontSize: 13 }}>
          <div style={{ fontWeight: 700, marginBottom: 4 }}>{position.sym}</div>
          <div className="row" style={{ gap: 12 }}>
            <span className={"chip " + (position.side === "BUY" ? "up" : "down")}>{position.side}</span>
            <span className="muted">Qty: {position.qty}</span>
            <span className="muted">Avg: {fmtNum(position.avg)}</span>
            <span className="muted">LTP: {fmtNum(position.ltp)}</span>
          </div>
        </div>
        <div className="field" style={{ marginBottom: 12 }}>
          <label className="field-label">Exit quantity (max {maxQty})</label>
          <input type="number" className="input mono" min={1} max={maxQty} value={qty} onChange={e => setQty(Math.max(1, Math.min(maxQty, +e.target.value)))}/>
        </div>
        <div style={{ background: "var(--surface-2)", borderRadius: 8, padding: "8px 12px", marginBottom: 16, fontSize: 12 }}>
          <span className="muted">Est. P&L at exit: </span>
          <span style={{ fontWeight: 700, color: +estPnl >= 0 ? "var(--up)" : "var(--down)" }}>{+estPnl >= 0 ? "+" : ""}{fmtINR(+estPnl, 2)}</span>
        </div>
        <div className="row" style={{ gap: 8, justifyContent: "flex-end" }}>
          <button className="btn btn-secondary" onClick={onClose}>Cancel</button>
          <button className="btn btn-sell" onClick={() => { onConfirm(qty); onClose(); }}>Exit {qty} lots</button>
        </div>
      </div>
    </div>
  );
};

/* ---------------- ADD MORE MODAL ---------------- */
const AddMoreModal = ({ position, onClose, onConfirm }) => {
  const [qty, setQty] = React.useState(1);
  return (
    <div style={{ position: "fixed", inset: 0, background: "rgba(15,20,25,.55)", zIndex: 100, display: "grid", placeItems: "center", padding: 24 }} onClick={onClose}>
      <div style={{ background: "var(--surface)", borderRadius: 16, width: "100%", maxWidth: 400, boxShadow: "var(--shadow-lg)", padding: 24 }} onClick={e => e.stopPropagation()}>
        <div className="row-between" style={{ marginBottom: 16 }}>
          <div style={{ fontSize: 16, fontWeight: 700 }}>Add to Position</div>
          <button className="btn-icon btn-ghost" onClick={onClose}><Icon name="x" size={16}/></button>
        </div>
        <div style={{ background: "var(--surface-2)", borderRadius: 10, padding: 12, marginBottom: 16, fontSize: 13 }}>
          <div style={{ fontWeight: 700, marginBottom: 4 }}>{position.sym}</div>
          <div className="row" style={{ gap: 12 }}>
            <span className={"chip " + (position.side === "BUY" ? "up" : "down")}>{position.side}</span>
            <span className="muted">Current qty: {position.qty}</span>
            <span className="muted">Avg: {fmtNum(position.avg)}</span>
          </div>
        </div>
        <div className="field" style={{ marginBottom: 16 }}>
          <label className="field-label">Additional quantity</label>
          <input type="number" className="input mono" min={1} value={qty} onChange={e => setQty(Math.max(1, +e.target.value))}/>
        </div>
        <div style={{ fontSize: 12, color: "var(--text-3)", marginBottom: 16 }}>
          Places a market order ({position.side}) for {qty} unit{qty !== 1 ? "s" : ""} of {position.sym}.
        </div>
        <div className="row" style={{ gap: 8, justifyContent: "flex-end" }}>
          <button className="btn btn-secondary" onClick={onClose}>Cancel</button>
          <button className={"btn " + (position.side === "BUY" ? "btn-buy" : "btn-sell")} onClick={() => { onConfirm(qty); onClose(); }}>
            {position.side} {qty} more
          </button>
        </div>
      </div>
    </div>
  );
};

/* ---------------- EQUITY TABLE ---------------- */
const EquityTable = ({ positions, onSquareOff, onPartialExit, onAddMore }) => {
  const [partialPos, setPartialPos] = React.useState(null);
  const [addMorePos, setAddMorePos] = React.useState(null);
  if (positions.length === 0) return <div style={{ textAlign: "center", padding: 32, color: "var(--text-3)" }}>No equity positions</div>;
  return (
    <>
      <div style={{ overflowX: "auto" }}>
        <table className="tbl">
          <thead>
            <tr>
              <th>Symbol</th><th>Side</th>
              <th className="num">Qty</th><th className="num">Avg</th><th className="num">LTP</th><th className="num">P&L</th>
              <th>Source</th><th></th>
            </tr>
          </thead>
          <tbody>
            {positions.map((p, i) => (
              <tr key={i}>
                <td><div style={{ fontWeight: 600 }}>{p.sym}</div></td>
                <td><span className={"chip " + (p.side === "BUY" ? "up" : "down")}>{p.side}</span></td>
                <td className="num">{p.qty}</td>
                <td className="num">{fmtNum(p.avg)}</td>
                <td className="num">{fmtNum(p.ltp)}</td>
                <td className="num" style={{ color: p.pnl >= 0 ? "var(--up)" : "var(--down)", fontWeight: 700 }}>{p.pnl >= 0 ? "+" : ""}{fmtNum(p.pnl, 2)}</td>
                <td>{p.algo === "Manual" ? <span className="chip">Manual</span> : <span className="chip brand"><Icon name="bot" size={11}/> {p.algo}</span>}</td>
                <td>
                  <div className="row" style={{ justifyContent: "flex-end", gap: 4 }}>
                    <button className="btn btn-secondary btn-sm" onClick={() => setAddMorePos(p)}>Add</button>
                    <button className="btn btn-secondary btn-sm" onClick={() => setPartialPos(p)}>Partial</button>
                    <button className="btn btn-sell btn-sm" onClick={() => onSquareOff(p._idx)}>Exit All</button>
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      {partialPos && <PartialExitModal position={partialPos} onClose={() => setPartialPos(null)} onConfirm={(qty) => onPartialExit(partialPos, qty)}/>}
      {addMorePos && <AddMoreModal position={addMorePos} onClose={() => setAddMorePos(null)} onConfirm={(qty) => onAddMore(addMorePos, qty)}/>}
    </>
  );
};

/* ---------------- OPTIONS TABLE ---------------- */
const OptionsTable = ({ positions, onSquareOff, onPartialExit, onAddMore }) => {
  const [partialPos, setPartialPos] = React.useState(null);
  const [addMorePos, setAddMorePos] = React.useState(null);
  if (positions.length === 0) return <div style={{ textAlign: "center", padding: 32, color: "var(--text-3)" }}>No options positions</div>;
  return (
    <>
      <div style={{ overflowX: "auto" }}>
        <table className="tbl">
          <thead>
            <tr>
              <th>Symbol</th><th>Expiry</th><th>Side</th>
              <th className="num">Qty</th><th className="num">Avg</th><th className="num">LTP</th><th className="num">P&L</th>
              <th>Source</th><th></th>
            </tr>
          </thead>
          <tbody>
            {positions.map((p, i) => {
              const parsed = parseOptionSym(p.sym);
              return (
                <tr key={i}>
                  <td>
                    {parsed ? (
                      <div className="row" style={{ gap: 4, flexWrap: "wrap" }}>
                        <span style={{ fontWeight: 700 }}>{parsed.underlying}</span>
                        <span className="chip">{parsed.strike}</span>
                        <span className={"chip " + (parsed.optType === "CE" ? "up" : "down")}>{parsed.optType}</span>
                      </div>
                    ) : <div style={{ fontWeight: 600 }}>{p.sym}</div>}
                  </td>
                  <td className="muted" style={{ fontSize: 12 }}>{p.expiry ?? "—"}</td>
                  <td><span className={"chip " + (p.side === "BUY" ? "up" : "down")}>{p.side}</span></td>
                  <td className="num">{p.qty}</td>
                  <td className="num">{fmtNum(p.avg)}</td>
                  <td className="num">{fmtNum(p.ltp)}</td>
                  <td className="num" style={{ color: p.pnl >= 0 ? "var(--up)" : "var(--down)", fontWeight: 700 }}>{p.pnl >= 0 ? "+" : ""}{fmtNum(p.pnl, 2)}</td>
                  <td>{p.algo === "Manual" ? <span className="chip">Manual</span> : <span className="chip brand"><Icon name="bot" size={11}/> {p.algo}</span>}</td>
                  <td>
                    <div className="row" style={{ justifyContent: "flex-end", gap: 4 }}>
                      <button className="btn btn-secondary btn-sm" onClick={() => setAddMorePos(p)}>Add</button>
                      <button className="btn btn-secondary btn-sm" onClick={() => setPartialPos(p)}>Partial</button>
                      <button className="btn btn-sell btn-sm" onClick={() => onSquareOff(p._idx)}>Exit All</button>
                    </div>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
      {partialPos && <PartialExitModal position={partialPos} onClose={() => setPartialPos(null)} onConfirm={(qty) => onPartialExit(partialPos, qty)}/>}
      {addMorePos && <AddMoreModal position={addMorePos} onClose={() => setAddMorePos(null)} onConfirm={(qty) => onAddMore(addMorePos, qty)}/>}
    </>
  );
};

/* ---------------- POSITIONS ---------------- */
const PositionsScreen = ({ positions, onSquareOff, onSquareOffAll, addToast, margin, onPartialExit, onAddMore }) => {
  const equityPositions = positions.map((p, i) => ({ ...p, _idx: i })).filter(p => p.type === "EQ" || p.type !== "OPT");
  const optionPositions = positions.map((p, i) => ({ ...p, _idx: i })).filter(p => p.type === "OPT");
  const defaultPosTab = optionPositions.length > 0 ? "options" : "equity";
  const [posTab, setPosTab] = React.useState(defaultPosTab);
  const [tab, setTab] = React.useState("open");
  const [closedOrders, setClosedOrders] = React.useState(null); // null = not loaded
  const [closedLoading, setClosedLoading] = React.useState(false);
  const totalPnl = positions.reduce((s, p) => s + p.pnl, 0);

  const marginUsed = margin?.used ?? 0;
  const marginAvailable = margin?.available ?? 0;

  const handleTabChange = async (t) => {
    setTab(t);
    if (t === "closed" && closedOrders === null && !closedLoading) {
      setClosedLoading(true);
      try {
        const result = await API.getOrders();
        const orders = Array.isArray(result?.data) ? result.data : (Array.isArray(result) ? result : []);
        setClosedOrders(orders);
      } catch (e) {
        setClosedOrders([]);
      } finally {
        setClosedLoading(false);
      }
    }
  };
  const profitable = positions.filter(p => p.pnl >= 0).length;

  return (
    <div className="page">
      <div className="row-between" style={{ marginBottom: 16 }}>
        <div>
          <h2 className="page-title">Positions</h2>
          <div className="page-sub">{positions.length} open · {profitable} in profit · Net P&L {fmtINR(totalPnl)}</div>
        </div>
        <div className="row" style={{ gap: 8 }}>
          <button className="btn btn-secondary"><Icon name="refresh" size={14}/> Refresh</button>
          {positions.length > 0 && <button className="btn btn-sell" onClick={onSquareOffAll}>Square off all</button>}
        </div>
      </div>

      <div className="grid" style={{ gridTemplateColumns: "repeat(4, 1fr)", marginBottom: 16 }}>
        <div className="kpi">
          <div className="kpi-label">Net P&L</div>
          <div className="kpi-value" style={{ color: totalPnl >= 0 ? "var(--up)" : "var(--down)" }}>
            {totalPnl >= 0 ? "+" : ""}{fmtINR(totalPnl)}
          </div>
          <div className="kpi-foot muted">Realized + unrealized</div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Open positions</div>
          <div className="kpi-value">{positions.length}</div>
          <div className="kpi-foot up">{profitable} profitable · {positions.length - profitable} in loss</div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Margin used</div>
          <div className="kpi-value">{fmtINR(marginUsed)}</div>
          <div className="kpi-foot muted">of {fmtINR(marginAvailable)} available</div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Algo-managed</div>
          <div className="kpi-value">{positions.filter(p => p.algo !== "Manual").length}</div>
          <div className="kpi-foot muted">{positions.filter(p => p.algo === "Manual").length} manual</div>
        </div>
      </div>

      <div className="tabs">
        <div className={"tab " + (tab === "open" ? "active" : "")} onClick={() => handleTabChange("open")}>Open ({positions.length})</div>
        <div className={"tab " + (tab === "closed" ? "active" : "")} onClick={() => handleTabChange("closed")}>Closed today{closedOrders !== null ? ` (${closedOrders.length})` : ""}</div>
      </div>

      {tab === "open" && (
        <>
          <div className="tabs" style={{ marginBottom: 0, borderBottom: "none" }}>
            <div className={"tab " + (posTab === "equity" ? "active" : "")} onClick={() => setPosTab("equity")}>
              Equity ({equityPositions.length})
            </div>
            <div className={"tab " + (posTab === "options" ? "active" : "")} onClick={() => setPosTab("options")}>
              Options ({optionPositions.length})
            </div>
          </div>
          <div className="card" style={{ padding: 0, overflow: "hidden" }}>
            {posTab === "equity" && <EquityTable positions={equityPositions} onSquareOff={onSquareOff} onPartialExit={onPartialExit} onAddMore={onAddMore}/>}
            {posTab === "options" && <OptionsTable positions={optionPositions} onSquareOff={onSquareOff} onPartialExit={onPartialExit} onAddMore={onAddMore}/>}
          </div>
        </>
      )}

      {tab === "closed" && (
        <div className="card" style={{ padding: closedLoading || !closedOrders?.length ? 32 : 0, overflow: "hidden", textAlign: closedLoading || !closedOrders?.length ? "center" : "left" }}>
          {closedLoading && <div className="muted" style={{ fontSize: 13 }}>Loading orders…</div>}
          {!closedLoading && closedOrders !== null && closedOrders.length === 0 && (
            <div className="muted" style={{ fontSize: 13 }}>No orders found for today</div>
          )}
          {!closedLoading && closedOrders !== null && closedOrders.length > 0 && (
            <div style={{ overflowX: "auto" }}>
              <table className="tbl">
                <thead>
                  <tr>
                    <th>Order No</th><th>Symbol</th><th>Type</th><th>Side</th>
                    <th className="num">Qty</th><th className="num">Price</th>
                    <th>Status</th><th>Time</th>
                  </tr>
                </thead>
                <tbody>
                  {closedOrders.map((o, i) => (
                    <tr key={i}>
                      <td className="mono muted" style={{ fontSize: 12 }}>{o.nOrdNo}</td>
                      <td><div style={{ fontWeight: 600 }}>{o.trdSym}</div></td>
                      <td><span className="chip">{o.exTyp}</span></td>
                      <td><span className={"chip " + (o.trnsTp === "B" ? "up" : "down")}>{o.trnsTp === "B" ? "BUY" : "SELL"}</span></td>
                      <td className="num">{o.qty}</td>
                      <td className="num">{fmtNum(o.prc)}</td>
                      <td><span className="chip">{o.ordSt}</span></td>
                      <td className="muted" style={{ fontSize: 12 }}>{o.hsUpTm}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}
        </div>
      )}
    </div>
  );
};

/* ---------------- ALGOS LIBRARY ---------------- */
const WorkerStatusBanner = ({ ping }) => {
  const [now, setNow] = React.useState(Date.now());
  React.useEffect(() => {
    const t = setInterval(() => setNow(Date.now()), 5000);
    return () => clearInterval(t);
  }, []);

  if (!ping) {
    return (
      <div style={{ display: "flex", alignItems: "center", gap: 10, padding: "10px 16px", borderRadius: 10, marginBottom: 16, background: "var(--surface-2)", border: "1px solid var(--border)" }}>
        <span style={{ width: 8, height: 8, borderRadius: "50%", background: "var(--text-3)", display: "inline-block" }}/>
        <span style={{ fontSize: 13, color: "var(--text-3)" }}>Worker not seen yet — start it with <code style={{ fontSize: 12 }}>npm run dev</code> in the worker folder</span>
      </div>
    );
  }

  const lastPingMs = ping.lastPing?.toMillis?.() ?? ping.lastPing?.seconds * 1000 ?? 0;
  const ageSec = Math.floor((now - lastPingMs) / 1000);
  const isOnline = ping.online && ageSec < 60;
  const runningCount = ping.runningCount ?? 0;

  return (
    <div style={{
      display: "flex", alignItems: "center", gap: 12, padding: "10px 16px", borderRadius: 10,
      marginBottom: 16,
      background: isOnline ? "color-mix(in srgb, var(--up) 8%, var(--surface-1))" : "color-mix(in srgb, var(--down) 8%, var(--surface-1))",
      border: `1px solid ${isOnline ? "color-mix(in srgb, var(--up) 30%, transparent)" : "color-mix(in srgb, var(--down) 30%, transparent)"}`,
    }}>
      <span style={{ width: 8, height: 8, borderRadius: "50%", background: isOnline ? "var(--up)" : "var(--down)", display: "inline-block", flexShrink: 0 }}/>
      <span style={{ fontSize: 13, fontWeight: 600, color: isOnline ? "var(--up)" : "var(--down)" }}>
        Worker {isOnline ? "Online" : "Offline"}
      </span>
      <span style={{ fontSize: 12, color: "var(--text-2)" }}>
        {isOnline
          ? `${runningCount} strateg${runningCount === 1 ? "y" : "ies"} running · last ping ${ageSec}s ago`
          : `Last seen ${ageSec < 3600 ? ageSec + "s ago" : "over 1h ago"} · restart worker`}
      </span>
    </div>
  );
};

const AlgosScreen = ({ algos, onConfigure, onToggle, workerPing, onOpenLive }) => {
  const [filter, setFilter] = React.useState("all");

  // Sort by `order` field (Firestore) — falls back to catalog position
  const sorted = React.useMemo(() => {
    return [...algos].sort((a, b) => {
      const ao = a.order ?? 999;
      const bo = b.order ?? 999;
      if (ao !== bo) return ao - bo;
      return (a.id ?? "").localeCompare(b.id ?? "");
    });
  }, [algos]);

  const filtered = sorted.filter(a => filter === "all" || (filter === "running" ? a.running : !a.running));

  const move = async (idx, dir) => {
    const newIdx = idx + dir;
    if (newIdx < 0 || newIdx >= sorted.length) return;
    const a = sorted[idx];
    const b = sorted[newIdx];
    // Swap order values — uses index positions to ensure all docs get a numeric order
    const aOrder = a.order ?? idx;
    const bOrder = b.order ?? newIdx;
    await Promise.all([
      API.saveStrategy(a.id, { order: bOrder }),
      API.saveStrategy(b.id, { order: aOrder }),
    ]);
  };

  return (
    <div className="page">
      <WorkerStatusBanner ping={workerPing}/>
      <div className="row-between" style={{ marginBottom: 16 }}>
        <div>
          <h2 className="page-title">Algorithm Library</h2>
          <div className="page-sub">6 strategies · {algos.filter(a => a.running).length} active right now</div>
        </div>
        <div className="row" style={{ gap: 6 }}>
          <button className={"chip " + (filter === "all" ? "brand" : "")} onClick={() => setFilter("all")}>All</button>
          <button className={"chip " + (filter === "running" ? "brand" : "")} onClick={() => setFilter("running")}>Running</button>
          <button className={"chip " + (filter === "stopped" ? "brand" : "")} onClick={() => setFilter("stopped")}>Stopped</button>
        </div>
      </div>

      <div className="grid" style={{ gridTemplateColumns: "repeat(auto-fill, minmax(360px, 1fr))", gap: 16 }}>
        {filtered.map((a, i) => {
          // Index of `a` in the unfiltered sorted list — used for reorder math
          const sortedIdx = sorted.findIndex(x => x.id === a.id);
          const isFirst = sortedIdx === 0;
          const isLast  = sortedIdx === sorted.length - 1;
          return (
          <div key={a.id} className="card" style={{ position: "relative", padding: 0, overflow: "hidden" }}>
            {/* Top strip */}
            <div style={{
              padding: "16px 18px",
              background: a.running ? "linear-gradient(135deg, var(--brand-soft), transparent)" : "var(--surface-2)",
              borderBottom: "1px solid var(--border)"
            }}>
              <div className="row-between">
                <div className="row" style={{ gap: 12 }}>
                  <div style={{
                    width: 44, height: 44, borderRadius: 12,
                    background: a.running ? "var(--brand)" : "var(--surface-3)",
                    color: a.running ? "white" : "var(--text-2)",
                    display: "grid", placeItems: "center",
                    fontSize: 22, fontWeight: 700,
                  }}>{a.icon}</div>
                  <div>
                    <div style={{ fontSize: 15, fontWeight: 700, letterSpacing: "-0.01em" }}>{a.name}</div>
                    <div style={{ fontSize: 12, color: "var(--text-3)" }}>{a.tagline}</div>
                  </div>
                </div>
                <div className="row" style={{ gap: 4, alignItems: "center" }}>
                  {/* Reorder controls */}
                  <button title="Move up" disabled={isFirst}
                    onClick={() => move(sortedIdx, -1)}
                    style={{ background: "transparent", border: "1px solid var(--border)", borderRadius: 6, width: 24, height: 24, cursor: isFirst ? "not-allowed" : "pointer", opacity: isFirst ? 0.3 : 1, color: "var(--text-2)", fontSize: 12, padding: 0 }}>↑</button>
                  <button title="Move down" disabled={isLast}
                    onClick={() => move(sortedIdx, 1)}
                    style={{ background: "transparent", border: "1px solid var(--border)", borderRadius: 6, width: 24, height: 24, cursor: isLast ? "not-allowed" : "pointer", opacity: isLast ? 0.3 : 1, color: "var(--text-2)", fontSize: 12, padding: 0 }}>↓</button>
                  {a.running ? (
                    <span className="chip up" style={{ marginLeft: 4 }}>
                      <span className="pulse" style={{ width: 6, height: 6, background: "var(--up)", borderRadius: "50%" }}/>
                      LIVE {(a.runningConfigCount ?? 0) > 1 ? `× ${a.runningConfigCount}` : ""}
                    </span>
                  ) : (
                    <span className="chip" style={{ marginLeft: 4 }}>
                      {(a.configs?.length ?? 0) > 0 ? `${a.configs.length} config${a.configs.length > 1 ? "s" : ""}` : "No configs"}
                    </span>
                  )}
                </div>
              </div>
            </div>

            <div style={{ padding: "14px 18px" }}>
              <p style={{ margin: 0, fontSize: 13, color: "var(--text-2)", lineHeight: 1.55, marginBottom: 14, minHeight: 60 }}>
                {a.desc}
              </p>

              <div className="grid" style={{ gridTemplateColumns: "1fr 1fr 1fr", gap: 8, marginBottom: 14 }}>
                <Stat label="Win rate" value={a.winRate + "%"}/>
                <Stat label="Avg return" value={a.avgReturn} accent="up"/>
                <Stat label="Drawdown" value={a.drawdown} accent="down"/>
              </div>

              <div className="row-between" style={{ fontSize: 12, color: "var(--text-3)", marginBottom: 14 }}>
                <span><Icon name="shield" size={12}/> {a.risk} risk</span>
                <span>{a.bestFor}</span>
              </div>

              {a.running && (
                <div style={{ background: "var(--surface-2)", borderRadius: 10, padding: "10px 12px", marginBottom: 14 }}>
                  <div className="row-between">
                    <div>
                      <div style={{ fontSize: 11, color: "var(--text-3)", fontWeight: 600 }}>Today</div>
                      <div className="mono" style={{ fontSize: 16, fontWeight: 700, color: "var(--up)" }}>+{fmtNum(a.pnl, 0)}</div>
                    </div>
                    <div style={{ textAlign: "right" }}>
                      <div style={{ fontSize: 11, color: "var(--text-3)", fontWeight: 600 }}>Auto-trades</div>
                      <div className="mono" style={{ fontSize: 16, fontWeight: 700 }}>{a.autoTrades}</div>
                    </div>
                  </div>
                  {a.config?.pickedOptions?.length > 0 && (
                    <div style={{ marginTop: 8 }}>
                      <div style={{ fontSize: 11, color: "var(--text-3)", fontWeight: 600, marginBottom: 4 }}>Watching</div>
                      <div className="row" style={{ flexWrap: "wrap", gap: 4 }}>
                        {a.config.pickedOptions.map(o => (
                          <span key={o.sym} className="chip" style={{ fontSize: 10 }}>{o.sym}</span>
                        ))}
                      </div>
                    </div>
                  )}
                </div>
              )}

              <div className="row" style={{ gap: 8 }}>
                <button className="btn btn-secondary btn-sm" style={{ flex: 1, justifyContent: "center" }} onClick={() => onConfigure(a)}>
                  <Icon name="settings" size={13}/> Configure
                </button>
                {["max-profit", "momentum-burst", "option-dip-buyer", "candle-burst"].includes(a.id) && onOpenLive && (
                  <button className="btn btn-secondary btn-sm" style={{ flex: 1, justifyContent: "center" }} onClick={() => onOpenLive(a.id)}>
                    <Icon name="activity" size={13}/> Live
                  </button>
                )}
                <button className={"btn btn-sm " + (a.running ? "btn-sell" : "btn-primary")} style={{ flex: 1, justifyContent: "center" }}
                  onClick={() => onToggle(a.id)}>
                  {a.running ? <><Icon name="pause" size={13}/> Stop</> : <><Icon name="play" size={13}/> Start</>}
                </button>
              </div>
            </div>
          </div>
          );
        })}
      </div>
    </div>
  );
};

const Stat = ({ label, value, accent }) => (
  <div style={{ background: "var(--surface-2)", padding: "8px 10px", borderRadius: 8 }}>
    <div style={{ fontSize: 10, fontWeight: 700, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: ".04em" }}>{label}</div>
    <div className="mono" style={{
      fontSize: 13, fontWeight: 700,
      color: accent === "up" ? "var(--up)" : accent === "down" ? "var(--down)" : "var(--text)",
    }}>{value}</div>
  </div>
);

/* ---------------- OPTIONS PICKER WIDGET ---------------- */
const StockPickerWidget = ({ pickedStocks, onChange }) => {
  const [search, setSearch] = React.useState("");
  const [scripReady, setScripReady] = React.useState(() => API.searchScrips("A", 1).length > 0);

  React.useEffect(() => {
    if (scripReady) return;
    const id = setInterval(() => {
      if (API.searchScrips("A", 1).length > 0) { setScripReady(true); clearInterval(id); }
    }, 1000);
    return () => clearInterval(id);
  }, [scripReady]);

  const results = React.useMemo(() => {
    const q = search.trim();
    if (q.length < 2) return [];
    return API.searchScrips(q, 15).filter(s => s.exch === "nse_cm");
  }, [search, scripReady]);

  const addStock = (s) => {
    if (pickedStocks.find(p => p.sym === s.sym)) return;
    onChange([...pickedStocks, { sym: s.sym, name: s.name, token: s.token, exch: s.exch }]);
  };
  const removeStock = (sym) => onChange(pickedStocks.filter(s => s.sym !== sym));

  return (
    <div className="card" style={{ background: "var(--surface-2)", padding: 12 }}>
      {pickedStocks.length > 0 && (
        <div className="row" style={{ flexWrap: "wrap", gap: 6, marginBottom: 10 }}>
          {pickedStocks.map(s => (
            <div key={s.sym} className="chip brand" style={{ display: "flex", alignItems: "center", gap: 4 }}>
              {s.sym}
              <button style={{ background: "none", border: "none", cursor: "pointer", padding: 0, color: "inherit", lineHeight: 1 }}
                onClick={() => removeStock(s.sym)}>×</button>
            </div>
          ))}
        </div>
      )}
      <input className="input" placeholder={scripReady ? "Search NSE stock (min 2 chars)…" : "Loading scrip master…"}
        disabled={!scripReady}
        value={search} onChange={e => setSearch(e.target.value)}
        style={{ marginBottom: 8, fontSize: 12 }}/>
      {results.length > 0 && (
        <div style={{ maxHeight: 200, overflowY: "auto", border: "1px solid var(--border)", borderRadius: 8 }}>
          {results.map(s => (
            <div key={s.token} style={{
              padding: "7px 12px", cursor: "pointer", fontSize: 12,
              borderBottom: "1px solid var(--border)",
              display: "flex", justifyContent: "space-between", alignItems: "center",
              background: pickedStocks.find(p => p.sym === s.sym) ? "var(--brand-soft)" : "",
            }}
              onMouseEnter={e => e.currentTarget.style.background = "var(--surface)"}
              onMouseLeave={e => e.currentTarget.style.background = pickedStocks.find(p => p.sym === s.sym) ? "var(--brand-soft)" : ""}
              onClick={() => addStock(s)}>
              <span><span style={{ fontWeight: 600 }}>{s.sym}</span> <span style={{ color: "var(--text-3)", fontSize: 11 }}>{s.name}</span></span>
              <span className="chip" style={{ fontSize: 10 }}>+ Add</span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
};

const OptionsPickerWidget = ({ underlying, pickedOptions, onChange }) => {
  const [expiries, setExpiries] = React.useState([]);
  const [selExpiry, setSelExpiry] = React.useState("");
  const [optType, setOptType] = React.useState("CE");
  const [strikeSearch, setStrikeSearch] = React.useState("");
  const [results, setResults] = React.useState([]);

  // Load expiries — trigger scrip master load if F&O cache is empty
  React.useEffect(() => {
    let cancelled = false;
    const load = async () => {
      let exps = typeof API.getOptionExpiries === "function" ? API.getOptionExpiries(underlying) : [];
      if (exps.length === 0 && typeof API.loadScripMaster === "function") {
        await API.loadScripMaster();
        exps = API.getOptionExpiries(underlying);
      }
      if (cancelled) return;
      setExpiries(exps);
      setSelExpiry(exps[0] ?? "");
    };
    load();
    return () => { cancelled = true; };
  }, [underlying]);

  // Search options when inputs change
  React.useEffect(() => {
    if (!selExpiry) return;
    const typeArg = optType === "Both" ? undefined : optType;
    const opts = typeof API.searchOptions === "function"
      ? API.searchOptions(underlying, selExpiry, typeArg, 500)
      : [];
    // Filter by strike search
    const filtered = strikeSearch
      ? opts.filter(o => o.sym.includes(strikeSearch))
      : opts;
    setResults(filtered.slice(0, 30));
  }, [underlying, selExpiry, optType, strikeSearch]);

  const addOption = (opt) => {
    if (pickedOptions.find(p => p.sym === opt.sym)) return;
    onChange([...pickedOptions, opt]);
  };

  const removeOption = (sym) => {
    onChange(pickedOptions.filter(p => p.sym !== sym));
  };

  return (
    <div>
      {/* Picked options chips */}
      {pickedOptions.length > 0 && (
        <div className="row" style={{ flexWrap: "wrap", gap: 6, marginBottom: 10 }}>
          {pickedOptions.map(o => (
            <div key={o.sym} className="chip brand" style={{ display: "flex", alignItems: "center", gap: 4 }}>
              {o.sym}
              <button style={{ background: "none", border: "none", cursor: "pointer", padding: 0, color: "inherit", lineHeight: 1 }}
                onClick={() => removeOption(o.sym)}>×</button>
            </div>
          ))}
        </div>
      )}

      {/* Expiry + CE/PE selector */}
      <div className="row" style={{ gap: 8, marginBottom: 8 }}>
        <select className="input" style={{ flex: 1, padding: "6px 8px", fontSize: 12 }}
          value={selExpiry} onChange={e => setSelExpiry(e.target.value)}>
          {expiries.length === 0 && <option value="">Loading expiries…</option>}
          {expiries.map(e => <option key={e} value={e}>{typeof API.formatExpiry === "function" ? API.formatExpiry(e) : e}</option>)}
        </select>
        <div className="row" style={{ gap: 4 }}>
          {["CE", "PE", "Both"].map(t => (
            <button key={t} className={"chip " + (optType === t ? "brand" : "")}
              onClick={() => setOptType(t)} style={{ fontSize: 11 }}>
              {t}
            </button>
          ))}
        </div>
      </div>

      {/* Strike search */}
      <input className="input" placeholder="Filter by strike (e.g. 24500)…"
        value={strikeSearch} onChange={e => setStrikeSearch(e.target.value)}
        style={{ marginBottom: 8, fontSize: 12 }}/>

      {/* Results list */}
      {results.length > 0 && (
        <div style={{ maxHeight: 160, overflowY: "auto", border: "1px solid var(--border)", borderRadius: 8 }}>
          {results.map((o, i) => (
            <div key={i} style={{
              padding: "7px 12px", cursor: "pointer", fontSize: 12,
              borderBottom: "1px solid var(--border)",
              display: "flex", justifyContent: "space-between", alignItems: "center",
              background: pickedOptions.find(p => p.sym === o.sym) ? "var(--brand-soft)" : "",
            }}
              onMouseEnter={e => e.currentTarget.style.background = "var(--surface-2)"}
              onMouseLeave={e => e.currentTarget.style.background = pickedOptions.find(p => p.sym === o.sym) ? "var(--brand-soft)" : ""}
              onClick={() => addOption(o)}>
              <span style={{ fontWeight: 600 }}>{o.sym}</span>
              <span className="chip" style={{ fontSize: 10 }}>+ Add</span>
            </div>
          ))}
        </div>
      )}

      {expiries.length === 0 && results.length === 0 && (
        <div style={{ fontSize: 11, color: "var(--text-3)" }}>
          Loading F&O scrip master…
        </div>
      )}
    </div>
  );
};

/* ---------------- ALGO CONFIGURE MODAL ---------------- */
const AlgoConfigModal = ({ algo, onClose, onStart, addToast }) => {
  // Saved configs (subcollection) — fetched on mount
  const [configs, setConfigs] = React.useState([]);
  const [selectedConfigId, setSelectedConfigId] = React.useState(null);
  const [configName, setConfigName] = React.useState("Untitled");

  React.useEffect(() => {
    const unsub = API.listenConfigs(algo.id, list => {
      setConfigs(list);
      // Auto-select the first config if none picked yet
      setSelectedConfigId(prev => prev ?? list[0]?.id ?? null);
    });
    return () => unsub();
  }, [algo.id]);

  // When user picks a different config, reload form values from it
  const selectedConfig = configs.find(c => c.id === selectedConfigId);
  const cfgSource = selectedConfig?.config ?? algo.config ?? {};
  const pick = (k, def) => cfgSource[k] ?? algo[k] ?? def;

  const [form, setForm] = React.useState({
    instrument:        pick("instrument", "NIFTY"),
    capital:           pick("capital", 50000),
    sl:                pick("sl", 20),
    tp:                pick("tp", 40),
    pickedOptions:     pick("pickedOptions", []),
    callRange:         pick("callRange", { min: 24700, max: 24900 }),
    putRange:          pick("putRange",  { min: 24700, max: 24900 }),
    momentumThreshold: pick("momentumThreshold", 0.5),
    decayWindow:       pick("decayWindow", 45),
    // MaxProfit
    pickedStocks:          pick("pickedStocks", []),
    triggerStockCount:     pick("triggerStockCount", 3),
    triggerThresholdPct:   pick("triggerThresholdPct", 0.2),
    observationWindowSec:  pick("observationWindowSec", 45),
    stopLossPct:           pick("stopLossPct", 15),
    timeStopSec:           pick("timeStopSec", 90),
    limitProfitPct:        pick("limitProfitPct", 2),
    optionBudget:          pick("optionBudget", 10000),
    dummyMode:             pick("dummyMode", true),  // default ON for safety
    // CandleBurst
    candleSec:             pick("candleSec", 60),
    exitMode:              pick("exitMode", "timeout"),   // "timeout" | "pattern-trail"
    trailingStopPct:       pick("trailingStopPct", 30),
  });

  const update = (k, v) => setForm(p => ({ ...p, [k]: v }));

  // When user picks a different saved config, hydrate the form from it
  React.useEffect(() => {
    if (!selectedConfig) return;
    const c = selectedConfig.config ?? {};
    setConfigName(selectedConfig.name ?? "Untitled");
    setForm(prev => ({
      ...prev,
      // copy any field present on the saved config
      ...Object.fromEntries(Object.entries(c)),
    }));
  }, [selectedConfigId]);  // eslint-disable-line react-hooks/exhaustive-deps

  const onSave = async (opts = {}) => {
    const formWithMeta = { ...form, _configId: selectedConfigId, _configName: configName };
    const savedId = await onStart(algo, formWithMeta, opts);
    if (opts.asCopy && savedId) setSelectedConfigId(savedId);
  };

  const onDelete = async () => {
    if (!selectedConfigId) return;
    if (!confirm(`Delete config "${configName}"? This stops the strategy and removes it.`)) return;
    try {
      await API.setConfigRunning(algo.id, selectedConfigId, false);
      await API.deleteConfig(algo.id, selectedConfigId);
      addToast({ type: "warn", title: "Config deleted", body: configName });
      setSelectedConfigId(null);
    } catch (e) {
      addToast({ type: "warn", title: "Delete failed", body: e?.message ?? String(e) });
    }
  };

  const onStopConfig = async () => {
    if (!selectedConfigId) return;
    await API.setConfigRunning(algo.id, selectedConfigId, false);
    addToast({ type: "warn", title: "Stopped", body: configName });
  };

  const onNewConfig = () => {
    setSelectedConfigId(null);
    setConfigName("New config");
    // keep form values as-is so user can tweak from current state
  };

  return (
    <div style={{
      position: "fixed", inset: 0, background: "rgba(15,20,25,.55)", zIndex: 100,
      display: "grid", placeItems: "center", padding: 24, animation: "toastIn .2s",
    }} onClick={onClose}>
      <div style={{ background: "var(--surface)", borderRadius: 16, width: "100%", maxWidth: 560, maxHeight: "92vh", overflow: "auto", boxShadow: "var(--shadow-lg)" }}
        onClick={e => e.stopPropagation()}>
        <div style={{ padding: "20px 22px", borderBottom: "1px solid var(--border)" }}>
          <div className="row-between">
            <div className="row" style={{ gap: 12 }}>
              <div style={{ width: 40, height: 40, borderRadius: 11, background: "var(--brand)", color: "white", display: "grid", placeItems: "center", fontSize: 20, fontWeight: 700 }}>{algo.icon}</div>
              <div>
                <div style={{ fontSize: 16, fontWeight: 700 }}>Configure {algo.name}</div>
                <div style={{ fontSize: 12, color: "var(--text-3)" }}>{algo.tagline}</div>
              </div>
            </div>
            <button className="btn-icon btn-ghost" onClick={onClose}><Icon name="x" size={16}/></button>
          </div>
        </div>

        <div style={{ padding: "20px 22px" }}>
          {/* Configurations picker — list of saved configs + new/duplicate/delete */}
          <div className="card" style={{ padding: "12px 14px", marginBottom: 14, background: "var(--surface-2)" }}>
            <div className="row-between" style={{ marginBottom: 8 }}>
              <div style={{ fontSize: 12, fontWeight: 700, color: "var(--text-2)" }}>
                Configurations ({configs.length})
              </div>
              <div className="row" style={{ gap: 6 }}>
                <button className="chip" onClick={onNewConfig} title="Create new config from current form values">+ New</button>
                {selectedConfigId && (
                  <button className="chip" onClick={() => onSave({ run: false, asCopy: true })} title="Duplicate as a new config">Duplicate</button>
                )}
                {selectedConfigId && (
                  <button className="chip" style={{ color: "var(--down)" }} onClick={onDelete}>Delete</button>
                )}
              </div>
            </div>
            <div className="row" style={{ flexWrap: "wrap", gap: 6, marginBottom: 8 }}>
              {configs.length === 0 && (
                <span style={{ fontSize: 11, color: "var(--text-3)" }}>No saved configs yet — fill the form and click "Save as new".</span>
              )}
              {configs.map(c => (
                <button key={c.id}
                  className={"chip " + (c.id === selectedConfigId ? "brand" : "")}
                  onClick={() => setSelectedConfigId(c.id)}
                  style={{ display: "flex", alignItems: "center", gap: 4 }}>
                  {c.running && <span style={{ width: 6, height: 6, borderRadius: "50%", background: "var(--up)" }}/>}
                  {c.name ?? c.id.slice(0, 6)}
                </button>
              ))}
            </div>
            <div className="field">
              <label className="field-label" style={{ fontSize: 11 }}>Config name</label>
              <input className="input" value={configName} onChange={e => setConfigName(e.target.value)} placeholder="e.g. Aggressive 3-of-5"/>
            </div>
          </div>

          {/* Dummy / Live toggle — prominent at top */}
          <div className="card" style={{
            padding: "12px 14px", marginBottom: 14,
            background: form.dummyMode ? "color-mix(in srgb, var(--brand) 8%, var(--surface))" : "color-mix(in srgb, var(--down) 10%, var(--surface))",
            border: `1px solid ${form.dummyMode ? "var(--brand)" : "var(--down)"}`,
          }}>
            <div className="row-between">
              <div>
                <div style={{ fontSize: 13, fontWeight: 700, color: form.dummyMode ? "var(--brand)" : "var(--down)" }}>
                  {form.dummyMode ? "🧪 DUMMY MODE" : "⚠️ LIVE TRADING"}
                </div>
                <div style={{ fontSize: 11, color: "var(--text-2)", marginTop: 2 }}>
                  {form.dummyMode
                    ? "No real orders. Simulated trades logged to Firestore for review."
                    : "Real money. Orders placed with Kotak."}
                </div>
              </div>
              <label className="row" style={{ gap: 8, cursor: "pointer", alignItems: "center" }}>
                <input type="checkbox" checked={form.dummyMode} onChange={e => update("dummyMode", e.target.checked)}/>
                <span style={{ fontSize: 12, fontWeight: 600 }}>Dummy</span>
              </label>
            </div>
          </div>

          <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 14, marginBottom: 14 }}>
            <div className="field">
              <label className="field-label">Instrument</label>
              <select className="select" value={form.instrument} onChange={e => update("instrument", e.target.value)}>
                <option value="NIFTY">NIFTY</option>
                <option value="BANKNIFTY">BANK NIFTY</option>
                <option value="FINNIFTY">FIN NIFTY</option>
              </select>
            </div>
            <div className="field">
              <label className="field-label">Capital allocated (₹)</label>
              <input type="number" className="input mono" value={form.capital} onChange={e => update("capital", +e.target.value)}/>
            </div>
          </div>

          {/* Options picker */}
          <div style={{ marginBottom: 14 }}>
            <div style={{ fontSize: 12, fontWeight: 600, marginBottom: 8, color: "var(--text-2)" }}>
              Options to monitor (optional — auto-picked if empty)
            </div>
            <OptionsPickerWidget
              underlying={form.instrument}
              pickedOptions={form.pickedOptions ?? []}
              onChange={opts => setForm(f => ({ ...f, pickedOptions: opts }))}
            />
          </div>

          {algo.id === "momentum-burst" && (
            <>
              <div className="card" style={{ background: "var(--surface-2)", border: "1px dashed var(--border-strong)", padding: 14, marginBottom: 14 }}>
                <div style={{ fontSize: 12, fontWeight: 600, color: "var(--text-2)", marginBottom: 4 }}>
                  <Icon name="info" size={12}/> Momentum Burst will buy CE when {form.instrument} spikes up sharply
                  and PE on sharp spikes down — exiting when momentum decays for {form.decayWindow}s.
                </div>
              </div>
              <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 14, marginBottom: 14 }}>
                <div className="field">
                  <label className="field-label">CE strike range</label>
                  <div className="row" style={{ gap: 6 }}>
                    <input type="number" className="input mono" placeholder="Min" value={form.callRange.min}
                      onChange={e => update("callRange", { ...form.callRange, min: +e.target.value })}/>
                    <input type="number" className="input mono" placeholder="Max" value={form.callRange.max}
                      onChange={e => update("callRange", { ...form.callRange, max: +e.target.value })}/>
                  </div>
                </div>
                <div className="field">
                  <label className="field-label">PE strike range</label>
                  <div className="row" style={{ gap: 6 }}>
                    <input type="number" className="input mono" placeholder="Min" value={form.putRange.min}
                      onChange={e => update("putRange", { ...form.putRange, min: +e.target.value })}/>
                    <input type="number" className="input mono" placeholder="Max" value={form.putRange.max}
                      onChange={e => update("putRange", { ...form.putRange, max: +e.target.value })}/>
                  </div>
                </div>
              </div>
              <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 14, marginBottom: 14 }}>
                <div className="field">
                  <label className="field-label">Spike threshold (% in 5s)</label>
                  <input type="number" step="0.1" className="input mono" value={form.momentumThreshold}
                    onChange={e => update("momentumThreshold", +e.target.value)}/>
                </div>
                <div className="field">
                  <label className="field-label">Decay window (s)</label>
                  <input type="number" className="input mono" value={form.decayWindow}
                    onChange={e => update("decayWindow", +e.target.value)}/>
                </div>
              </div>
            </>
          )}

          {algo.id === "max-profit" && (
            <>
              <div className="card" style={{ background: "var(--surface-2)", border: "1px dashed var(--border-strong)", padding: 14, marginBottom: 14 }}>
                <div style={{ fontSize: 12, fontWeight: 600, color: "var(--text-2)" }}>
                  <Icon name="info" size={12}/> MaxProfit waits for {form.triggerStockCount}+ stocks to move ≥{form.triggerThresholdPct}%
                  in the same direction within {form.observationWindowSec}s, then buys the best matching option from your pool.
                </div>
              </div>

              <div style={{ marginBottom: 14 }}>
                <div style={{ fontSize: 12, fontWeight: 600, marginBottom: 8, color: "var(--text-2)" }}>
                  Watchlist stocks ({form.pickedStocks.length} added)
                </div>
                <StockPickerWidget
                  pickedStocks={form.pickedStocks}
                  onChange={stocks => setForm(f => ({ ...f, pickedStocks: stocks }))}
                />
              </div>

              <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 14, marginBottom: 14 }}>
                <div className="field">
                  <label className="field-label">Trigger stock count</label>
                  <input type="number" className="input mono" value={form.triggerStockCount}
                    onChange={e => update("triggerStockCount", +e.target.value)}/>
                </div>
                <div className="field">
                  <label className="field-label">Trigger threshold (%)</label>
                  <input type="number" step="0.1" className="input mono" value={form.triggerThresholdPct}
                    onChange={e => update("triggerThresholdPct", +e.target.value)}/>
                </div>
                <div className="field">
                  <label className="field-label">Observation window (s)</label>
                  <input type="number" className="input mono" value={form.observationWindowSec}
                    onChange={e => update("observationWindowSec", +e.target.value)}/>
                </div>
                <div className="field">
                  <label className="field-label">Option budget (₹)</label>
                  <input type="number" className="input mono" value={form.optionBudget}
                    onChange={e => update("optionBudget", +e.target.value)}/>
                </div>
                <div className="field">
                  <label className="field-label">Limit profit (%) — sell when hit</label>
                  <input type="number" step="0.5" className="input mono" value={form.limitProfitPct}
                    onChange={e => update("limitProfitPct", +e.target.value)}/>
                </div>
                <div className="field">
                  <label className="field-label">Stop loss (%) — safety net</label>
                  <input type="number" step="0.5" className="input mono" value={form.stopLossPct}
                    onChange={e => update("stopLossPct", +e.target.value)}/>
                </div>
                <div className="field">
                  <label className="field-label">Time stop (s) — market exit if limit not hit</label>
                  <input type="number" className="input mono" value={form.timeStopSec}
                    onChange={e => update("timeStopSec", +e.target.value)}/>
                </div>
              </div>
            </>
          )}

          {algo.id === "candle-burst" && (
            <>
              <div className="card" style={{ background: "var(--surface-2)", border: "1px dashed var(--border-strong)", padding: 14, marginBottom: 14 }}>
                <div style={{ fontSize: 12, fontWeight: 600, color: "var(--text-2)" }}>
                  <Icon name="info" size={12}/> Builds {form.candleSec}s candles from {form.instrument} spot.
                  Detects bullish/bearish engulfing, hammer / shooting star, marubozu. Buys CE/PE on pattern.
                  {form.exitMode === "pattern-trail"
                    ? <> Exits on opposite-pattern reversal or {form.trailingStopPct}% trail from peak; SL safety net at −{form.stopLossPct}%.</>
                    : <> Exits at +{form.limitProfitPct}% limit, market at {form.timeStopSec}s, SL at −{form.stopLossPct}%.</>
                  }
                </div>
              </div>

              {/* Exit strategy selector */}
              <div style={{ marginBottom: 14 }}>
                <label className="field-label">Exit strategy</label>
                <div className="row" style={{ gap: 6 }}>
                  <button type="button" onClick={() => update("exitMode", "timeout")}
                    className={"chip " + (form.exitMode === "timeout" ? "brand" : "")}
                    style={{ flex: 1, padding: "10px 14px", fontSize: 12, textAlign: "center", justifyContent: "center" }}>
                    ⏱ Limit + Time stop
                  </button>
                  <button type="button" onClick={() => update("exitMode", "pattern-trail")}
                    className={"chip " + (form.exitMode === "pattern-trail" ? "brand" : "")}
                    style={{ flex: 1, padding: "10px 14px", fontSize: 12, textAlign: "center", justifyContent: "center" }}>
                    🕯 Pattern reversal + Trail
                  </button>
                </div>
              </div>

              <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 14, marginBottom: 14 }}>
                <div className="field">
                  <label className="field-label">Candle period (s)</label>
                  <input type="number" className="input mono" value={form.candleSec}
                    onChange={e => update("candleSec", +e.target.value)}/>
                </div>
                <div className="field">
                  <label className="field-label">Option budget (₹)</label>
                  <input type="number" className="input mono" value={form.optionBudget}
                    onChange={e => update("optionBudget", +e.target.value)}/>
                </div>
                <div className="field">
                  <label className="field-label">Stop loss (%) — safety net</label>
                  <input type="number" step="0.5" className="input mono" value={form.stopLossPct}
                    onChange={e => update("stopLossPct", +e.target.value)}/>
                </div>
                {form.exitMode === "timeout" ? (
                  <>
                    <div className="field">
                      <label className="field-label">Limit profit (%)</label>
                      <input type="number" step="0.5" className="input mono" value={form.limitProfitPct}
                        onChange={e => update("limitProfitPct", +e.target.value)}/>
                    </div>
                    <div className="field">
                      <label className="field-label">Time stop (s)</label>
                      <input type="number" className="input mono" value={form.timeStopSec}
                        onChange={e => update("timeStopSec", +e.target.value)}/>
                    </div>
                  </>
                ) : (
                  <div className="field">
                    <label className="field-label">Trailing stop (% drop from peak)</label>
                    <input type="number" step="1" className="input mono" value={form.trailingStopPct}
                      onChange={e => update("trailingStopPct", +e.target.value)}/>
                  </div>
                )}
              </div>
            </>
          )}

          <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 14, marginBottom: 18 }}>
            <div className="field">
              <label className="field-label">Stop loss (%)</label>
              <input type="number" step="0.5" className="input mono" value={form.sl} onChange={e => update("sl", +e.target.value)}/>
            </div>
            <div className="field">
              <label className="field-label">Take profit (%)</label>
              <input type="number" step="0.5" className="input mono" value={form.tp} onChange={e => update("tp", +e.target.value)}/>
            </div>
          </div>

          <div style={{ background: "var(--surface-2)", borderRadius: 10, padding: 14, marginBottom: 18 }}>
            <div style={{ fontSize: 12, fontWeight: 600, marginBottom: 8 }}>Risk summary</div>
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 10, fontSize: 12 }}>
              <div><div className="muted">Max loss</div><div className="mono" style={{ fontWeight: 600, color: "var(--down)" }}>−{fmtINR(form.capital * form.sl / 100)}</div></div>
              <div><div className="muted">Target profit</div><div className="mono" style={{ fontWeight: 600, color: "var(--up)" }}>+{fmtINR(form.capital * form.tp / 100)}</div></div>
              <div><div className="muted">R:R</div><div className="mono" style={{ fontWeight: 600 }}>1 : {(form.tp/form.sl).toFixed(2)}</div></div>
            </div>
          </div>
        </div>

        <div style={{ padding: "14px 22px", borderTop: "1px solid var(--border)", display: "flex", gap: 8, justifyContent: "space-between", flexWrap: "wrap" }}>
          <div className="row" style={{ gap: 6 }}>
            <button className="btn btn-secondary" onClick={onClose}>Close</button>
            <button className="btn btn-secondary" onClick={() => onSave({ run: false, asCopy: false })}>
              <Icon name="settings" size={14}/> {selectedConfigId ? "Save" : "Save as new"}
            </button>
            {selectedConfigId && (
              <button className="btn btn-secondary" onClick={() => onSave({ run: false, asCopy: true })}>
                Save as copy
              </button>
            )}
          </div>
          <div className="row" style={{ gap: 6 }}>
            {selectedConfig?.running ? (
              <button className="btn btn-sell" onClick={onStopConfig}>
                <Icon name="pause" size={14}/> Stop
              </button>
            ) : (
              <button className="btn btn-primary" onClick={() => onSave({ run: true, asCopy: false })}>
                <Icon name="play" size={14}/> {selectedConfigId ? "Save & Start" : "Save & Start as new"}
              </button>
            )}
          </div>
        </div>
      </div>
    </div>
  );
};

/* ---------------- LIVE ALGO MONITOR ---------------- */
const AlgoMonitorScreen = ({ algos, market, events }) => {
  const running = algos.filter(a => a.running);
  return (
    <div className="page">
      <h2 className="page-title">Live Algo Monitor</h2>
      <div className="page-sub">{running.length} algos running · Streaming via Kotak websocket · {events.length} events today</div>

      <div className="grid" style={{ gridTemplateColumns: "repeat(3, 1fr)", marginBottom: 16 }}>
        {running.map(a => <RunningAlgoCard key={a.id} algo={a}/>)}
      </div>

      <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 16 }}>
        <div className="card" style={{ padding: 0, overflow: "hidden" }}>
          <div style={{ padding: "14px 18px", borderBottom: "1px solid var(--border)" }}>
            <div className="row-between">
              <div style={{ fontWeight: 600, fontSize: 14 }}>Live event stream</div>
              <span className="chip up"><span className="pulse" style={{width:6,height:6,background:"var(--up)",borderRadius:"50%"}}/> Live</span>
            </div>
          </div>
          <div style={{ maxHeight: 480, overflowY: "auto", padding: "8px 0" }}>
            {events.length === 0 && <div className="muted" style={{ padding: 24, textAlign: "center", fontSize: 13 }}>No events yet today</div>}
            {events.map((e, i) => (
              <div key={i} style={{ padding: "10px 18px", borderBottom: "1px solid var(--border)", display: "flex", gap: 12 }}>
                <div style={{
                  width: 28, height: 28, borderRadius: 8, flexShrink: 0,
                  background: e.type === "buy" ? "var(--up-soft)" : e.type === "sell" ? "var(--down-soft)" : "var(--surface-2)",
                  color: e.type === "buy" ? "var(--up)" : e.type === "sell" ? "var(--down)" : "var(--text-2)",
                  display: "grid", placeItems: "center", fontSize: 12, fontWeight: 700,
                }}>{e.type === "buy" ? "B" : e.type === "sell" ? "S" : "i"}</div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 13, fontWeight: 600 }}>{e.title}</div>
                  <div style={{ fontSize: 12, color: "var(--text-3)" }}>{e.body}</div>
                </div>
                <div className="mono muted" style={{ fontSize: 11, whiteSpace: "nowrap" }}>{e.time}</div>
              </div>
            ))}
          </div>
        </div>

        <div className="card">
          <div className="card-title">Subscribed feed health</div>
          <div className="grid" style={{ gap: 10 }}>
            <FeedHealthRow label="Kotak Quote websocket" status="up" detail="48ms · 412 ticks/s"/>
            <FeedHealthRow label="Kotak Order websocket"  status="up" detail="22ms · idle"/>
            <FeedHealthRow label="Firebase Functions"     status="up" detail="172ms avg"/>
            <FeedHealthRow label="Heartbeat"              status="up" detail="last 1.2s ago"/>
            <FeedHealthRow label="Margin available"       status="ok" detail={fmtINR(248_650)}/>
          </div>
          <hr className="hr" style={{ margin: "16px 0" }}/>
          <div className="card-title">Today's auto-trade summary</div>
          <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 8 }}>
            <Stat label="Trades placed" value="22"/>
            <Stat label="Filled" value="22" accent="up"/>
            <Stat label="Profit hits (TP)" value="14"/>
            <Stat label="Stop hits (SL)" value="6" accent="down"/>
            <Stat label="Time-exits" value="2"/>
            <Stat label="Net P&L" value={"+" + fmtINR(6_305, 0)} accent="up"/>
          </div>
        </div>
      </div>
    </div>
  );
};

const RunningAlgoCard = ({ algo }) => (
  <div className="card" style={{ padding: 0, overflow: "hidden" }}>
    <div style={{ padding: "14px 16px", borderBottom: "1px solid var(--border)", display: "flex", gap: 10, alignItems: "center" }}>
      <div style={{ width: 36, height: 36, borderRadius: 10, background: "var(--brand)", color: "white", display: "grid", placeItems: "center", fontSize: 18, fontWeight: 700 }}>{algo.icon}</div>
      <div style={{ flex: 1 }}>
        <div style={{ fontSize: 13, fontWeight: 700 }}>{algo.name}</div>
        <div style={{ fontSize: 11, color: "var(--text-3)" }}>{algo.tagline}</div>
      </div>
      <span className="chip up"><span className="pulse" style={{width:5,height:5,background:"var(--up)",borderRadius:"50%"}}/></span>
    </div>
    <div style={{ padding: 14 }}>
      <div className="row-between" style={{ marginBottom: 8 }}>
        <span className="muted" style={{ fontSize: 11, fontWeight: 600 }}>P&L today</span>
        <span className="mono" style={{ fontWeight: 700, color: algo.pnl >= 0 ? "var(--up)" : "var(--down)" }}>
          {algo.pnl >= 0 ? "+" : ""}{fmtINR(algo.pnl, 0)}
        </span>
      </div>
      <div className="row-between" style={{ marginBottom: 8 }}>
        <span className="muted" style={{ fontSize: 11, fontWeight: 600 }}>Auto-trades</span>
        <span className="mono" style={{ fontWeight: 600 }}>{algo.autoTrades}</span>
      </div>
      <div className="row-between" style={{ marginBottom: 12 }}>
        <span className="muted" style={{ fontSize: 11, fontWeight: 600 }}>Status</span>
        <span style={{ fontSize: 11, color: "var(--text-2)" }}>Watching for setup…</span>
      </div>
      <div style={{ height: 4, background: "var(--surface-2)", borderRadius: 2, overflow: "hidden" }}>
        <div style={{ width: "62%", height: "100%", background: "var(--brand)", borderRadius: 2 }}/>
      </div>
      <div style={{ fontSize: 10, color: "var(--text-3)", marginTop: 6 }}>
        Capital used 62% · Risk budget 38% remaining
      </div>
    </div>
  </div>
);

const FeedHealthRow = ({ label, status, detail }) => (
  <div className="row-between" style={{ padding: "8px 0", borderBottom: "1px solid var(--border)" }}>
    <div className="row" style={{ gap: 8 }}>
      <span className="pulse" style={{ width: 8, height: 8, background: "var(--up)", borderRadius: "50%" }}/>
      <span style={{ fontSize: 13, fontWeight: 500 }}>{label}</span>
    </div>
    <span className="mono muted" style={{ fontSize: 11 }}>{detail}</span>
  </div>
);

/* ---------------- REPORTS ---------------- */
const ReportsScreen = ({ pnlHistory, isDemo }) => {
  const [period, setPeriod] = React.useState("daily");
  const [orders, setOrders] = React.useState([]);
  const [ordersLoading, setOrdersLoading] = React.useState(false);

  React.useEffect(() => {
    if (isDemo) return; // demo mode: no Firestore orders needed
    setOrdersLoading(true);
    API.loadOrders(30).then(data => {
      setOrders(Array.isArray(data) ? data : []);
    }).catch(() => setOrders([])).finally(() => setOrdersLoading(false));
  }, [isDemo]);

  // group by week / month
  const grouped = React.useMemo(() => {
    if (!pnlHistory || pnlHistory.length === 0) return [];
    if (period === "daily") return pnlHistory;
    if (period === "weekly") {
      const map = {};
      pnlHistory.forEach(d => {
        const wkStart = new Date(d.date);
        wkStart.setDate(wkStart.getDate() - wkStart.getDay() + 1);
        const k = wkStart.toISOString().slice(0, 10);
        if (!map[k]) map[k] = { date: wkStart, pnl: 0, trades: 0 };
        map[k].pnl += (d.pnl || 0);
        map[k].trades += (d.trades || 0);
      });
      let cumul = 0;
      return Object.values(map).sort((a, b) => a.date - b.date).map(w => { cumul += w.pnl; return { ...w, cumul }; });
    }
    if (period === "monthly") {
      const map = {};
      pnlHistory.forEach(d => {
        const dt = new Date(d.date);
        const k = `${dt.getFullYear()}-${dt.getMonth()}`;
        if (!map[k]) map[k] = { date: new Date(dt.getFullYear(), dt.getMonth(), 1), pnl: 0, trades: 0 };
        map[k].pnl += (d.pnl || 0);
        map[k].trades += (d.trades || 0);
      });
      let cumul = 0;
      return Object.values(map).sort((a, b) => a.date - b.date).map(w => { cumul += w.pnl; return { ...w, cumul }; });
    }
    return [];
  }, [period, pnlHistory]);

  // Empty state — no P&L history yet
  if (!pnlHistory || pnlHistory.length === 0) {
    return (
      <div className="page">
        <div className="row-between" style={{ marginBottom: 16 }}>
          <div>
            <h2 className="page-title">Performance Reports</h2>
            <div className="page-sub">P&L analysis across time periods</div>
          </div>
        </div>
        <div className="card" style={{ padding: 60, textAlign: "center" }}>
          <div style={{ fontSize: 36, marginBottom: 10, opacity: .35 }}>📊</div>
          <div style={{ fontSize: 16, fontWeight: 600, marginBottom: 6 }}>No trade data yet. Start trading to see reports.</div>
          <div className="muted" style={{ fontSize: 13 }}>Your P&amp;L curve and stats will appear here after your first trade.</div>
        </div>
      </div>
    );
  }

  const totalPnl = grouped.reduce((s, d) => s + (d.pnl || 0), 0);
  const winDays = grouped.filter(d => (d.pnl || 0) >= 0).length;
  const avgPerDay = grouped.length > 0 ? totalPnl / grouped.length : 0;
  const bestDay = grouped.length > 0 ? Math.max(...grouped.map(d => d.pnl || 0)) : 0;
  const worstDay = grouped.length > 0 ? Math.min(...grouped.map(d => d.pnl || 0)) : 0;

  // KPI from pnlHistory snapshots
  const lastCumul = pnlHistory[pnlHistory.length - 1].cumul ?? totalPnl;
  const allCumuls = pnlHistory.map(d => d.cumul ?? d.pnl ?? 0);
  const bestDayCumul = Math.max(...allCumuls);
  const worstDayCumul = Math.min(...allCumuls);

  return (
    <div className="page">
      <div className="row-between" style={{ marginBottom: 16 }}>
        <div>
          <h2 className="page-title">Performance Reports</h2>
          <div className="page-sub">P&L analysis across time periods</div>
        </div>
        <div className="row" style={{ gap: 6 }}>
          <button className={"chip " + (period === "daily" ? "brand" : "")} onClick={() => setPeriod("daily")}>Daily</button>
          <button className={"chip " + (period === "weekly" ? "brand" : "")} onClick={() => setPeriod("weekly")}>Weekly</button>
          <button className={"chip " + (period === "monthly" ? "brand" : "")} onClick={() => setPeriod("monthly")}>Monthly</button>
          <button className="btn btn-secondary btn-sm"><Icon name="download" size={13}/> Export</button>
        </div>
      </div>

      {/* Top KPI row: real data from pnlHistory */}
      <div className="grid" style={{ gridTemplateColumns: "repeat(3, 1fr)", marginBottom: 16 }}>
        <div className="kpi">
          <div className="kpi-label">Total P&L</div>
          <div className="kpi-value" style={{ color: lastCumul >= 0 ? "var(--up)" : "var(--down)" }}>
            {lastCumul >= 0 ? "+" : ""}{fmtINR(lastCumul, 0)}
          </div>
          <div className="kpi-foot muted">{pnlHistory.length} trading days</div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Best day</div>
          <div className="kpi-value" style={{ color: "var(--up)" }}>+{fmtINR(bestDayCumul, 0)}</div>
          <div className="kpi-foot up">single day peak</div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Worst day</div>
          <div className="kpi-value" style={{ color: "var(--down)" }}>{fmtINR(worstDayCumul, 0)}</div>
          <div className="kpi-foot down">single day trough</div>
        </div>
      </div>

      <div className="grid" style={{ gridTemplateColumns: "repeat(5, 1fr)", marginBottom: 16 }}>
        <div className="kpi"><div className="kpi-label">Period P&L</div><div className="kpi-value" style={{color: totalPnl>=0?"var(--up)":"var(--down)"}}>{totalPnl>=0?"+":""}{fmtINR(totalPnl, 0)}</div><div className="kpi-foot muted">{grouped.length} {period} periods</div></div>
        <div className="kpi"><div className="kpi-label">Win rate</div><div className="kpi-value">{grouped.length > 0 ? Math.round(winDays/grouped.length*100) : 0}%</div><div className="kpi-foot up">{winDays} winning · {grouped.length - winDays} losing</div></div>
        <div className="kpi"><div className="kpi-label">Avg / period</div><div className="kpi-value mono">{fmtINR(avgPerDay, 0)}</div><div className="kpi-foot muted">across {grouped.length}</div></div>
        <div className="kpi"><div className="kpi-label">Best period</div><div className="kpi-value" style={{color:"var(--up)"}}>+{fmtINR(bestDay, 0)}</div><div className="kpi-foot up">single period</div></div>
        <div className="kpi"><div className="kpi-label">Worst period</div><div className="kpi-value" style={{color:"var(--down)"}}>{fmtINR(worstDay, 0)}</div><div className="kpi-foot down">single period</div></div>
      </div>

      <div className="card" style={{ marginBottom: 16 }}>
        <div className="card-title">Cumulative P&L</div>
        <AreaChart data={grouped} valueKey="cumul" labelKey="date" height={260}/>
      </div>

      <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 16, marginBottom: 16 }}>
        <div className="card">
          <div className="card-title">P&L by {period.replace(/ly$/, "")}</div>
          <BarChart data={grouped} valueKey="pnl" height={220}/>
        </div>

        <div className="card">
          <div className="card-title">By strategy</div>
          <table className="tbl">
            <thead><tr><th>Algo</th><th className="num">Trades</th><th className="num">Win %</th><th className="num">P&L</th></tr></thead>
            <tbody>
              {[
                { name: "Momentum Burst", trades: 124, win: 64, pnl: 18460 },
                { name: "Iron Condor",    trades: 32,  win: 78, pnl: 8420 },
                { name: "VWAP Reversion", trades: 86,  win: 67, pnl: 11240 },
                { name: "ORB",            trades: 42,  win: 54, pnl: 4180 },
                { name: "Gap Fade",       trades: 18,  win: 56, pnl: -1320 },
                { name: "Manual",         trades: 9,   win: 44, pnl: -845 },
              ].map((r, i) => (
                <tr key={i}>
                  <td><span className="chip brand"><Icon name="bot" size={11}/> {r.name}</span></td>
                  <td className="num">{r.trades}</td>
                  <td className="num">{r.win}%</td>
                  <td className="num" style={{ color: r.pnl >= 0 ? "var(--up)" : "var(--down)", fontWeight: 600 }}>
                    {r.pnl >= 0 ? "+" : ""}{fmtNum(r.pnl, 0)}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>

      {/* Recent orders from Firestore (live mode only) */}
      {!isDemo && (
        <div className="card">
          <div className="card-title" style={{ marginBottom: 12 }}>
            Recent orders (last 30 days)
            {ordersLoading && <span className="muted" style={{ fontSize: 12, fontWeight: 400, marginLeft: 10 }}>Loading…</span>}
          </div>
          {!ordersLoading && orders.length === 0 ? (
            <div className="muted" style={{ fontSize: 13, padding: "16px 0", textAlign: "center" }}>No orders in the last 30 days.</div>
          ) : (
            <div style={{ overflowX: "auto" }}>
              <table className="tbl">
                <thead>
                  <tr>
                    <th>Date</th><th>Symbol</th><th>Side</th>
                    <th className="num">Qty</th><th className="num">Price</th><th>Status</th>
                  </tr>
                </thead>
                <tbody>
                  {orders.slice(0, 50).map((o, i) => {
                    const dt = o.ts ? new Date(o.ts) : null;
                    return (
                      <tr key={i}>
                        <td className="muted" style={{ fontSize: 12 }}>
                          {dt ? dt.toLocaleDateString("en-IN", { day: "2-digit", month: "short" }) : (o.date ?? "—")}
                        </td>
                        <td><div style={{ fontWeight: 600 }}>{o.sym ?? "—"}</div></td>
                        <td><span className={"chip " + (o.side === "BUY" ? "up" : "down")}>{o.side ?? "—"}</span></td>
                        <td className="num">{o.qty ?? "—"}</td>
                        <td className="num">{o.price != null ? fmtNum(o.price) : "—"}</td>
                        <td><span className="chip">{o.status ?? "—"}</span></td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          )}
        </div>
      )}
    </div>
  );
};

/* ---------------- ORDERS & TRADES ---------------- */
const OrdersScreen = ({ addToast, liveOrders = [] }) => {
  const [tab, setTab] = React.useState("orders");
  const [fetchedOrders, setFetchedOrders] = React.useState(null);
  const [trades, setTrades] = React.useState(null);
  const [loadingOrders, setLoadingOrders] = React.useState(false);
  const [loadingTrades, setLoadingTrades] = React.useState(false);

  // Merge fetched orders with live HSI updates — live takes precedence by nOrdNo
  const orders = React.useMemo(() => {
    const base = fetchedOrders ?? [];
    if (!liveOrders.length) return base;
    const merged = [...base];
    liveOrders.forEach(lo => {
      const idx = merged.findIndex(o => o.nOrdNo === lo.nOrdNo);
      if (idx >= 0) merged[idx] = { ...merged[idx], ...lo };
      else merged.unshift(lo);
    });
    return merged;
  }, [fetchedOrders, liveOrders]);

  React.useEffect(() => {
    setLoadingOrders(true);
    API.getOrders()
      .then(res => {
        const data = Array.isArray(res?.data) ? res.data : (Array.isArray(res) ? res : []);
        setFetchedOrders(data);
      })
      .catch(() => setFetchedOrders([]))
      .finally(() => setLoadingOrders(false));

    setLoadingTrades(true);
    API.getTrades()
      .then(res => {
        const data = Array.isArray(res?.data) ? res.data : (Array.isArray(res) ? res : []);
        setTrades(data);
      })
      .catch(() => setTrades([]))
      .finally(() => setLoadingTrades(false));
  }, []);

  const refresh = () => {
    setOrders(null); setTrades(null);
    setLoadingOrders(true);
    API.getOrders()
      .then(res => setOrders(Array.isArray(res?.data) ? res.data : (Array.isArray(res) ? res : [])))
      .catch(() => setOrders([]))
      .finally(() => setLoadingOrders(false));
    setLoadingTrades(true);
    API.getTrades()
      .then(res => setTrades(Array.isArray(res?.data) ? res.data : (Array.isArray(res) ? res : [])))
      .catch(() => setTrades([]))
      .finally(() => setLoadingTrades(false));
  };

  const loading = tab === "orders" ? loadingOrders : loadingTrades;
  const rows = tab === "orders" ? orders : trades;

  return (
    <div className="page">
      <div className="row-between" style={{ marginBottom: 16 }}>
        <div>
          <h2 className="page-title">Orders &amp; Trades</h2>
          <div className="page-sub">Today's order book and trade book from Kotak</div>
        </div>
        <button className="btn btn-secondary" onClick={refresh}><Icon name="refresh" size={14}/> Refresh</button>
      </div>

      <div className="tabs" style={{ marginBottom: 16 }}>
        <div className={"tab " + (tab === "orders" ? "active" : "")} onClick={() => setTab("orders")}>
          Orders{orders !== null ? ` (${orders.length})` : ""}
        </div>
        <div className={"tab " + (tab === "trades" ? "active" : "")} onClick={() => setTab("trades")}>
          Trades{trades !== null ? ` (${trades.length})` : ""}
        </div>
      </div>

      <div className="card" style={{ padding: loading || !rows?.length ? 40 : 0, overflow: "hidden", textAlign: loading || !rows?.length ? "center" : "left" }}>
        {loading && <div className="muted" style={{ fontSize: 13 }}><Icon name="refresh" size={14}/> Loading {tab}…</div>}

        {!loading && rows !== null && rows.length === 0 && (
          <div>
            <div style={{ fontSize: 28, marginBottom: 8, opacity: .4 }}>{tab === "orders" ? "📋" : "📊"}</div>
            <div className="muted" style={{ fontSize: 13 }}>No {tab} found for today</div>
          </div>
        )}

        {!loading && rows !== null && rows.length > 0 && tab === "orders" && (
          <div style={{ overflowX: "auto" }}>
            <table className="tbl">
              <thead>
                <tr>
                  <th>Order No</th>
                  <th>Symbol</th>
                  <th>Type</th>
                  <th>Side</th>
                  <th className="num">Qty</th>
                  <th className="num">Price</th>
                  <th>Status</th>
                  <th>Time</th>
                </tr>
              </thead>
              <tbody>
                {rows.map((o, i) => (
                  <tr key={i}>
                    <td className="mono muted" style={{ fontSize: 12 }}>{o.nOrdNo}</td>
                    <td><div style={{ fontWeight: 600 }}>{o.trdSym}</div></td>
                    <td><span className="chip">{o.exTyp}</span></td>
                    <td><span className={"chip " + (o.trnsTp === "B" ? "up" : "down")}>{o.trnsTp === "B" ? "BUY" : "SELL"}</span></td>
                    <td className="num">{o.qty}</td>
                    <td className="num">{fmtNum(o.prc)}</td>
                    <td><span className={"chip " + (o.ordSt === "complete" || o.ordSt === "COMPLETE" ? "up" : o.ordSt === "rejected" || o.ordSt === "REJECTED" ? "down" : "")}>{o.ordSt}</span></td>
                    <td className="muted" style={{ fontSize: 12 }}>{o.hsUpTm}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}

        {!loading && rows !== null && rows.length > 0 && tab === "trades" && (
          <div style={{ overflowX: "auto" }}>
            <table className="tbl">
              <thead>
                <tr>
                  <th>Trade No</th>
                  <th>Symbol</th>
                  <th>Side</th>
                  <th className="num">Qty</th>
                  <th className="num">Price</th>
                  <th className="num">Value</th>
                  <th>Time</th>
                </tr>
              </thead>
              <tbody>
                {rows.map((t, i) => (
                  <tr key={i}>
                    <td className="mono muted" style={{ fontSize: 12 }}>{t.trdNo}</td>
                    <td><div style={{ fontWeight: 600 }}>{t.trdSym}</div></td>
                    <td><span className={"chip " + (t.trnsTp === "B" ? "up" : "down")}>{t.trnsTp === "B" ? "BUY" : "SELL"}</span></td>
                    <td className="num">{t.qty}</td>
                    <td className="num">{fmtNum(t.prc)}</td>
                    <td className="num" style={{ fontWeight: 600 }}>{fmtINR(t.trdVal)}</td>
                    <td className="muted" style={{ fontSize: 12 }}>{t.hsUpTm}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>
    </div>
  );
};

/* ---------------- TRADE JOURNAL ---------------- */
const JournalScreen = ({ trades: demoTrades, isDemo }) => {
  const [q, setQ] = React.useState("");
  const [liveOrders, setLiveOrders] = React.useState([]);
  const [loading, setLoading] = React.useState(false);

  React.useEffect(() => {
    if (isDemo) return; // demo mode: use demoTrades prop
    setLoading(true);
    API.loadOrders(90).then(data => {
      setLiveOrders(Array.isArray(data) ? data : []);
    }).catch(() => setLiveOrders([])).finally(() => setLoading(false));
  }, [isDemo]);

  // In demo mode use mock trades, in live mode use Firestore orders
  const allEntries = isDemo ? (demoTrades || []) : liveOrders;

  // Normalise Firestore orders to a common display shape
  const rows = allEntries.map(t => {
    if (isDemo) return t; // already has id, time (Date), sym, side, qty, price, pnl, algo, status
    const dt = t.ts ? new Date(t.ts) : null;
    return {
      id:     t.orderNo ?? "—",
      time:   dt,
      sym:    t.sym ?? "—",
      side:   t.side ?? "—",
      qty:    t.qty ?? "—",
      price:  t.price ?? 0,
      pnl:    null, // not stored per-order
      algo:   t.product ?? "—",
      status: t.status ?? "—",
    };
  });

  const filtered = rows.filter(t => {
    const search = q.toLowerCase();
    return (
      String(t.sym).toLowerCase().includes(search) ||
      String(t.algo).toLowerCase().includes(search) ||
      String(t.id).toLowerCase().includes(search)
    );
  });

  const totalPnl = filtered.reduce((s, t) => s + (t.pnl || 0), 0);

  if (loading) {
    return (
      <div className="page">
        <h2 className="page-title">Trade Journal</h2>
        <div className="card" style={{ padding: 60, textAlign: "center" }}>
          <div className="muted" style={{ fontSize: 13 }}><Icon name="refresh" size={14}/> Loading journal…</div>
        </div>
      </div>
    );
  }

  return (
    <div className="page">
      <div className="row-between" style={{ marginBottom: 16 }}>
        <div>
          <h2 className="page-title">Trade Journal</h2>
          <div className="page-sub">
            {filtered.length} trades{isDemo && totalPnl !== 0 ? ` · Net ${fmtINR(totalPnl, 0)}` : ""}
          </div>
        </div>
        <div className="row" style={{ gap: 8 }}>
          <input className="input" placeholder="Search trades..." value={q} onChange={e => setQ(e.target.value)} style={{ width: 260 }}/>
          <button className="btn btn-secondary"><Icon name="filter" size={14}/> Filter</button>
          <button className="btn btn-secondary"><Icon name="download" size={14}/> CSV</button>
        </div>
      </div>

      {filtered.length === 0 ? (
        <div className="card" style={{ padding: 60, textAlign: "center" }}>
          <div style={{ fontSize: 32, marginBottom: 10, opacity: .35 }}>📒</div>
          <div style={{ fontSize: 15, fontWeight: 600, marginBottom: 6 }}>
            {q
              ? "No trades match your search."
              : "Your trade journal is empty. Completed trades will appear here."}
          </div>
          {!q && <div className="muted" style={{ fontSize: 13 }}>Place your first trade to get started.</div>}
        </div>
      ) : (
        <div className="card" style={{ padding: 0, overflow: "hidden" }}>
          <div style={{ overflowX: "auto" }}>
            <table className="tbl">
              <thead>
                <tr>
                  <th>ID</th><th>Time</th><th>Instrument</th><th>Side</th>
                  <th className="num">Qty</th><th className="num">Price</th>
                  {isDemo && <th className="num">P&L</th>}
                  <th>{isDemo ? "Algo" : "Product"}</th><th>Status</th>
                </tr>
              </thead>
              <tbody>
                {filtered.slice(0, 50).map((t, idx) => (
                  <tr key={t.id ?? idx}>
                    <td className="mono muted" style={{ fontSize: 12 }}>{t.id}</td>
                    <td className="muted" style={{ fontSize: 12 }}>
                      {t.time
                        ? <>{t.time.toLocaleDateString("en-IN", {day:"2-digit",month:"short"})}<br/>
                            <span style={{ fontSize: 11 }}>{t.time.toLocaleTimeString("en-IN", {hour:"2-digit",minute:"2-digit"})}</span>
                          </>
                        : "—"}
                    </td>
                    <td><div style={{ fontWeight: 600 }}>{t.sym}</div></td>
                    <td><span className={"chip " + (t.side === "BUY" ? "up" : "down")}>{t.side}</span></td>
                    <td className="num">{t.qty}</td>
                    <td className="num">{t.price != null && t.price !== 0 ? fmtNum(t.price) : "—"}</td>
                    {isDemo && (
                      <td className="num" style={{ color: (t.pnl || 0) >= 0 ? "var(--up)" : "var(--down)", fontWeight: 600 }}>
                        {(t.pnl || 0) >= 0 ? "+" : ""}{fmtNum(t.pnl || 0, 0)}
                      </td>
                    )}
                    <td>
                      {t.algo === "Manual"
                        ? <span className="chip">Manual</span>
                        : <span className="chip brand"><Icon name="bot" size={11}/> {t.algo}</span>}
                    </td>
                    <td><span className="chip up">{t.status}</span></td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}
    </div>
  );
};

/* ---------------- BACKTEST ---------------- */
const BacktestScreen = ({ algos }) => {
  const [algo, setAlgo] = React.useState("momentum-burst");
  const [period, setPeriod] = React.useState("3M");
  const [running, setRunning] = React.useState(false);
  const [result, setResult] = React.useState(null);

  const run = () => {
    setRunning(true);
    setResult(null);
    setTimeout(() => {
      // generate fake equity curve
      const n = period === "1M" ? 22 : period === "3M" ? 65 : period === "6M" ? 130 : 250;
      const eq = [];
      let v = 0;
      const today = new Date();
      for (let i = 0; i < n; i++) {
        const d = new Date(today); d.setDate(d.getDate() - (n - i));
        const day = (Math.random() - 0.42) * 1800;
        v += day;
        eq.push({ date: d, pnl: day, cumul: +v.toFixed(2) });
      }
      const total = +v.toFixed(2);
      const wins = eq.filter(e => e.pnl >= 0).length;
      const peak = Math.max(...eq.map(e => e.cumul));
      const trough = Math.min(...eq.map(e => e.cumul));
      setResult({
        equity: eq,
        total,
        winRate: Math.round(wins / n * 100),
        trades: n * 4,
        avgTrade: +(total / (n * 4)).toFixed(2),
        maxDrawdown: +(((trough - peak) / Math.max(Math.abs(peak), 1)) * 100).toFixed(2),
        sharpe: +(0.8 + Math.random() * 1.6).toFixed(2),
      });
      setRunning(false);
    }, 1100);
  };

  const a = algos.find(x => x.id === algo);

  return (
    <div className="page">
      <h2 className="page-title">Backtest</h2>
      <div className="page-sub">Run any strategy on historical data to validate before going live</div>

      <div className="card" style={{ marginBottom: 16 }}>
        <div className="grid" style={{ gridTemplateColumns: "2fr 1fr 1fr 1fr auto", gap: 14, alignItems: "end" }}>
          <div className="field">
            <label className="field-label">Strategy</label>
            <select className="select" value={algo} onChange={e => setAlgo(e.target.value)}>
              {algos.map(a => <option key={a.id} value={a.id}>{a.name}</option>)}
            </select>
          </div>
          <div className="field">
            <label className="field-label">Instrument</label>
            <select className="select" defaultValue="NIFTY"><option>NIFTY</option><option>BANKNIFTY</option><option>FINNIFTY</option></select>
          </div>
          <div className="field">
            <label className="field-label">Period</label>
            <select className="select" value={period} onChange={e => setPeriod(e.target.value)}>
              <option>1M</option><option>3M</option><option>6M</option><option>1Y</option>
            </select>
          </div>
          <div className="field">
            <label className="field-label">Capital</label>
            <input className="input mono" defaultValue={100000}/>
          </div>
          <button className="btn btn-primary" onClick={run} disabled={running} style={{ padding: "10px 18px" }}>
            {running ? <><Icon name="refresh" size={14}/> Running...</> : <><Icon name="play" size={14}/> Run backtest</>}
          </button>
        </div>
      </div>

      {!result && !running && (
        <div className="card" style={{ padding: 60, textAlign: "center" }}>
          <div style={{ fontSize: 36, marginBottom: 10, opacity: .4 }}>{a.icon}</div>
          <div style={{ fontSize: 16, fontWeight: 600, marginBottom: 6 }}>Ready to backtest {a.name}</div>
          <div className="muted" style={{ fontSize: 13, maxWidth: 480, margin: "0 auto" }}>
            Click "Run backtest" to simulate this strategy over the selected historical period.
            Results include P&L, win rate, drawdown, and Sharpe ratio.
          </div>
        </div>
      )}

      {running && (
        <div className="card" style={{ padding: 60, textAlign: "center" }}>
          <div className="mono" style={{ fontSize: 14, color: "var(--brand)", marginBottom: 10 }}>Simulating {period} of historical ticks...</div>
          <div style={{ width: 320, height: 4, background: "var(--surface-2)", borderRadius: 2, margin: "0 auto", overflow: "hidden" }}>
            <div style={{ width: "60%", height: "100%", background: "var(--brand)", animation: "scan 1.1s linear infinite" }}/>
          </div>
          <style>{`@keyframes scan { 0% { transform: translateX(-100%); } 100% { transform: translateX(280%); } }`}</style>
        </div>
      )}

      {result && (
        <>
          <div className="grid" style={{ gridTemplateColumns: "repeat(5, 1fr)", marginBottom: 16 }}>
            <div className="kpi"><div className="kpi-label">Net P&L</div><div className="kpi-value" style={{color:result.total>=0?"var(--up)":"var(--down)"}}>{result.total>=0?"+":""}{fmtINR(result.total, 0)}</div><div className={"kpi-foot " + (result.total >=0 ?"up":"down")}>{period} simulation</div></div>
            <div className="kpi"><div className="kpi-label">Win rate</div><div className="kpi-value">{result.winRate}%</div><div className="kpi-foot muted">of {result.trades} trades</div></div>
            <div className="kpi"><div className="kpi-label">Avg / trade</div><div className="kpi-value mono">{fmtINR(result.avgTrade, 0)}</div><div className="kpi-foot muted">{result.trades} total</div></div>
            <div className="kpi"><div className="kpi-label">Max drawdown</div><div className="kpi-value" style={{color:"var(--down)"}}>{result.maxDrawdown}%</div><div className="kpi-foot down">peak to trough</div></div>
            <div className="kpi"><div className="kpi-label">Sharpe ratio</div><div className="kpi-value">{result.sharpe}</div><div className={"kpi-foot " + (result.sharpe >= 1.5 ? "up" : "")}>{result.sharpe >= 1.5 ? "Excellent" : result.sharpe >= 1 ? "Good" : "Acceptable"}</div></div>
          </div>

          <div className="card" style={{ marginBottom: 16 }}>
            <div className="card-title">Equity curve</div>
            <AreaChart data={result.equity} valueKey="cumul" labelKey="date" height={300}/>
          </div>

          <div className="card">
            <div className="card-title">Daily returns</div>
            <BarChart data={result.equity} valueKey="pnl" height={200}/>
          </div>
        </>
      )}
    </div>
  );
};

/* ---------------- SETTINGS ---------------- */
const SettingsScreen = () => {
  const [profile, setProfile]   = React.useState(null); // { mobile, ucc, consumerCode, isConnected, sessionTs }
  const [profileStatus, setProfileStatus] = React.useState("idle"); // idle | saving | saved | error
  const [reconnectOpen, setReconnectOpen] = React.useState(false);
  const [rcTotp, setRcTotp] = React.useState("");
  const [rcMpin, setRcMpin] = React.useState("");
  const [rcErr, setRcErr]   = React.useState("");
  const [rcLoading, setRcLoading] = React.useState(false);

  // Update mobile/UCC/consumer code section
  const [newMobile, setNewMobile]           = React.useState("");
  const [newUcc, setNewUcc]                 = React.useState("");
  const [newConsumerCode, setNewConsumerCode] = React.useState("");

  const [limits, setLimits]     = React.useState({ maxDailyLoss: 15000, maxPositionSize: 100000, maxConcurrentAlgos: 4, autoStopAfterLosingDays: 2 });
  const [limitStatus, setLimitStatus] = React.useState("idle");

  React.useEffect(() => {
    API.loadKotakProfile().then(data => {
      if (data) setProfile(data);
    }).catch(() => {});
    API.loadRiskLimits().then(data => {
      if (data) setLimits(prev => ({ ...prev, ...data }));
    }).catch(() => {});
  }, []);

  function maskMobile(m) {
    if (!m) return "";
    const digits = m.replace(/\D/g, "");
    if (digits.length >= 10) return `+91 ••••• ••${digits.slice(-3)}`;
    return m;
  }

  const saveProfile = async () => {
    if (!newMobile || !newUcc) return;
    setProfileStatus("saving");
    try {
      await API.kotakSaveProfile({ mobile: newMobile, ucc: newUcc, ...(newConsumerCode && { consumerCode: newConsumerCode }) });
      setProfile(p => ({ ...(p ?? {}), mobile: newMobile, ucc: newUcc, ...(newConsumerCode && { consumerCode: newConsumerCode }), isConnected: false }));
      setNewMobile(""); setNewUcc(""); setNewConsumerCode("");
      setProfileStatus("saved");
      setTimeout(() => setProfileStatus("idle"), 2000);
    } catch (e) {
      setProfileStatus("error");
    }
  };

  const reconnect = async (e) => {
    e.preventDefault();
    setRcErr("");
    if (!rcTotp || rcTotp.length !== 6) { setRcErr("Enter the 6-digit TOTP from your authenticator"); return; }
    if (!rcMpin) { setRcErr("Enter your MPIN"); return; }
    setRcLoading(true);
    try {
      await API.kotakConnectDirect({ totp: rcTotp, mpin: rcMpin });
      setProfile(p => ({ ...(p ?? {}), isConnected: true, sessionTs: Date.now() }));
      setReconnectOpen(false); setRcTotp(""); setRcMpin("");
    } catch (ex) {
      setRcErr(ex?.message || "Connection failed — check TOTP and MPIN");
    } finally {
      setRcLoading(false);
    }
  };

  const disconnect = async () => {
    try {
      await API.kotakDisconnect();
      setProfile(p => ({ ...(p ?? {}), isConnected: false, sessionTs: null }));
    } catch (e) {
      console.warn("Disconnect failed:", e);
    }
  };

  const saveLimits = async () => {
    setLimitStatus("saving");
    try {
      await API.saveRiskLimits(limits);
      setLimitStatus("saved");
      setTimeout(() => setLimitStatus("idle"), 2000);
    } catch (e) {
      setLimitStatus("error");
    }
  };

  return (
    <div className="page">
      <h2 className="page-title">Settings</h2>
      <div className="page-sub">Kotak Neo connection, risk limits, and notification preferences</div>

      <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 16 }}>
        <div className="card">
          <div className="card-title">Kotak Neo Account</div>

          {/* Status row */}
          <div className="row-between" style={{ marginBottom: 14 }}>
            <div>
              {profile?.isConnected
                ? <span className="chip up"><Icon name="check" size={12}/> Session active</span>
                : <span className="chip">Not connected</span>}
              {profile?.mobile && (
                <div style={{ marginTop: 6, fontSize: 12, color: "var(--text-3)" }}>
                  {maskMobile(profile.mobile)} &nbsp;·&nbsp; UCC: {profile.ucc}
                  {profile.consumerCode
                    ? <> &nbsp;·&nbsp; Consumer: <span style={{ color: "var(--up)" }}>{profile.consumerCode.slice(0, 6)}…</span></>
                    : <> &nbsp;·&nbsp; <span style={{ color: "var(--down)" }}>No consumer code</span></>
                  }
                </div>
              )}
              {profile?.sessionTs && profile?.isConnected && (
                <div style={{ marginTop: 2, fontSize: 11, color: "var(--text-3)" }}>
                  Connected at {new Date(profile.sessionTs).toLocaleTimeString("en-IN", { hour: "2-digit", minute: "2-digit" })}
                </div>
              )}
            </div>
            <div className="row" style={{ gap: 6 }}>
              <button className="btn btn-primary btn-sm" onClick={() => { setReconnectOpen(v => !v); setRcErr(""); }}>
                {reconnectOpen ? "Cancel" : "Reconnect Kotak"}
              </button>
              {profile?.isConnected && (
                <button className="btn btn-secondary btn-sm" onClick={disconnect}>Disconnect</button>
              )}
            </div>
          </div>

          {/* Inline reconnect form */}
          {reconnectOpen && (
            <form onSubmit={reconnect} style={{ background: "var(--surface-2)", borderRadius: 10, padding: 14, marginBottom: 14 }}>
              <div style={{ fontSize: 13, fontWeight: 600, marginBottom: 12 }}>Re-authenticate with Kotak</div>
              <div className="field" style={{ marginBottom: 10 }}>
                <label className="field-label">
                  TOTP
                  <span className="muted" style={{ fontWeight: 400, marginLeft: 6 }}>from Google/Microsoft Authenticator</span>
                </label>
                <input className="input mono" placeholder="123456" maxLength={6} inputMode="numeric"
                  value={rcTotp} onChange={e => setRcTotp(e.target.value.replace(/\D/g, "").slice(0, 6))} autoFocus/>
              </div>
              <div className="field" style={{ marginBottom: 12 }}>
                <label className="field-label">MPIN</label>
                <input className="input mono" type="password" placeholder="••••••" value={rcMpin}
                  onChange={e => setRcMpin(e.target.value)}/>
              </div>
              {rcErr && <div style={{ color: "var(--down)", fontSize: 12, marginBottom: 8 }}>{rcErr}</div>}
              <button type="submit" className="btn btn-primary btn-sm" disabled={rcLoading}>
                {rcLoading ? "Connecting…" : "Connect"}
              </button>
              <div style={{ marginTop: 10, fontSize: 11, color: "var(--text-3)" }}>
                TOTP and MPIN are never stored. They are used once to authenticate with Kotak.
              </div>
            </form>
          )}

          <hr className="hr" style={{ margin: "16px 0" }}/>

          {/* Update mobile / UCC / consumer code */}
          <div style={{ fontSize: 13, fontWeight: 600, marginBottom: 10 }}>Update mobile / UCC / Consumer code</div>
          <div className="field" style={{ marginBottom: 10 }}>
            <label className="field-label">Mobile number</label>
            <input className="input" placeholder="+91XXXXXXXXXX" value={newMobile}
              onChange={e => setNewMobile(e.target.value)}/>
          </div>
          <div className="field" style={{ marginBottom: 10 }}>
            <label className="field-label">UCC (5 characters)</label>
            <input className="input mono" placeholder="AB123" maxLength={6} value={newUcc}
              onChange={e => setNewUcc(e.target.value.toUpperCase())}/>
          </div>
          <div className="field" style={{ marginBottom: 12 }}>
            <label className="field-label">Consumer code <span className="muted" style={{ fontWeight: 400 }}>(optional)</span></label>
            <input className="input mono" placeholder="consumer key / code" value={newConsumerCode}
              onChange={e => setNewConsumerCode(e.target.value)}/>
          </div>
          <button className="btn btn-secondary btn-sm" onClick={saveProfile}
            disabled={profileStatus === "saving" || !newMobile || !newUcc}>
            {profileStatus === "saving" ? "Saving…" : profileStatus === "saved" ? "✓ Saved" : "Save"}
          </button>
          {profileStatus === "error" && <div style={{ color: "var(--down)", fontSize: 12, marginTop: 8 }}>Save failed — check Firebase connection</div>}
        </div>

        <div className="card">
          <div className="card-title">Risk limits</div>
          <div className="field" style={{ marginBottom: 12 }}>
            <label className="field-label">Max daily loss (₹)</label>
            <input className="input mono" type="number" value={limits.maxDailyLoss}
              onChange={e => setLimits(p => ({ ...p, maxDailyLoss: +e.target.value }))}/>
          </div>
          <div className="field" style={{ marginBottom: 12 }}>
            <label className="field-label">Max position size (₹)</label>
            <input className="input mono" type="number" value={limits.maxPositionSize}
              onChange={e => setLimits(p => ({ ...p, maxPositionSize: +e.target.value }))}/>
          </div>
          <div className="field" style={{ marginBottom: 12 }}>
            <label className="field-label">Max concurrent algos</label>
            <input className="input mono" type="number" value={limits.maxConcurrentAlgos}
              onChange={e => setLimits(p => ({ ...p, maxConcurrentAlgos: +e.target.value }))}/>
          </div>
          <div className="field" style={{ marginBottom: 12 }}>
            <label className="field-label">Auto-stop after losing days</label>
            <input className="input mono" type="number" value={limits.autoStopAfterLosingDays}
              onChange={e => setLimits(p => ({ ...p, autoStopAfterLosingDays: +e.target.value }))}/>
          </div>
          <button className="btn btn-primary btn-sm" style={{ marginTop: 4 }} onClick={saveLimits}
            disabled={limitStatus === "saving"}>
            {limitStatus === "saving" ? "Saving…" : limitStatus === "saved" ? "✓ Saved" : "Save limits"}
          </button>
          {limitStatus === "error" && <div style={{ color: "var(--down)", fontSize: 12, marginTop: 8 }}>Save failed</div>}
        </div>

        <div className="card">
          <div className="card-title">Notifications</div>
          <NotifRow label="Trade fills" def={true}/>
          <NotifRow label="Stop-loss hits" def={true}/>
          <NotifRow label="Take-profit hits" def={true}/>
          <NotifRow label="Algo started/stopped" def={true}/>
          <NotifRow label="Margin warnings" def={true}/>
          <NotifRow label="Daily summary email" def={true}/>
          <NotifRow label="WhatsApp alerts" def={false}/>
        </div>

        <div className="card">
          <div className="card-title">Trading hours</div>
          <div className="field" style={{ marginBottom: 12 }}>
            <label className="field-label">Algos start at</label>
            <input className="input mono" type="time" defaultValue="09:20"/>
          </div>
          <div className="field" style={{ marginBottom: 12 }}>
            <label className="field-label">Algos stop placing new trades at</label>
            <input className="input mono" type="time" defaultValue="15:00"/>
          </div>
          <div className="field" style={{ marginBottom: 12 }}>
            <label className="field-label">Force square-off at</label>
            <input className="input mono" type="time" defaultValue="15:20"/>
          </div>
          <div style={{ background: "var(--surface-2)", padding: 12, borderRadius: 8, fontSize: 12, color: "var(--text-2)" }}>
            <Icon name="info" size={12}/> Velox will block all new entries after the cutoff time but will still manage existing positions.
          </div>
        </div>
      </div>
    </div>
  );
};

const NotifRow = ({ label, def }) => {
  const [on, setOn] = React.useState(def);
  return (
    <div className="row-between" style={{ padding: "10px 0", borderBottom: "1px solid var(--border)" }}>
      <span style={{ fontSize: 13 }}>{label}</span>
      <button onClick={() => setOn(v => !v)}
        style={{
          width: 36, height: 20, borderRadius: 99,
          background: on ? "var(--brand)" : "var(--surface-3)",
          position: "relative", transition: "background .15s",
        }}>
        <span style={{
          position: "absolute", top: 2, left: on ? 18 : 2,
          width: 16, height: 16, borderRadius: "50%", background: "white",
          transition: "left .15s",
        }}/>
      </button>
    </div>
  );
};

/* ─────────────────────────────────────────────────────────────────────────────
   STRATEGY GUIDE  —  one page per algo, full decision logic explained
   ───────────────────────────────────────────────────────────────────────────── */

const STRATEGY_DOCS = [
  {
    id: "max-profit",
    name: "Max Profit",
    icon: "★",
    tagline: "Cluster-momentum across watchlist stocks → buy index options",
    color: "#10b981",
    overview: `Max Profit watches a basket of stocks (your watchlist) for SYNCHRONIZED directional moves and uses the cluster as a signal to buy index options. It fits a least-squares regression line through each stock's last N seconds of ticks (default 45s) — the slope tells you whether each stock is currently trending, not just where it ended up. When ≥ K stocks are trending in the same direction with slope beyond the threshold, the strategy buys the best CE (cluster up) or PE (cluster down) from your pre-configured option pool within your budget.`,
    whichOption: [
      { cond: "≥ triggerStockCount stocks have slope ≥ +triggerThresholdPct% over observationWindowSec", action: "BUY CALL (CE)", reason: "Broad-market push up — calls profit" },
      { cond: "≥ triggerStockCount stocks have slope ≤ −triggerThresholdPct%", action: "BUY PUT (PE)", reason: "Broad-market push down — puts profit" },
      { cond: "Mixed (both sides meet threshold) — CE wins by order of check", action: "BUY CALL (CE)", reason: "Tie-break: bullish bias by default" },
    ],
    entryRules: [
      "Each stock has its own rolling tick window (observationWindowSec, default 45s)",
      "Compute slope via least-squares regression of (timestamp, price)",
      "Stock counts as 'up' if slope-equivalent return ≥ +triggerThresholdPct, 'down' if ≤ −triggerThresholdPct",
      "Synchronous entering guard prevents same-batch double-fire (replaces cooldown)",
      "Best option = closest to (but under) optionBudget within the matching CE/PE pool",
    ],
    exitRules: [
      "LIMIT: option premium reaches entry × (1 + limitProfitPct/100) — simulated locally, market sell when crossed",
      "SL: option premium drops to entry × (1 − stopLossPct/100) — safety market sell",
      "TIMEOUT: timeStopSec elapsed since fill — market sell at whatever price",
      "No cooldown after exit — re-enters immediately if cluster trigger fires again",
    ],
    flow: [
      { step: "1", label: "Subscribe stocks + options", detail: "Worker subscribes pickedStocks (nse_cm) + pickedOptions (nse_fo) tokens at start" },
      { step: "2", label: "Maintain per-stock window", detail: "Rolling ticks for observationWindowSec per stock" },
      { step: "3", label: "Compute slopes", detail: "Least-squares slope of (ts, price); convert to % over window" },
      { step: "4", label: "Count up/down", detail: "upCount = #stocks slope ≥ threshold; downCount = #stocks slope ≤ −threshold" },
      { step: "5", label: "Trigger", detail: "If upCount ≥ K → CE; else if downCount ≥ K → PE; else watch" },
      { step: "6", label: "Pick best option", detail: "Filter pool by type+budget, pick option closest to (but under) budget" },
      { step: "7", label: "Place MKT BUY", detail: "MIS, DAY, qty = lotSize from scrip master" },
      { step: "8", label: "Manage exits", detail: "Tick-by-tick: LIMIT / SL / TIMEOUT — whichever fires first" },
    ],
    params: [
      { name: "triggerStockCount", default: "3", desc: "Number of stocks needed in same direction to fire" },
      { name: "triggerThresholdPct", default: "0.2%", desc: "Per-stock slope threshold (window-equivalent return)" },
      { name: "observationWindowSec", default: "45s", desc: "Rolling window for slope per stock" },
      { name: "limitProfitPct", default: "2%", desc: "Sell when premium reaches this % above entry" },
      { name: "stopLossPct", default: "15%", desc: "Safety market sell if premium drops this % below entry" },
      { name: "timeStopSec", default: "90s", desc: "Market sell if neither LIMIT nor SL fires by then" },
      { name: "optionBudget", default: "₹10,000", desc: "Maximum spend per trade — picks option closest to this" },
      { name: "dummyMode", default: "ON", desc: "When ON, skips real orders and logs to /users/{uid}/dummyOrders" },
    ],
    risk: "Medium — depends on stock-cluster correlation with index. Slope filter rejects spike-and-fade and noisy chop. Best for sector-wide moves (banking, IT clusters).",
  },
  {
    id: "candle-burst",
    name: "Candle Burst",
    icon: "🕯",
    tagline: "Japanese candlestick patterns on 1-min index spot",
    color: "#f59e0b",
    overview: `Candle Burst builds 1-minute OHLC candles from the index spot tick stream and runs classic Japanese candlestick pattern detection on each candle close. When a bullish pattern fires it buys a CE; bearish fires a PE. Two exit strategies are user-selectable: "Limit + Time stop" (fixed targets) or "Pattern reversal + Trail" (let winners run, exit on opposite pattern or trailing stop from peak).`,
    whichOption: [
      { cond: "Bullish engulfing / Hammer / Bull Marubozu detected on candle close", action: "BUY CALL (CE)", reason: "Pattern theory predicts continuation up" },
      { cond: "Bearish engulfing / Shooting Star / Bear Marubozu detected on candle close", action: "BUY PUT (PE)", reason: "Pattern theory predicts continuation down" },
    ],
    entryRules: [
      "Accumulate spot ticks into candleSec-second buckets (default 60s)",
      "On candle close, run detectPattern(prev, current)",
      "Marubozu: body ≥ 90% of total range (almost no wicks)",
      "Hammer (bull): lower wick ≥ 2× body, tiny upper wick, body ≤ 35% of range",
      "Shooting Star (bear): upper wick ≥ 2× body, tiny lower wick, body ≤ 35% of range",
      "Bullish engulfing: prev red + current green & current body engulfs prev body",
      "Bearish engulfing: prev green + current red & current body engulfs prev body",
      "No cooldown — re-enters as soon as previous position exits",
    ],
    exitRules: [
      "(Always) SL safety: premium ≤ entry × (1 − stopLossPct/100) → market sell",
      "Mode 'timeout': LIMIT (+limitProfitPct%) or TIMEOUT (timeStopSec elapsed)",
      "Mode 'pattern-trail': TRAIL (premium drops trailingStopPct% from peak since entry) or REVERSAL (opposite-direction pattern fires on next candle close)",
    ],
    flow: [
      { step: "1", label: "Subscribe spot + options", detail: "Index spot ticks + pickedOptions tokens" },
      { step: "2", label: "Build 1-min candles", detail: "Bucket spot ticks; first tick of minute = open, max = high, min = low, last = close" },
      { step: "3", label: "Detect pattern on close", detail: "When minute rolls over, run pattern detection on the just-closed candle (using previous candle as context for engulfing)" },
      { step: "4", label: "Trigger", detail: "Bullish pattern → CE; Bearish pattern → PE" },
      { step: "5", label: "Pick option", detail: "Closest to (but under) optionBudget within matching type" },
      { step: "6", label: "Place MKT BUY", detail: "MIS, DAY, qty = lotSize" },
      { step: "7", label: "Manage exits", detail: "Per selected mode (timeout vs pattern-trail). SL always active as safety." },
    ],
    params: [
      { name: "candleSec", default: "60s", desc: "Candle bucket size — 60s = standard 1-min candle" },
      { name: "exitMode", default: "timeout", desc: "timeout = LIMIT + TIMEOUT; pattern-trail = REVERSAL + trailing stop" },
      { name: "limitProfitPct", default: "2%", desc: "(timeout mode) Sell at this profit %" },
      { name: "timeStopSec", default: "90s", desc: "(timeout mode) Market sell after this many seconds" },
      { name: "trailingStopPct", default: "30%", desc: "(pattern-trail mode) Sell when premium drops this % from its peak since entry" },
      { name: "stopLossPct", default: "15%", desc: "Always-active safety net" },
      { name: "optionBudget", default: "₹10,000", desc: "Maximum spend per trade" },
    ],
    risk: "Medium — pattern reliability varies by market regime. Pattern-trail mode lets winners run but may give back gains before triggering. Timeout mode caps holding time at 90s.",
  },
  {
    id: "momentum-burst",
    name: "Momentum Burst",
    icon: "⚡",
    tagline: "Catches sudden directional price spikes on index spot",
    color: "#f59e0b",
    overview: `Momentum Burst watches the index spot in real-time and maintains a 5-second rolling window of ticks. When the simple endpoint return over that 5s window exceeds a configurable threshold, it interprets this as a momentum spike and immediately buys an ATM/near-ATM option to ride the continuation. Exits on premium TP, SL, or decay (if premium stagnates for decayWindow seconds).`,
    whichOption: [
      { cond: "5-sec spot return > +spikeThreshold%", action: "BUY CALL (CE)", reason: "Spot spiking up → calls gain" },
      { cond: "5-sec spot return < −spikeThreshold%", action: "BUY PUT (PE)", reason: "Spot dropping fast → puts gain" },
    ],
    entryRules: [
      "Rolling 5-second window of spot ticks (sliding, not aligned to clock seconds)",
      "Need ≥ 3 ticks in window before signal is valid",
      "Trigger: |( latest − oldest_in_window ) / oldest| × 100 ≥ spikeThreshold",
      "Debounce: 8-second cooldown after every spike (avoids stuttering)",
      "Strike picked from pickedOptions pool via value-aware scoring (40% proximity-to-ATM + 60% value vs trend); falls back to nearest-strike auto-selection if pool empty",
    ],
    exitRules: [
      "TP: option premium rises ≥ tp% from entry → market sell",
      "SL: option premium falls ≥ sl% from entry → market sell",
      "DECAY: held longer than decayWindow seconds without TP/SL → market sell",
    ],
    flow: [
      { step: "1", label: "Subscribe spot + options upfront", detail: "Spot index + ALL pickedOption tokens, so live premiums are tracked before the spike" },
      { step: "2", label: "Maintain 5s window", detail: "Push ticks; drop ticks older than 5s" },
      { step: "3", label: "Spike check", detail: "Window return ≥ threshold AND no open pos AND 8s since last spike" },
      { step: "4", label: "Pick option", detail: "Value-aware regression scoring across same-type options in pool" },
      { step: "5", label: "Place MKT BUY", detail: "MIS, DAY, qty = lotSize" },
      { step: "6", label: "Fill confirm", detail: "First option tick after order sets entry price (no Kotak fill callback)" },
      { step: "7", label: "Monitor TP / SL / decay", detail: "On every option tick: check exit conditions" },
    ],
    params: [
      { name: "spikeThreshold", default: "0.5%", desc: "Minimum 5-sec spot return to trigger entry" },
      { name: "callRange / putRange", default: "0 — ∞", desc: "Strike clamp for auto-pick (only used if pickedOptions empty)" },
      { name: "sl", default: "20%", desc: "Option premium loss % that triggers stop" },
      { name: "tp", default: "40%", desc: "Option premium gain % that triggers profit-take" },
      { name: "decayWindow", default: "45s", desc: "Maximum hold time if neither TP nor SL hits" },
    ],
    risk: "Medium — option premium decay accelerates if the move stalls. 8s debounce + decay exit limit damage on chop days.",
  },
  {
    id: "option-dip-buyer",
    name: "Option Dip Buyer",
    icon: "🎧",
    tagline: "Buys a single leg dipping while peers stay calm",
    color: "#3b82f6",
    overview: `Option Dip Buyer watches a basket of options (your pickedOptions) and looks for a single leg dipping sharply versus its own short-term rolling average — but only when the other legs in the basket remain stable. The thesis: a one-off dip in one strike without a basket-wide move is likely a liquidity blip, not a real direction change, and the leg will mean-revert. Buys the dipping leg, exits on quick recovery (TP), further dip (SL), or time stop.`,
    whichOption: [
      { cond: "Exactly one leg's price drops ≥ dipThresholdPct% from its rolling avg AND peers stay below peerMax", action: "BUY that exact leg", reason: "Mean-reversion bet — liquidity dip in isolation" },
    ],
    entryRules: [
      "Per leg: maintain rolling window of last N ticks (windowTicks, default 30)",
      "leg.avg = mean of window; leg.dipPct = (avg − last) / avg × 100",
      "Need ≥ max(5, windowTicks/2) ticks per leg before any decision",
      "Entry: EXACTLY ONE leg has dipPct ≥ dipThresholdPct AND ALL OTHER legs have dipPct < (dipThresholdPct × maxPeerDipFrac)",
      "If two or more legs are dipping, the move is basket-wide → no entry",
    ],
    exitRules: [
      "TP: premium rises ≥ tpPct% from entry",
      "SL: premium falls ≥ slPct% from entry (deeper dip than expected)",
      "TIME: held maxHoldSecs seconds — exit at market regardless",
    ],
    flow: [
      { step: "1", label: "Subscribe legs", detail: "All options in the basket are subscribed at start" },
      { step: "2", label: "Per-leg rolling window", detail: "Maintain windowTicks ticks per leg; compute avg" },
      { step: "3", label: "Detect single-leg dip", detail: "Exactly one leg ≥ dipThresholdPct AND peers below peerMax" },
      { step: "4", label: "Enter that leg", detail: "Place MKT BUY for the dipping leg, MIS, qty = lotSize" },
      { step: "5", label: "Monitor exits", detail: "Tick-by-tick: TP / SL / time stop" },
    ],
    params: [
      { name: "dipThresholdPct", default: "12%", desc: "Minimum drop from rolling avg to qualify as a dip" },
      { name: "maxPeerDipFrac", default: "0.3", desc: "Fraction of threshold peers can drift (3.6% by default)" },
      { name: "windowTicks", default: "30", desc: "Rolling window size in ticks" },
      { name: "tpPct", default: "15%", desc: "Take-profit target" },
      { name: "slPct", default: "20%", desc: "Stop-loss threshold" },
      { name: "maxHoldSecs", default: "120s", desc: "Maximum hold time" },
    ],
    risk: "Medium — works best in calm, mean-reverting tape. False signals if the whole basket is moving but window hasn't caught up yet. Requires multiple legs to disambiguate true single-leg blips from basket moves.",
  },
  {
    id: "iron-condor",
    name: "Iron Condor",
    icon: "🦅",
    tagline: "Collects premium when market stays range-bound",
    color: "#10b981",
    overview: `Iron Condor is a four-leg options strategy designed to profit from time decay (theta) when the underlying stays within a price range. It simultaneously sells an OTM CE and an OTM PE (the short wings) and buys a further OTM CE and PE (the long wings) as insurance caps. Maximum profit is achieved when the index expires within the inner strikes.`,
    whichOption: [
      { cond: "Always (4 legs at setup)", action: "SELL OTM CE + SELL OTM PE", reason: "Collect premium from both sides" },
      { cond: "Same setup", action: "BUY far OTM CE + BUY far OTM PE", reason: "Cap maximum loss (required margin benefit)" },
    ],
    entryRules: [
      "Entered near market open on expiry day (or 1 day before for weekly expiries)",
      "Short CE strike: spot + upper buffer (e.g. +200 on NIFTY)",
      "Short PE strike: spot − lower buffer (e.g. −200 on NIFTY)",
      "Long CE strike: short CE + wing width (e.g. +100 further OTM)",
      "Long PE strike: short PE − wing width (e.g. −100 further OTM)",
      "All legs same expiry, product NRML",
    ],
    exitRules: [
      "Profit target: close the spread when net premium received decays to 20–30% of original (lock in 70–80% of max profit)",
      "Stop loss: if short strike is breached (spot moves past sold CE or PE), buy back that side at market",
      "Time exit: close all legs 15 minutes before market close on expiry day regardless",
    ],
    flow: [
      { step: "1", label: "Check VIX / range", detail: "High VIX = wider range expected, widen strikes" },
      { step: "2", label: "Calculate strikes", detail: "ATM ± buffer for shorts; shorts ± wing for longs" },
      { step: "3", label: "Place 4 orders", detail: "SELL CE, SELL PE, BUY far CE, BUY far PE (all NRML)" },
      { step: "4", label: "Monitor net premium", detail: "Sum of credits received minus debits paid" },
      { step: "5", label: "Exit at profit target", detail: "Buy back sold legs when net P&L ≥ 70% of max profit" },
      { step: "6", label: "Breach exit", detail: "Spot crosses short strike → buy back that side immediately" },
    ],
    params: [
      { name: "upperBuffer", default: "+200", desc: "Distance above spot for short CE strike" },
      { name: "lowerBuffer", default: "−200", desc: "Distance below spot for short PE strike" },
      { name: "wingWidth", default: "100", desc: "Gap between short and long strikes (insurance)" },
      { name: "profitTarget", default: "70%", desc: "% of max profit at which to close" },
      { name: "breachSL", default: "short strike", desc: "Close side if spot crosses this level" },
    ],
    risk: "Low-Medium — defined risk (max loss = wing width − net premium). Loses when market makes a big directional move.",
  },
  {
    id: "orb",
    name: "Opening Range Breakout",
    icon: "📈",
    tagline: "Trades the first 15-minute candle breakout",
    color: "#6366f1",
    overview: `ORB (Opening Range Breakout) defines the high and low of the first 15 minutes of the trading session (9:15–9:30 AM IST). A breakout above the opening range high is a BUY signal; a breakout below the low is a SELL signal. The logic is that institutional order flow tends to set direction in the first 15 minutes, and the breakout of that range shows conviction.`,
    whichOption: [
      { cond: "Price closes above ORB high on 1-min candle", action: "BUY CALL (CE) — ATM or 1 strike OTM", reason: "Bullish breakout — CE gains as index rises" },
      { cond: "Price closes below ORB low on 1-min candle", action: "BUY PUT (PE) — ATM or 1 strike OTM", reason: "Bearish breakdown — PE gains as index falls" },
    ],
    entryRules: [
      "Wait for 9:30 AM — let the opening range (9:15–9:30) form completely",
      "Record ORB high and ORB low",
      "On the first 1-min candle that closes above ORB high → BUY CE (ATM or nearest OTM strike)",
      "On the first 1-min candle that closes below ORB low → BUY PE (ATM or nearest OTM strike)",
      "Only one direction per day — first signal wins",
      "No entry after 1:00 PM (option premium time decay accelerates)",
    ],
    exitRules: [
      "Stop Loss: option entry price − SL% (e.g. 30% of premium) OR price reverses back into the opening range",
      "Take Profit: option premium gains TP% from entry (e.g. 80–100%)",
      "Time exit: close all positions by 3:00 PM regardless",
    ],
    flow: [
      { step: "1", label: "9:15–9:30 AM: record range", detail: "Mark ORB_HIGH = max(candles), ORB_LOW = min(candles)" },
      { step: "2", label: "9:30 AM: start watching", detail: "Monitor 1-min candles for close outside range" },
      { step: "3", label: "Breakout detected", detail: "Close > ORB_HIGH → CE signal; Close < ORB_LOW → PE signal" },
      { step: "4", label: "Select strike", detail: "ATM or 1 strike in direction of move; current week expiry" },
      { step: "5", label: "Place BUY order", detail: "MKT order, MIS product, 1 lot" },
      { step: "6", label: "Monitor TP / SL", detail: "Tick-by-tick check; also watch if price re-enters ORB (false breakout)" },
      { step: "7", label: "Exit", detail: "TP hit, SL hit, false-breakout re-entry, or 3 PM time exit" },
    ],
    params: [
      { name: "orbMinutes", default: "15", desc: "Minutes to build the opening range (9:15 to 9:15+N)" },
      { name: "sl", default: "30%", desc: "Premium loss % that closes the trade" },
      { name: "tp", default: "80%", desc: "Premium gain % that closes the trade" },
      { name: "noEntryAfter", default: "13:00", desc: "Stop looking for entries after this time" },
    ],
    risk: "Medium — clean breakouts give strong R:R, but false breakouts (chop days) hit SL frequently. Works best on trend days.",
  },
  {
    id: "vwap-reversion",
    name: "VWAP Mean Reversion",
    icon: "〰️",
    tagline: "Fades extreme moves away from VWAP",
    color: "#8b5cf6",
    overview: `VWAP (Volume Weighted Average Price) is the fair-value benchmark institutional traders use intraday. When price stretches too far from VWAP — measured in standard deviations (σ) of intraday price action — it tends to snap back. This strategy fades (trades against) that extreme extension, buying puts when price is too high and calls when price is too low.`,
    whichOption: [
      { cond: "Price > VWAP + 1.5σ (extended above VWAP)", action: "BUY PUT (PE)", reason: "Price stretched up → fade back down toward VWAP" },
      { cond: "Price < VWAP − 1.5σ (extended below VWAP)", action: "BUY CALL (CE)", reason: "Price stretched down → fade back up toward VWAP" },
    ],
    entryRules: [
      "Calculate intraday VWAP continuously from 9:15 AM using (price × volume) / cumulative volume",
      "Calculate rolling standard deviation of price from VWAP over the session",
      "Signal when: |price − VWAP| > 1.5 × σ",
      "Confirm: no open position, market is not in a strong trend (ADX < 25 preferred)",
      "Enter with ATM option in the fade direction; expiry = nearest weekly",
    ],
    exitRules: [
      "Primary target: price touches VWAP (return to mean)",
      "Stop loss: price extends further to 2.5σ — the extension is accelerating, not reverting",
      "Time stop: if not exited within 30 minutes, close at market",
    ],
    flow: [
      { step: "1", label: "Build VWAP", detail: "Running sum of price×volume / running sum of volume from 9:15 AM" },
      { step: "2", label: "Measure σ deviation", detail: "Standard deviation of (close − VWAP) over session bars" },
      { step: "3", label: "Detect extreme", detail: "|price − VWAP| > 1.5σ?" },
      { step: "4", label: "Direction", detail: "Above VWAP → PE (fade down); Below VWAP → CE (fade up)" },
      { step: "5", label: "Enter ATM option", detail: "Buy ATM of fade direction, MIS, current weekly expiry" },
      { step: "6", label: "Target: VWAP touch", detail: "Close position when price crosses VWAP" },
      { step: "7", label: "SL: 2.5σ extension", detail: "If move continues instead of reverting, cut loss" },
    ],
    params: [
      { name: "entryBand", default: "1.5σ", desc: "Deviation from VWAP to trigger entry" },
      { name: "slBand", default: "2.5σ", desc: "Deviation at which the trade is wrong — cut loss" },
      { name: "timeStop", default: "30 min", desc: "Maximum time to hold if VWAP touch not reached" },
      { name: "minVolume", default: "200% avg", desc: "Volume filter — only enter if volume confirms the move" },
    ],
    risk: "Medium — reversion is reliable in sideways markets but dangerous in strong trend days. The 2.5σ SL caps damage.",
  },
  {
    id: "gap-fade",
    name: "Gap Up / Down Fade",
    icon: "🔻",
    tagline: "Fades opening gaps that lack follow-through",
    color: "#ef4444",
    overview: `When the market opens significantly higher (gap up) or lower (gap down) than the previous close, retail traders often chase the move expecting continuation. The Gap Fade strategy does the opposite — it bets that the gap will partially fill when no strong follow-through arrives in the first 15 minutes. The signal is a gap with weak momentum: the gap opened big but the first 15 minutes are quiet.`,
    whichOption: [
      { cond: "Gap UP (open > prev close by > 0.5%) + first 15 min range is small (weak momentum)", action: "BUY PUT (PE)", reason: "Gap is fading back toward prev close — puts profit as index falls" },
      { cond: "Gap DOWN (open < prev close by > 0.5%) + first 15 min range is small", action: "BUY CALL (CE)", reason: "Gap filling back up — calls profit as index rises" },
    ],
    entryRules: [
      "Pre-market: calculate gap = (today open − yesterday close) / yesterday close × 100",
      "Gap must be ≥ 0.5% (configurable) to qualify",
      "At 9:30 AM: check first 15-min candle range (high − low)",
      "Weak momentum = first 15-min range < 0.3% of spot (market is coiling, not following through)",
      "Enter at 9:31 AM after confirmation: CE for gap-down fade, PE for gap-up fade",
      "No entry if VIX spike > 20% (high vol days, gap may not fill)",
    ],
    exitRules: [
      "Target: gap fills 50% (price moves halfway back to previous close)",
      "Stop loss: price extends in the gap direction by SL% of the option premium",
      "Time exit: 11:30 AM — gap fades typically play out in first 2 hours; stale setups become directional",
    ],
    flow: [
      { step: "1", label: "Pre-open: measure gap", detail: "gap% = (open − prevClose) / prevClose × 100" },
      { step: "2", label: "Filter: gap ≥ 0.5%?", detail: "Skip if gap is too small to be meaningful" },
      { step: "3", label: "9:30 AM: measure ORB range", detail: "range = (ORB_HIGH − ORB_LOW) / spot × 100" },
      { step: "4", label: "Weak follow-through?", detail: "range < 0.3% confirms weak momentum" },
      { step: "5", label: "Enter fade direction", detail: "Gap up → BUY PE; Gap down → BUY CE at 9:31 AM" },
      { step: "6", label: "Target 50% gap fill", detail: "e.g. gap = 100pts → target 50pts of fill" },
      { step: "7", label: "Exit at target / SL / 11:30 AM", detail: "Whichever comes first" },
    ],
    params: [
      { name: "minGapPct", default: "0.5%", desc: "Minimum gap size to consider the setup" },
      { name: "weakMomentumRange", default: "0.3%", desc: "Max first-15min range to confirm weak follow-through" },
      { name: "gapFillTarget", default: "50%", desc: "% of the gap to target for profit" },
      { name: "sl", default: "35%", desc: "Option premium loss % before cutting" },
      { name: "timeStop", default: "11:30 AM", desc: "Hard close time regardless of P&L" },
    ],
    risk: "Medium-High — on days with strong directional gap continuation, the fade fails and hits SL. Works best 3–4 days per week; avoid on RBI/Fed event days.",
  },
  {
    id: "scalp-tight",
    name: "Tight-Stop Scalper",
    icon: "🎯",
    tagline: "Fast 5–8 tick scalps on 1-min candles",
    color: "#ec4899",
    overview: `The Tight-Stop Scalper takes very short-lived directional bets on 1-minute candles using a combination of candle structure and momentum. It enters on strong candle closes, targets 5–8 ticks of option move, and cuts immediately if the trade goes wrong. The win rate is high because targets are small and stops are tight; the strategy relies on volume of trades rather than large per-trade gains.`,
    whichOption: [
      { cond: "1-min candle closes bullish with body > 60% of range AND volume spike", action: "BUY CALL (CE)", reason: "Strong close with volume = institutional buying" },
      { cond: "1-min candle closes bearish with body > 60% of range AND volume spike", action: "BUY PUT (PE)", reason: "Strong close with volume = institutional selling" },
    ],
    entryRules: [
      "Only between 9:30 AM – 2:00 PM (avoid open chop and late-day low volume)",
      "1-min candle body must be > 60% of the candle's total range (strong directional close)",
      "Volume on that candle must be ≥ 150% of the 20-candle average volume",
      "RSI(14) on 1-min must be 45–70 for CE entry, 30–55 for PE entry (avoid overbought/oversold fades)",
      "Enter on next candle open immediately after signal candle closes",
      "Max 6 scalp trades per day to limit overtrading",
    ],
    exitRules: [
      "Target: 5–8 ticks of option move from entry (e.g. ₹5–8 on a ₹100 option)",
      "Stop loss: 3–5 ticks — very tight, taken immediately, no averaging",
      "If entry candle's low (for CE) or high (for PE) is breached on the next candle: exit immediately",
    ],
    flow: [
      { step: "1", label: "Each 1-min candle close", detail: "Check body%, volume ratio, RSI" },
      { step: "2", label: "All conditions met?", detail: "body>60%, vol≥150% avg, RSI in range" },
      { step: "3", label: "Direction", detail: "Bullish candle → CE; Bearish candle → PE" },
      { step: "4", label: "Enter on next open", detail: "Immediate MKT BUY, ATM strike, MIS, current expiry" },
      { step: "5", label: "Set tick target", detail: "Entry price + 5–8 ticks → place limit SELL" },
      { step: "6", label: "Monitor 1 candle", detail: "If next candle invalidates (closes against), exit at market" },
      { step: "7", label: "Hard SL: 3–5 ticks", detail: "If price drops 3–5 ticks from entry, close at market immediately" },
    ],
    params: [
      { name: "minBodyPct", default: "60%", desc: "Minimum candle body as % of range" },
      { name: "volumeMultiplier", default: "1.5×", desc: "Volume must be this many times the 20-candle average" },
      { name: "tickTarget", default: "5–8", desc: "Option price ticks to target" },
      { name: "tickSL", default: "3–5", desc: "Option price ticks at which to stop out" },
      { name: "maxTrades", default: "6 / day", desc: "Daily trade cap to avoid overtrading" },
    ],
    risk: "High — frequent entries mean transaction costs add up. Tight SL means getting stopped out often. Requires low-latency execution; slippage on MKT orders in illiquid strikes kills P&L.",
  },
];

const StrategyGuideScreen = () => {
  const [activeId, setActiveId] = React.useState(STRATEGY_DOCS[0].id);
  const doc = STRATEGY_DOCS.find(d => d.id === activeId);

  return (
    <div className="page">
      <div style={{ marginBottom: 20 }}>
        <h2 className="page-title">Strategy Guide</h2>
        <div className="page-sub">Learn exactly how each algorithm works — entry conditions, which option to buy, and exit rules</div>
      </div>

      {/* Strategy tab strip */}
      <div className="row" style={{ gap: 8, marginBottom: 24, flexWrap: "wrap" }}>
        {STRATEGY_DOCS.map(d => (
          <button key={d.id}
            onClick={() => setActiveId(d.id)}
            style={{
              padding: "8px 14px", borderRadius: 10, border: "1px solid",
              borderColor: activeId === d.id ? d.color : "var(--border)",
              background: activeId === d.id ? d.color + "22" : "var(--surface-2)",
              color: activeId === d.id ? d.color : "var(--text-2)",
              fontWeight: activeId === d.id ? 700 : 500,
              fontSize: 13, cursor: "pointer", whiteSpace: "nowrap",
            }}>
            {d.icon} {d.name}
          </button>
        ))}
      </div>

      {doc && (
        <div style={{ display: "flex", flexDirection: "column", gap: 20 }}>

          {/* Hero */}
          <div className="card" style={{ padding: "20px 24px", borderLeft: `4px solid ${doc.color}` }}>
            <div className="row" style={{ gap: 16, alignItems: "flex-start" }}>
              <div style={{
                width: 56, height: 56, borderRadius: 14, fontSize: 28,
                background: doc.color + "22", display: "grid", placeItems: "center", flexShrink: 0,
              }}>{doc.icon}</div>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 20, fontWeight: 800, letterSpacing: "-.02em", marginBottom: 4 }}>{doc.name}</div>
                <div style={{ fontSize: 13, color: "var(--text-3)", marginBottom: 12 }}>{doc.tagline}</div>
                <p style={{ margin: 0, fontSize: 14, color: "var(--text-2)", lineHeight: 1.7 }}>{doc.overview}</p>
              </div>
            </div>
          </div>

          {/* Which option gets bought */}
          <div className="card" style={{ padding: "18px 22px" }}>
            <div style={{ fontSize: 13, fontWeight: 700, textTransform: "uppercase", letterSpacing: ".06em", color: "var(--text-3)", marginBottom: 14 }}>
              Which Option Gets Bought
            </div>
            <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
              {doc.whichOption.map((row, i) => (
                <div key={i} style={{
                  display: "grid", gridTemplateColumns: "1fr auto 1fr",
                  alignItems: "center", gap: 12,
                  background: "var(--surface-2)", borderRadius: 10, padding: "12px 16px",
                }}>
                  <div>
                    <div style={{ fontSize: 11, fontWeight: 700, color: "var(--text-3)", marginBottom: 3 }}>CONDITION</div>
                    <div style={{ fontSize: 13, fontWeight: 600 }}>{row.cond}</div>
                  </div>
                  <div style={{
                    padding: "6px 14px", borderRadius: 8, fontSize: 13, fontWeight: 800,
                    background: row.action.includes("CALL") ? "var(--up)" : "var(--down)",
                    color: "white", whiteSpace: "nowrap",
                  }}>{row.action}</div>
                  <div>
                    <div style={{ fontSize: 11, fontWeight: 700, color: "var(--text-3)", marginBottom: 3 }}>WHY</div>
                    <div style={{ fontSize: 13, color: "var(--text-2)" }}>{row.reason}</div>
                  </div>
                </div>
              ))}
            </div>
          </div>

          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 20 }}>
            {/* Entry rules */}
            <div className="card" style={{ padding: "18px 22px" }}>
              <div style={{ fontSize: 13, fontWeight: 700, textTransform: "uppercase", letterSpacing: ".06em", color: "var(--text-3)", marginBottom: 14 }}>
                Entry Conditions
              </div>
              <ol style={{ margin: 0, paddingLeft: 20, display: "flex", flexDirection: "column", gap: 8 }}>
                {doc.entryRules.map((r, i) => (
                  <li key={i} style={{ fontSize: 13, color: "var(--text-2)", lineHeight: 1.55 }}>{r}</li>
                ))}
              </ol>
            </div>

            {/* Exit rules */}
            <div className="card" style={{ padding: "18px 22px" }}>
              <div style={{ fontSize: 13, fontWeight: 700, textTransform: "uppercase", letterSpacing: ".06em", color: "var(--text-3)", marginBottom: 14 }}>
                Exit Rules
              </div>
              <ol style={{ margin: 0, paddingLeft: 20, display: "flex", flexDirection: "column", gap: 8 }}>
                {doc.exitRules.map((r, i) => (
                  <li key={i} style={{ fontSize: 13, color: "var(--text-2)", lineHeight: 1.55 }}>{r}</li>
                ))}
              </ol>
            </div>
          </div>

          {/* Decision flow */}
          <div className="card" style={{ padding: "18px 22px" }}>
            <div style={{ fontSize: 13, fontWeight: 700, textTransform: "uppercase", letterSpacing: ".06em", color: "var(--text-3)", marginBottom: 16 }}>
              Decision Flow
            </div>
            <div style={{ display: "flex", flexDirection: "column", gap: 0 }}>
              {doc.flow.map((step, i) => (
                <div key={i} style={{ display: "flex", gap: 16, alignItems: "flex-start" }}>
                  <div style={{ display: "flex", flexDirection: "column", alignItems: "center", flexShrink: 0 }}>
                    <div style={{
                      width: 32, height: 32, borderRadius: "50%", fontSize: 13, fontWeight: 800,
                      background: doc.color, color: "white",
                      display: "grid", placeItems: "center",
                    }}>{step.step}</div>
                    {i < doc.flow.length - 1 && (
                      <div style={{ width: 2, height: 28, background: "var(--border)", margin: "2px 0" }}/>
                    )}
                  </div>
                  <div style={{ paddingBottom: i < doc.flow.length - 1 ? 12 : 0, paddingTop: 5 }}>
                    <div style={{ fontSize: 14, fontWeight: 700, marginBottom: 2 }}>{step.label}</div>
                    <div style={{ fontSize: 12, color: "var(--text-3)", fontFamily: "monospace" }}>{step.detail}</div>
                  </div>
                </div>
              ))}
            </div>
          </div>

          {/* Parameters */}
          <div className="card" style={{ padding: "18px 22px" }}>
            <div style={{ fontSize: 13, fontWeight: 700, textTransform: "uppercase", letterSpacing: ".06em", color: "var(--text-3)", marginBottom: 14 }}>
              Configurable Parameters
            </div>
            <div style={{ overflowX: "auto" }}>
              <table style={{ width: "100%", borderCollapse: "collapse", fontSize: 13 }}>
                <thead>
                  <tr style={{ borderBottom: "1px solid var(--border)" }}>
                    <th style={{ textAlign: "left", padding: "6px 12px 8px 0", color: "var(--text-3)", fontWeight: 700, fontSize: 11, textTransform: "uppercase" }}>Parameter</th>
                    <th style={{ textAlign: "left", padding: "6px 12px 8px", color: "var(--text-3)", fontWeight: 700, fontSize: 11, textTransform: "uppercase" }}>Default</th>
                    <th style={{ textAlign: "left", padding: "6px 0 8px 12px", color: "var(--text-3)", fontWeight: 700, fontSize: 11, textTransform: "uppercase" }}>Description</th>
                  </tr>
                </thead>
                <tbody>
                  {doc.params.map((p, i) => (
                    <tr key={i} style={{ borderBottom: i < doc.params.length - 1 ? "1px solid var(--border)" : "none" }}>
                      <td style={{ padding: "9px 12px 9px 0", fontFamily: "monospace", fontWeight: 700, color: doc.color }}>{p.name}</td>
                      <td style={{ padding: "9px 12px", fontFamily: "monospace", color: "var(--text-2)" }}>{p.default}</td>
                      <td style={{ padding: "9px 0 9px 12px", color: "var(--text-2)", lineHeight: 1.4 }}>{p.desc}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>

          {/* Risk note */}
          <div style={{
            padding: "14px 18px", borderRadius: 12,
            background: "var(--surface-2)", borderLeft: `3px solid ${doc.color}`,
            fontSize: 13, color: "var(--text-2)", lineHeight: 1.6,
          }}>
            <span style={{ fontWeight: 700, color: doc.color }}>Risk: </span>{doc.risk}
          </div>

        </div>
      )}
    </div>
  );
};

/* ---------------- TRADES (entry → exit pairs with P&L) ---------------- */
const TradesScreen = () => {
  const [trades, setTrades] = React.useState([]);
  const [modeFilter, setModeFilter] = React.useState("all");
  const [algoFilter, setAlgoFilter] = React.useState("all");
  const [dateFrom, setDateFrom] = React.useState("");
  const [dateTo, setDateTo]     = React.useState("");
  const [configNameFilter, setConfigNameFilter] = React.useState("all");
  const [expandedConfig, setExpandedConfig] = React.useState(null);

  React.useEffect(() => {
    const unsub = API.listenTrades(setTrades, 500);
    return () => unsub();
  }, []);

  const filtered = trades.filter(t => {
    if (modeFilter === "dummy" && !t.dummyMode) return false;
    if (modeFilter === "live"  &&  t.dummyMode) return false;
    if (algoFilter !== "all"   && t.algoId !== algoFilter) return false;
    if (dateFrom) {
      const from = new Date(dateFrom).setHours(0,0,0,0);
      if ((t.exitTs ?? 0) < from) return false;
    }
    if (dateTo) {
      const to = new Date(dateTo).setHours(23,59,59,999);
      if ((t.exitTs ?? 0) > to) return false;
    }
    if (configNameFilter !== "all" && t.configName !== configNameFilter) return false;
    return true;
  });

  const algos = [...new Set(trades.map(t => t.algoId).filter(Boolean))];
  const configNames = [...new Set(trades.map(t => t.configName).filter(Boolean))];

  // Aggregate stats
  const totalPnl  = filtered.reduce((s, t) => s + (t.pnl ?? 0), 0);
  const winners   = filtered.filter(t => (t.pnl ?? 0) > 0);
  const losers    = filtered.filter(t => (t.pnl ?? 0) < 0);
  const winRate   = filtered.length ? (winners.length / filtered.length * 100) : 0;
  const avgWin    = winners.length ? winners.reduce((s, t) => s + t.pnl, 0) / winners.length : 0;
  const avgLoss   = losers.length  ? losers.reduce((s, t) => s + t.pnl, 0) / losers.length  : 0;

  const fmtMoney = (n) => (n >= 0 ? "+" : "") + "₹" + n.toFixed(0);
  const fmtTime  = (ts) => ts ? new Date(ts).toLocaleTimeString("en-IN", { hour: "2-digit", minute: "2-digit", second: "2-digit" }) : "—";
  const fmtDate  = (ts) => ts ? new Date(ts).toLocaleDateString("en-IN") : "—";

  const reasonColor = (r) => r === "TP" ? "var(--up)" : r === "SL" ? "var(--down)" : "var(--text-2)";

  return (
    <div className="page">
      <div className="row-between" style={{ marginBottom: 16 }}>
        <div>
          <h2 className="page-title">Strategy Trades</h2>
          <div className="page-sub">{filtered.length} trades · {modeFilter === "all" ? "all modes" : modeFilter} · {algoFilter === "all" ? "all strategies" : algoFilter}</div>
        </div>
        <div className="row" style={{ gap: 6 }}>
          {["all", "dummy", "live"].map(m => (
            <button key={m} className={"chip " + (modeFilter === m ? "brand" : "")} onClick={() => setModeFilter(m)}>
              {m === "all" ? "All" : m === "dummy" ? "🧪 Dummy" : "⚠️ Live"}
            </button>
          ))}
        </div>
      </div>

      {/* Summary cards */}
      <div className="grid" style={{ gridTemplateColumns: "repeat(auto-fill, minmax(160px, 1fr))", gap: 10, marginBottom: 16 }}>
        <div className="card" style={{ padding: 14 }}>
          <div style={{ fontSize: 11, color: "var(--text-3)", marginBottom: 4 }}>NET P&L</div>
          <div className="mono" style={{ fontSize: 20, fontWeight: 700, color: totalPnl >= 0 ? "var(--up)" : "var(--down)" }}>{fmtMoney(totalPnl)}</div>
        </div>
        <div className="card" style={{ padding: 14 }}>
          <div style={{ fontSize: 11, color: "var(--text-3)", marginBottom: 4 }}>TRADES</div>
          <div className="mono" style={{ fontSize: 20, fontWeight: 700 }}>{filtered.length}</div>
          <div style={{ fontSize: 11, color: "var(--text-3)", marginTop: 2 }}>{winners.length}W / {losers.length}L</div>
        </div>
        <div className="card" style={{ padding: 14 }}>
          <div style={{ fontSize: 11, color: "var(--text-3)", marginBottom: 4 }}>WIN RATE</div>
          <div className="mono" style={{ fontSize: 20, fontWeight: 700 }}>{winRate.toFixed(0)}%</div>
        </div>
        <div className="card" style={{ padding: 14 }}>
          <div style={{ fontSize: 11, color: "var(--text-3)", marginBottom: 4 }}>AVG WIN</div>
          <div className="mono" style={{ fontSize: 16, fontWeight: 700, color: "var(--up)" }}>{fmtMoney(avgWin)}</div>
        </div>
        <div className="card" style={{ padding: 14 }}>
          <div style={{ fontSize: 11, color: "var(--text-3)", marginBottom: 4 }}>AVG LOSS</div>
          <div className="mono" style={{ fontSize: 16, fontWeight: 700, color: "var(--down)" }}>{fmtMoney(avgLoss)}</div>
        </div>
      </div>

      {/* Config name filter chips */}
      {configNames.length > 0 && (
        <div className="row" style={{ gap: 6, flexWrap: "wrap", marginBottom: 10 }}>
          <button className={"chip " + (configNameFilter === "all" ? "brand" : "")} onClick={() => setConfigNameFilter("all")}>All configs</button>
          {configNames.map(n => (
            <button key={n} className={"chip " + (configNameFilter === n ? "brand" : "")} onClick={() => setConfigNameFilter(n)}>{n}</button>
          ))}
        </div>
      )}

      {/* Algo filter + date filter */}
      <div className="row" style={{ gap: 10, flexWrap: "wrap", marginBottom: 12, alignItems: "center" }}>
        {algos.length > 1 && (
          <div className="row" style={{ gap: 6, flexWrap: "wrap" }}>
            <button className={"chip " + (algoFilter === "all" ? "brand" : "")} onClick={() => setAlgoFilter("all")}>All strategies</button>
            {algos.map(a => (
              <button key={a} className={"chip " + (algoFilter === a ? "brand" : "")} onClick={() => setAlgoFilter(a)}>{a}</button>
            ))}
          </div>
        )}
        <div className="row" style={{ gap: 6, marginLeft: "auto", alignItems: "center" }}>
          <span style={{ fontSize: 12, color: "var(--text-3)" }}>From</span>
          <input type="date" className="input mono" style={{ padding: "4px 8px", fontSize: 12, width: 140 }}
            value={dateFrom} onChange={e => setDateFrom(e.target.value)}/>
          <span style={{ fontSize: 12, color: "var(--text-3)" }}>To</span>
          <input type="date" className="input mono" style={{ padding: "4px 8px", fontSize: 12, width: 140 }}
            value={dateTo} onChange={e => setDateTo(e.target.value)}/>
          {(dateFrom || dateTo) && (
            <button className="chip" onClick={() => { setDateFrom(""); setDateTo(""); }} style={{ fontSize: 11 }}>✕ Clear</button>
          )}
        </div>
      </div>

      {/* Trades table */}
      {filtered.length === 0 ? (
        <div className="card" style={{ padding: 24, textAlign: "center", color: "var(--text-3)" }}>
          No trades yet. Start a strategy in dummy mode to populate this view.
        </div>
      ) : (
        <div className="card" style={{ padding: 0, overflow: "hidden" }}>
          <table style={{ width: "100%", borderCollapse: "collapse", fontSize: 13 }}>
            <thead>
              <tr style={{ background: "var(--surface-2)" }}>
                <th style={{ padding: "10px 12px", textAlign: "left", fontWeight: 600, color: "var(--text-2)" }}>Time</th>
                <th style={{ padding: "10px 12px", textAlign: "left", fontWeight: 600, color: "var(--text-2)" }}>Symbol</th>
                <th style={{ padding: "10px 12px", textAlign: "left", fontWeight: 600, color: "var(--text-2)" }}>Algo</th>
                <th style={{ padding: "10px 12px", textAlign: "right", fontWeight: 600, color: "var(--text-2)" }}>Qty</th>
                <th style={{ padding: "10px 12px", textAlign: "right", fontWeight: 600, color: "var(--text-2)" }}>Entry</th>
                <th style={{ padding: "10px 12px", textAlign: "right", fontWeight: 600, color: "var(--text-2)" }}>Exit</th>
                <th style={{ padding: "10px 12px", textAlign: "right", fontWeight: 600, color: "var(--text-2)" }}>Held</th>
                <th style={{ padding: "10px 12px", textAlign: "right", fontWeight: 600, color: "var(--text-2)" }}>P&L</th>
                <th style={{ padding: "10px 12px", textAlign: "center", fontWeight: 600, color: "var(--text-2)" }}>Reason</th>
                <th style={{ padding: "10px 12px", textAlign: "left", fontWeight: 600, color: "var(--text-2)" }}>Config</th>
                <th style={{ padding: "10px 12px", textAlign: "center", fontWeight: 600, color: "var(--text-2)" }}>Mode</th>
              </tr>
            </thead>
            <tbody>
              {filtered.map(t => (
                <tr key={t.id} style={{ borderTop: "1px solid var(--border)" }}>
                  <td style={{ padding: "10px 12px" }}>
                    <div style={{ fontWeight: 500 }}>{fmtTime(t.exitTs)}</div>
                    <div style={{ fontSize: 11, color: "var(--text-3)" }}>{fmtDate(t.exitTs)}</div>
                  </td>
                  <td style={{ padding: "10px 12px", fontWeight: 600 }}>{t.sym ?? t.tradingSymbol ?? "—"}</td>
                  <td style={{ padding: "10px 12px", color: "var(--text-2)" }}>{t.algoId}</td>
                  <td style={{ padding: "10px 12px", textAlign: "right" }} className="mono">{t.qty}</td>
                  <td style={{ padding: "10px 12px", textAlign: "right" }} className="mono">₹{t.entryPrice?.toFixed(2)}</td>
                  <td style={{ padding: "10px 12px", textAlign: "right" }} className="mono">₹{t.exitPrice?.toFixed(2)}</td>
                  <td style={{ padding: "10px 12px", textAlign: "right", color: "var(--text-3)" }} className="mono">{t.holdSec}s</td>
                  <td style={{ padding: "10px 12px", textAlign: "right" }} className="mono">
                    <span style={{ fontWeight: 700, color: (t.pnl ?? 0) >= 0 ? "var(--up)" : "var(--down)" }}>{fmtMoney(t.pnl ?? 0)}</span>
                    <div style={{ fontSize: 11, color: "var(--text-3)" }}>{(t.pnlPct ?? 0) >= 0 ? "+" : ""}{(t.pnlPct ?? 0).toFixed(1)}%</div>
                  </td>
                  <td style={{ padding: "10px 12px", textAlign: "center" }}>
                    <span className="chip" style={{ fontSize: 10, color: reasonColor(t.exitReason) }}>{t.exitReason}</span>
                  </td>
                  <td style={{ padding: "10px 12px" }}>
                    {t.config ? (
                      <div style={{ position: "relative" }}>
                        <button className="chip" style={{ fontSize: 10, cursor: "pointer", maxWidth: 120, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}
                          onClick={() => setExpandedConfig(expandedConfig === t.id ? null : t.id)}>
                          {t.configName ?? "cfg"} ▾
                        </button>
                        {expandedConfig === t.id && (
                          <div style={{
                            position: "fixed", zIndex: 1000,
                            background: "var(--surface-1)", border: "1px solid var(--border)",
                            borderRadius: 10, padding: "14px 16px", minWidth: 240, fontSize: 12,
                            boxShadow: "0 8px 32px rgba(0,0,0,0.25)", lineHeight: 2,
                            top: "50%", left: "50%", transform: "translate(-50%, -50%)",
                          }}>
                            <div className="row-between" style={{ marginBottom: 10 }}>
                              <span style={{ fontWeight: 700, fontSize: 13 }}>{t.configName ?? "Config"}</span>
                              <button className="chip" style={{ fontSize: 10 }} onClick={() => setExpandedConfig(null)}>✕</button>
                            </div>
                            {Object.entries(t.config).map(([k, v]) => (
                              <div key={k} className="row-between" style={{ gap: 24, borderTop: "1px solid var(--border)", padding: "4px 0" }}>
                                <span style={{ color: "var(--text-3)" }}>{k}</span>
                                <span className="mono" style={{ fontWeight: 600 }}>{String(v)}</span>
                              </div>
                            ))}
                          </div>
                        )}
                      </div>
                    ) : <span style={{ color: "var(--text-3)", fontSize: 11 }}>—</span>}
                  </td>
                  <td style={{ padding: "10px 12px", textAlign: "center" }}>
                    <span className="chip" style={{ fontSize: 10, background: t.dummyMode ? "color-mix(in srgb, var(--brand) 15%, transparent)" : "color-mix(in srgb, var(--down) 15%, transparent)", color: t.dummyMode ? "var(--brand)" : "var(--down)" }}>
                      {t.dummyMode ? "🧪" : "⚠️"}
                    </span>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
};

/* ---------------- MAX PROFIT LIVE DASHBOARD ---------------- */
const WORKER_BASE = "http://localhost:8080";

const MaxProfitLiveScreen = ({ onBack }) => {
  const algoId = "max-profit";
  const [configs, setConfigs] = React.useState([]);
  const [activeConfigId, setActiveConfigId] = React.useState(null);
  const [snap, setSnap]       = React.useState(null);
  const [connected, setConn]  = React.useState(false);
  const [err, setErr]         = React.useState(null);

  // Listen to configs of this algo to populate tabs
  React.useEffect(() => {
    const unsub = API.listenConfigs(algoId, list => {
      setConfigs(list);
      setActiveConfigId(prev => {
        if (prev && list.find(c => c.id === prev)) return prev;
        // Prefer a running config; else first config
        return list.find(c => c.running)?.id ?? list[0]?.id ?? null;
      });
    });
    return () => unsub();
  }, []);

  // Open SSE for the active config (changes when user clicks a tab)
  React.useEffect(() => {
    if (!activeConfigId) { setSnap(null); setConn(false); return; }
    const es = new EventSource(`${WORKER_BASE}/api/strategy/${algoId}/${activeConfigId}/stream`);
    es.onopen = () => { setConn(true); setErr(null); };
    es.onerror = () => { setConn(false); setErr("disconnected — is the worker running and the config started?"); };
    es.onmessage = (e) => {
      try { setSnap(JSON.parse(e.data)); } catch {}
    };
    return () => es.close();
  }, [activeConfigId]);

  const activeConfig = configs.find(c => c.id === activeConfigId);

  const t = snap?.trigger;
  const pos = snap?.position;
  const stocks = snap?.stocks ?? [];
  const options = snap?.options ?? [];

  const pillBg = (dir) => dir === "up" ? "var(--up)" : dir === "down" ? "var(--down)" : "var(--surface-3)";

  return (
    <div className="page">
      <div className="row-between" style={{ marginBottom: 16 }}>
        <div>
          <button className="btn btn-secondary btn-sm" onClick={onBack}>← Back to Algos</button>
          <h2 className="page-title" style={{ marginTop: 10, display: "inline-flex", alignItems: "center", gap: 10 }}>
            Max Profit · Live
            {snap?.dummyMode && (
              <span style={{ fontSize: 11, fontWeight: 700, padding: "3px 10px", borderRadius: 999, background: "var(--brand)", color: "white" }}>
                DUMMY
              </span>
            )}
            {snap && snap.dummyMode === false && (
              <span style={{ fontSize: 11, fontWeight: 700, padding: "3px 10px", borderRadius: 999, background: "var(--down)", color: "white" }}>
                LIVE
              </span>
            )}
          </h2>
          <div className="page-sub">
            <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
              <span style={{ width: 8, height: 8, borderRadius: "50%", background: connected ? "var(--up)" : "var(--down)" }}/>
              {connected ? "Streaming from worker" : (err ?? "connecting…")}
              {activeConfig && <span style={{ marginLeft: 8, color: "var(--text-3)" }}>· {activeConfig.name ?? "—"}</span>}
            </span>
          </div>
        </div>
      </div>

      {/* Config tabs — switch between configurations */}
      {configs.length > 1 && (
        <div className="row" style={{ gap: 6, flexWrap: "wrap", marginBottom: 12 }}>
          {configs.map(c => (
            <button key={c.id}
              className={"chip " + (c.id === activeConfigId ? "brand" : "")}
              onClick={() => setActiveConfigId(c.id)}
              style={{ display: "flex", alignItems: "center", gap: 6 }}>
              {c.running && <span className="pulse" style={{ width: 6, height: 6, background: "var(--up)", borderRadius: "50%" }}/>}
              {c.name ?? c.id.slice(0, 6)}
            </button>
          ))}
        </div>
      )}

      {configs.length === 0 && (
        <div className="card" style={{ padding: 24, textAlign: "center", color: "var(--text-3)" }}>
          No configurations yet. Configure Max Profit and save a config to see live data here.
        </div>
      )}

      {configs.length > 0 && !snap && (
        <div className="card" style={{ padding: 24, textAlign: "center", color: "var(--text-3)" }}>
          {configs.find(c => c.id === activeConfigId)?.running
            ? "Waiting for first snapshot… (the worker will emit when a tick arrives)"
            : "This config is not running — go to Algos and click Start to see live data."}
        </div>
      )}

      {snap && (
        <>
          {/* Trigger / cooldown card */}
          <div className="card" style={{ padding: 16, marginBottom: 16 }}>
            <div className="row-between" style={{ marginBottom: 10 }}>
              <div style={{ fontSize: 14, fontWeight: 700 }}>
                {pos ? (pos.awaitingFill ? "Awaiting fill" : "In Position") : (t?.cooldownMs > 0 ? "Cooldown" : "Watching")}
              </div>
              <div style={{ fontSize: 12, color: "var(--text-3)" }}>
                trigger: {t?.stockCount}+ stocks · ≥{t?.thresholdPct}% · window {t?.observationSec}s
              </div>
            </div>
            <div className="row" style={{ gap: 12, alignItems: "center" }}>
              <div className="chip" style={{ background: pillBg("up"), color: "white" }}>
                ↑ {t?.upCount ?? 0} up
              </div>
              <div className="chip" style={{ background: pillBg("down"), color: "white" }}>
                ↓ {t?.downCount ?? 0} down
              </div>
              <div className="chip">
                — {(stocks.length - (t?.upCount ?? 0) - (t?.downCount ?? 0))} neutral
              </div>
              {t?.cooldownMs > 0 && (
                <div className="chip" style={{ background: "var(--surface-3)" }}>
                  cooldown {Math.ceil(t.cooldownMs / 1000)}s
                </div>
              )}
            </div>
          </div>

          {/* Position panel */}
          {pos && (
            <div className="card" style={{ padding: 16, marginBottom: 16, background: pos.pnlPct >= 0 ? "color-mix(in srgb, var(--up) 6%, var(--surface))" : "color-mix(in srgb, var(--down) 6%, var(--surface))" }}>
              <div className="row-between" style={{ marginBottom: 10 }}>
                <div>
                  <div style={{ fontSize: 14, fontWeight: 700 }}>{pos.sym} · {pos.type}</div>
                  <div style={{ fontSize: 12, color: "var(--text-3)" }}>
                    entry ₹{pos.entry} · current ₹{pos.current} · qty {pos.lotQty} · held {pos.holdSec}s
                  </div>
                </div>
                <div style={{ fontSize: 22, fontWeight: 700, color: pos.pnlPct >= 0 ? "var(--up)" : "var(--down)" }}>
                  {pos.pnlPct >= 0 ? "+" : ""}{pos.pnlPct}%
                </div>
              </div>
              <div className="row" style={{ gap: 12, fontSize: 11, color: "var(--text-2)" }}>
                <span>TP @ +{pos.tpAt}%</span>
                <span>SL @ −{pos.slAt}%</span>
                <span>entry momentum {pos.entryMomentum}%</span>
                <span>current {pos.currentMomentum}%</span>
                <span>limit @ ₹{pos.limitPrice ?? "?"}</span>
                <span>time stop in {Math.ceil((pos.timeStopInMs ?? 0) / 1000)}s</span>
              </div>
            </div>
          )}

          {/* Stocks grid */}
          <div style={{ fontSize: 13, fontWeight: 700, marginBottom: 8 }}>Watchlist stocks ({stocks.length})</div>
          <div className="grid" style={{ gridTemplateColumns: "repeat(auto-fill, minmax(200px, 1fr))", gap: 10, marginBottom: 18 }}>
            {stocks.map(s => (
              <div key={s.token} className="card" style={{
                padding: 12, borderLeft: `3px solid ${pillBg(s.direction)}`,
              }}>
                <div className="row-between">
                  <div style={{ fontSize: 13, fontWeight: 700 }}>{s.sym}</div>
                  <div style={{ fontSize: 11, color: "var(--text-3)" }}>{s.ticks} ticks</div>
                </div>
                <div className="row-between" style={{ marginTop: 6 }}>
                  <div className="mono" style={{ fontSize: 14 }}>{s.ltp?.toFixed(2) ?? "—"}</div>
                  <div className="mono" style={{ fontSize: 13, color: (s.trendReturnPct ?? 0) >= 0 ? "var(--up)" : "var(--down)", fontWeight: 600 }}>
                    {(s.trendReturnPct ?? 0) >= 0 ? "+" : ""}{s.trendReturnPct ?? 0}%
                  </div>
                </div>
                <div className="row-between" style={{ fontSize: 10, color: "var(--text-3)", marginTop: 4 }}>
                  <span>endpoint {(s.windowReturnPct ?? 0) >= 0 ? "+" : ""}{s.windowReturnPct ?? 0}%</span>
                  {s.lastTickAge != null && <span>tick {s.lastTickAge}s ago</span>}
                </div>
              </div>
            ))}
            {stocks.length === 0 && <div style={{ fontSize: 12, color: "var(--text-3)" }}>No stocks configured</div>}
          </div>

          {/* Options grid */}
          <div style={{ fontSize: 13, fontWeight: 700, marginBottom: 8 }}>Option pool ({options.length})</div>
          <div className="grid" style={{ gridTemplateColumns: "repeat(auto-fill, minmax(220px, 1fr))", gap: 10 }}>
            {options.map(o => (
              <div key={o.token} className="card" style={{
                padding: 12,
                opacity: o.ltp == null ? 0.6 : 1,
                borderLeft: `3px solid ${o.withinBudget ? "var(--up)" : "var(--down)"}`,
              }}>
                <div className="row-between">
                  <div style={{ fontSize: 12, fontWeight: 700 }}>{o.sym}</div>
                  <div className="chip" style={{ fontSize: 10 }}>{o.type}</div>
                </div>
                <div className="row-between" style={{ marginTop: 6 }}>
                  <div className="mono" style={{ fontSize: 13 }}>₹{o.ltp?.toFixed(2) ?? "—"}</div>
                  <div style={{ fontSize: 11, color: "var(--text-3)" }}>×{o.lotSize}</div>
                </div>
                <div className="row-between" style={{ marginTop: 4 }}>
                  <div style={{ fontSize: 11, color: "var(--text-2)" }}>
                    cost {o.cost != null ? `₹${o.cost.toLocaleString()}` : "—"}
                  </div>
                  <div style={{ fontSize: 10, color: o.withinBudget ? "var(--up)" : "var(--down)" }}>
                    {o.withinBudget == null ? "" : (o.withinBudget ? "in budget" : "over budget")}
                  </div>
                </div>
              </div>
            ))}
            {options.length === 0 && <div style={{ fontSize: 12, color: "var(--text-3)" }}>No options configured</div>}
          </div>
        </>
      )}
    </div>
  );
};

/* ---------------- SHARED LIVE-DASHBOARD HELPERS ---------------- */
// Hook: subscribes to configs of an algo and an EventSource for the active config.
// Returns { configs, activeConfigId, setActiveConfigId, snap, connected, err }.
const useLiveStrategy = (algoId) => {
  const [configs, setConfigs] = React.useState([]);
  const [activeConfigId, setActiveConfigId] = React.useState(null);
  const [snap, setSnap] = React.useState(null);
  const [connected, setConn] = React.useState(false);
  const [err, setErr] = React.useState(null);

  React.useEffect(() => {
    const unsub = API.listenConfigs(algoId, list => {
      setConfigs(list);
      setActiveConfigId(prev => {
        if (prev && list.find(c => c.id === prev)) return prev;
        return list.find(c => c.running)?.id ?? list[0]?.id ?? null;
      });
    });
    return () => unsub();
  }, [algoId]);

  React.useEffect(() => {
    if (!activeConfigId) { setSnap(null); setConn(false); return; }
    const es = new EventSource(`${WORKER_BASE}/api/strategy/${algoId}/${activeConfigId}/stream`);
    es.onopen    = () => { setConn(true);  setErr(null); };
    es.onerror   = () => { setConn(false); setErr("disconnected — is the worker running and config started?"); };
    es.onmessage = (e) => { try { setSnap(JSON.parse(e.data)); } catch {} };
    return () => es.close();
  }, [algoId, activeConfigId]);

  return { configs, activeConfigId, setActiveConfigId, snap, connected, err };
};

const LiveHeader = ({ title, configs, activeConfigId, setActiveConfigId, connected, err, onBack, dummyMode }) => {
  const activeConfig = configs.find(c => c.id === activeConfigId);
  return (
    <>
      <div className="row-between" style={{ marginBottom: 12 }}>
        <div>
          <button className="btn btn-secondary btn-sm" onClick={onBack}>← Back to Algos</button>
          <h2 className="page-title" style={{ marginTop: 10, display: "inline-flex", alignItems: "center", gap: 10 }}>
            {title}
            {dummyMode === true && <span style={{ fontSize: 11, fontWeight: 700, padding: "3px 10px", borderRadius: 999, background: "var(--brand)", color: "white" }}>DUMMY</span>}
            {dummyMode === false && <span style={{ fontSize: 11, fontWeight: 700, padding: "3px 10px", borderRadius: 999, background: "var(--down)", color: "white" }}>LIVE</span>}
          </h2>
          <div className="page-sub">
            <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
              <span style={{ width: 8, height: 8, borderRadius: "50%", background: connected ? "var(--up)" : "var(--down)" }}/>
              {connected ? "Streaming from worker" : (err ?? "connecting…")}
              {activeConfig && <span style={{ marginLeft: 8, color: "var(--text-3)" }}>· {activeConfig.name ?? "—"}</span>}
            </span>
          </div>
        </div>
      </div>
      {configs.length > 1 && (
        <div className="row" style={{ gap: 6, flexWrap: "wrap", marginBottom: 12 }}>
          {configs.map(c => (
            <button key={c.id}
              className={"chip " + (c.id === activeConfigId ? "brand" : "")}
              onClick={() => setActiveConfigId(c.id)}
              style={{ display: "flex", alignItems: "center", gap: 6 }}>
              {c.running && <span className="pulse" style={{ width: 6, height: 6, background: "var(--up)", borderRadius: "50%" }}/>}
              {c.name ?? c.id.slice(0, 6)}
            </button>
          ))}
        </div>
      )}
    </>
  );
};

const LivePositionPanel = ({ pos, extra }) => {
  if (!pos) return null;
  return (
    <div className="card" style={{ padding: 16, marginBottom: 16, background: (pos.pnlPct ?? 0) >= 0 ? "color-mix(in srgb, var(--up) 6%, var(--surface))" : "color-mix(in srgb, var(--down) 6%, var(--surface))" }}>
      <div className="row-between" style={{ marginBottom: 10 }}>
        <div>
          <div style={{ fontSize: 14, fontWeight: 700 }}>{pos.sym ?? pos.label} {pos.type ? `· ${pos.type}` : ""}</div>
          <div style={{ fontSize: 12, color: "var(--text-3)" }}>
            entry ₹{pos.entry} · current ₹{pos.current} · qty {pos.lotQty} · held {pos.holdSec}s
          </div>
        </div>
        <div style={{ fontSize: 22, fontWeight: 700, color: (pos.pnlPct ?? 0) >= 0 ? "var(--up)" : "var(--down)" }}>
          {(pos.pnlPct ?? 0) >= 0 ? "+" : ""}{pos.pnlPct}%
        </div>
      </div>
      <div className="row" style={{ gap: 12, fontSize: 11, color: "var(--text-2)", flexWrap: "wrap" }}>
        {/* TP shown only when there's a fixed-profit exit (e.g. timeout mode) — pattern-trail uses trailing stop instead */}
        {pos.exitMode !== "pattern-trail" && pos.tpAt != null && <span>TP @ +{pos.tpAt}%</span>}
        {pos.slAt != null && <span>SL @ −{pos.slAt}%</span>}
        {extra}
      </div>
    </div>
  );
};

/* ---------------- MOMENTUM BURST LIVE DASHBOARD ---------------- */
const MomentumBurstLiveScreen = ({ onBack }) => {
  const { configs, activeConfigId, setActiveConfigId, snap, connected, err } = useLiveStrategy("momentum-burst");
  const pos = snap?.position;
  const t = snap?.trigger ?? {};
  const options = snap?.options ?? [];

  // Visual fill of the threshold bar — how close current window return is to spike threshold
  const ratio = t.spikeThreshold > 0 ? Math.min(1, (t.absReturnPct ?? 0) / t.spikeThreshold) : 0;
  const dir = (t.windowReturnPct ?? 0) >= 0 ? "up" : "down";
  const barColor = dir === "up" ? "var(--up)" : "var(--down)";

  return (
    <div className="page">
      <LiveHeader title="Momentum Burst · Live" {...{ configs, activeConfigId, setActiveConfigId, connected, err, onBack, dummyMode: snap?.dummyMode }}/>
      {configs.length === 0 && (
        <div className="card" style={{ padding: 24, textAlign: "center", color: "var(--text-3)" }}>
          No configurations yet. Configure Momentum Burst and save a config to see live data here.
        </div>
      )}
      {configs.length > 0 && !snap && (
        <div className="card" style={{ padding: 24, textAlign: "center", color: "var(--text-3)" }}>
          {configs.find(c => c.id === activeConfigId)?.running
            ? "Waiting for first snapshot… (the worker will emit when a tick arrives)"
            : "This config is not running — go to Algos and click Start to see live data."}
        </div>
      )}
      {snap && (
        <>
          {/* Spike meter */}
          <div className="card" style={{ padding: 16, marginBottom: 16 }}>
            <div className="row-between" style={{ marginBottom: 8 }}>
              <div style={{ fontSize: 14, fontWeight: 700 }}>
                {pos ? (pos.awaitingFill ? "Awaiting fill" : "In Position") : (t.cooldownMs > 0 ? "Cooldown" : "Watching for spike")}
              </div>
              <div style={{ fontSize: 12, color: "var(--text-3)" }}>
                {snap.instrument} spot ₹{snap.spot?.toFixed(2) ?? "—"} · {t.windowTicks} ticks in {t.windowSec}s
              </div>
            </div>
            <div style={{ fontSize: 11, color: "var(--text-2)", marginBottom: 4 }}>
              Spike threshold: <b>±{t.spikeThreshold}%</b> in 5s · current 5s return: <b style={{ color: barColor }}>{(t.windowReturnPct ?? 0) >= 0 ? "+" : ""}{t.windowReturnPct}%</b>
            </div>
            <div style={{ height: 12, background: "var(--surface-2)", borderRadius: 6, position: "relative", overflow: "hidden" }}>
              <div style={{
                position: "absolute", left: 0, top: 0, bottom: 0,
                width: `${ratio * 100}%`,
                background: barColor,
                transition: "width 0.2s",
              }}/>
              <div style={{ position: "absolute", right: 4, top: -1, fontSize: 9, color: "var(--text-3)", lineHeight: "14px" }}>
                {(ratio * 100).toFixed(0)}% of threshold
              </div>
            </div>
            {t.cooldownMs > 0 && (
              <div style={{ fontSize: 11, color: "var(--text-3)", marginTop: 6 }}>
                cooldown {Math.ceil(t.cooldownMs / 1000)}s remaining
              </div>
            )}
          </div>

          {/* Position */}
          {pos && (
            <LivePositionPanel pos={pos} extra={<>
              <span>decay in {pos.decayInSec}s</span>
            </>}/>
          )}

          {/* Options pool */}
          <div style={{ fontSize: 13, fontWeight: 700, marginBottom: 8 }}>Option pool ({options.length})</div>
          <div className="grid" style={{ gridTemplateColumns: "repeat(auto-fill, minmax(200px, 1fr))", gap: 10 }}>
            {options.map(o => (
              <div key={o.token} className="card" style={{ padding: 12, opacity: o.ltp == null ? 0.5 : 1 }}>
                <div className="row-between">
                  <div style={{ fontSize: 12, fontWeight: 700 }}>{o.sym}</div>
                  <div className="chip" style={{ fontSize: 10 }}>{o.type}</div>
                </div>
                <div className="row-between" style={{ marginTop: 6 }}>
                  <div className="mono" style={{ fontSize: 14 }}>₹{o.ltp?.toFixed(2) ?? "—"}</div>
                  <div style={{ fontSize: 11, color: "var(--text-3)" }}>×{o.lotSize}</div>
                </div>
                {o.lastTickAge != null && (
                  <div style={{ fontSize: 10, color: "var(--text-3)", marginTop: 4 }}>tick {o.lastTickAge}s ago</div>
                )}
              </div>
            ))}
            {options.length === 0 && <div style={{ fontSize: 12, color: "var(--text-3)" }}>No options configured — strategy will auto-pick from spot.</div>}
          </div>
        </>
      )}
    </div>
  );
};

/* ---------------- OPTION DIP BUYER LIVE DASHBOARD ---------------- */
const OptionDipBuyerLiveScreen = ({ onBack }) => {
  const { configs, activeConfigId, setActiveConfigId, snap, connected, err } = useLiveStrategy("option-dip-buyer");
  const pos = snap?.position;
  const t   = snap?.trigger ?? {};
  const legs = snap?.legs ?? [];

  const stateColor = (s) => s === "dipping" ? "var(--up)" : s === "peer-violation" ? "var(--down)" : s === "warming" ? "var(--text-3)" : "var(--text-3)";
  const stateLabel = (s) => s === "dipping" ? "🟢 DIP" : s === "peer-violation" ? "⛔ peer dipping" : s === "warming" ? "warming up" : "calm";

  return (
    <div className="page">
      <LiveHeader title="Option Dip Buyer · Live" {...{ configs, activeConfigId, setActiveConfigId, connected, err, onBack, dummyMode: snap?.dummyMode }}/>
      {configs.length === 0 && (
        <div className="card" style={{ padding: 24, textAlign: "center", color: "var(--text-3)" }}>
          No configurations yet. Configure Option Dip Buyer and save a config to see live data here.
        </div>
      )}
      {configs.length > 0 && !snap && (
        <div className="card" style={{ padding: 24, textAlign: "center", color: "var(--text-3)" }}>
          {configs.find(c => c.id === activeConfigId)?.running
            ? "Waiting for first snapshot… (the worker will emit when a tick arrives)"
            : "This config is not running — go to Algos and click Start to see live data."}
        </div>
      )}
      {snap && (
        <>
          {/* Trigger summary */}
          <div className="card" style={{ padding: 16, marginBottom: 16 }}>
            <div className="row-between">
              <div>
                <div style={{ fontSize: 14, fontWeight: 700 }}>
                  {pos ? "In Position" : (legs.some(l => l.state === "peer-violation") ? "Peer dipping — blocked" : "Watching for single-leg dip")}
                </div>
                <div style={{ fontSize: 12, color: "var(--text-3)", marginTop: 4 }}>
                  Trigger when exactly <b>one</b> leg drops ≥ <b>{t.dipThresholdPct}%</b> from its {t.windowTicks}-tick avg AND peers stay below <b>{t.peerMaxPct}%</b>
                </div>
              </div>
            </div>
          </div>

          {pos && (
            <LivePositionPanel pos={pos} extra={<>
              <span>time stop in {pos.timeStopInSec}s</span>
            </>}/>
          )}

          {/* Legs grid */}
          <div style={{ fontSize: 13, fontWeight: 700, marginBottom: 8 }}>Legs ({legs.length})</div>
          <div className="grid" style={{ gridTemplateColumns: "repeat(auto-fill, minmax(220px, 1fr))", gap: 10 }}>
            {legs.map(l => {
              const dipColor = l.dipPct >= t.dipThresholdPct ? "var(--up)" : l.dipPct >= t.peerMaxPct ? "var(--down)" : "var(--text-2)";
              return (
                <div key={l.idx} className="card" style={{
                  padding: 12,
                  borderLeft: `3px solid ${stateColor(l.state)}`,
                  opacity: l.state === "warming" ? 0.6 : 1,
                  boxShadow: l.isHeld ? "0 0 0 2px var(--brand) inset" : "none",
                }}>
                  <div className="row-between">
                    <div style={{ fontSize: 12, fontWeight: 700 }}>{l.label}</div>
                    {l.isHeld ? (
                      <span className="chip brand" style={{ fontSize: 10 }}>HELD</span>
                    ) : (
                      <span className="chip" style={{ fontSize: 10, color: stateColor(l.state) }}>{stateLabel(l.state)}</span>
                    )}
                  </div>
                  <div className="row-between" style={{ marginTop: 6 }}>
                    <div className="mono" style={{ fontSize: 14 }}>₹{l.last.toFixed(2)}</div>
                    <div className="mono" style={{ fontSize: 13, fontWeight: 600, color: dipColor }}>
                      {l.dipPct >= 0 ? "↓ " : "↑ "}{Math.abs(l.dipPct)}%
                    </div>
                  </div>
                  <div style={{ fontSize: 11, color: "var(--text-3)", marginTop: 4 }}>
                    avg ₹{l.avg.toFixed(2)} · {l.ticks} ticks{l.lastTickAge != null ? ` · tick ${l.lastTickAge}s ago` : ""}
                  </div>
                </div>
              );
            })}
            {legs.length === 0 && <div style={{ fontSize: 12, color: "var(--text-3)" }}>No legs configured.</div>}
          </div>
        </>
      )}
    </div>
  );
};

/* ---------------- CANDLE BURST LIVE DASHBOARD ---------------- */
const CandleBurstLiveScreen = ({ onBack }) => {
  const { configs, activeConfigId, setActiveConfigId, snap, connected, err } = useLiveStrategy("candle-burst");
  const pos = snap?.position;
  const cur = snap?.currentCandle;
  const prev = snap?.prevCandle;
  const lastPattern = snap?.lastPattern;
  const options = snap?.options ?? [];

  // Render a candle as O/H/L/C with mini wick visual
  const Candle = ({ candle, label, highlight }) => {
    if (!candle) return <div className="card" style={{ padding: 12 }}><div style={{ fontSize: 11, color: "var(--text-3)" }}>{label}</div><div style={{ fontSize: 12, color: "var(--text-3)", marginTop: 6 }}>—</div></div>;
    const bullish = candle.c > candle.o;
    const color   = bullish ? "var(--up)" : "var(--down)";
    const range   = Math.max(1e-9, candle.h - candle.l);
    const bodyTop = Math.max(candle.o, candle.c);
    const bodyBot = Math.min(candle.o, candle.c);
    const upperPct = (candle.h - bodyTop) / range * 100;
    const bodyPct  = (bodyTop - bodyBot) / range * 100;
    const lowerPct = (bodyBot - candle.l) / range * 100;
    return (
      <div className="card" style={{ padding: 12, borderLeft: highlight ? `3px solid ${color}` : "" }}>
        <div className="row-between"><div style={{ fontSize: 11, color: "var(--text-3)" }}>{label}</div><div className="chip" style={{ fontSize: 10, color }}>{bullish ? "BULL" : "BEAR"}</div></div>
        <div className="row" style={{ marginTop: 8, gap: 10, alignItems: "stretch" }}>
          <div style={{ width: 22, height: 90, position: "relative" }}>
            <div style={{ position: "absolute", left: "50%", top: 0, width: 2, height: `${upperPct}%`, background: "var(--text-3)", transform: "translateX(-50%)" }}/>
            <div style={{ position: "absolute", left: 0, right: 0, top: `${upperPct}%`, height: `${bodyPct}%`, background: color, borderRadius: 2 }}/>
            <div style={{ position: "absolute", left: "50%", top: `${upperPct + bodyPct}%`, width: 2, height: `${lowerPct}%`, background: "var(--text-3)", transform: "translateX(-50%)" }}/>
          </div>
          <div style={{ fontSize: 11, color: "var(--text-2)", lineHeight: 1.5 }}>
            <div>O ₹{candle.o.toFixed(2)}</div>
            <div>H ₹{candle.h.toFixed(2)}</div>
            <div>L ₹{candle.l.toFixed(2)}</div>
            <div>C ₹{candle.c.toFixed(2)}</div>
          </div>
        </div>
      </div>
    );
  };

  return (
    <div className="page">
      <LiveHeader title="Candle Burst · Live" {...{ configs, activeConfigId, setActiveConfigId, connected, err, onBack, dummyMode: snap?.dummyMode }}/>
      {configs.length === 0 && (
        <div className="card" style={{ padding: 24, textAlign: "center", color: "var(--text-3)" }}>
          No configurations yet. Configure Candle Burst and save a config to see live data here.
        </div>
      )}
      {configs.length > 0 && !snap && (
        <div className="card" style={{ padding: 24, textAlign: "center", color: "var(--text-3)" }}>
          {configs.find(c => c.id === activeConfigId)?.running
            ? "Waiting for first snapshot… (the worker will emit when a tick arrives)"
            : "This config is not running — go to Algos and click Start to see live data."}
        </div>
      )}
      {snap && (
        <>
          {/* Strategy summary */}
          <div className="card" style={{ padding: 16, marginBottom: 16 }}>
            <div className="row-between">
              <div>
                <div style={{ fontSize: 14, fontWeight: 700 }}>
                  {pos ? (pos.awaitingFill ? "Awaiting fill" : "In Position") : "Watching candles"}
                </div>
                <div style={{ fontSize: 12, color: "var(--text-3)", marginTop: 4 }}>
                  Building {snap.candleSec}s candles · detecting engulfing / hammer / shooting star / marubozu
                </div>
              </div>
              {lastPattern && (
                <div style={{ textAlign: "right", fontSize: 12 }}>
                  <div style={{ color: "var(--text-3)" }}>Last pattern</div>
                  <div style={{ fontWeight: 700 }}>{lastPattern.name}</div>
                  <div style={{ fontSize: 11, color: "var(--text-3)" }}>{new Date(lastPattern.ts).toLocaleTimeString("en-IN")}</div>
                </div>
              )}
            </div>
          </div>

          {/* Candles side by side */}
          <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 10, marginBottom: 16 }}>
            <Candle candle={prev} label="Previous candle"/>
            <Candle candle={cur} label="Current candle (live)" highlight/>
          </div>

          {pos && (
            <LivePositionPanel pos={pos} extra={<>
              {pos.pattern && <span>pattern: {pos.pattern}</span>}
              {pos.exitMode === "pattern-trail" ? (
                <>
                  {pos.peakPnlPct > 0
                    ? <span>peak +{pos.peakPnlPct}% · trail fires below +{pos.trailFiresAtPnlPct}%</span>
                    : <span>trail arms after +{pos.tpAt}% (not yet reached)</span>}
                  <span>exits on opposite-pattern reversal</span>
                </>
              ) : (
                <>
                  <span>limit @ ₹{pos.limitPrice ?? "?"}</span>
                  <span>time stop in {Math.ceil((pos.timeStopInMs ?? 0) / 1000)}s</span>
                </>
              )}
            </>}/>
          )}

          {/* Options pool */}
          <div style={{ fontSize: 13, fontWeight: 700, marginBottom: 8 }}>Option pool ({options.length})</div>
          <div className="grid" style={{ gridTemplateColumns: "repeat(auto-fill, minmax(220px, 1fr))", gap: 10 }}>
            {options.map(o => (
              <div key={o.token} className="card" style={{
                padding: 12,
                opacity: o.ltp == null ? 0.5 : 1,
                borderLeft: `3px solid ${o.withinBudget ? "var(--up)" : "var(--down)"}`,
              }}>
                <div className="row-between">
                  <div style={{ fontSize: 12, fontWeight: 700 }}>{o.sym}</div>
                  <div className="chip" style={{ fontSize: 10 }}>{o.type}</div>
                </div>
                <div className="row-between" style={{ marginTop: 6 }}>
                  <div className="mono" style={{ fontSize: 14 }}>₹{o.ltp?.toFixed(2) ?? "—"}</div>
                  <div style={{ fontSize: 11, color: "var(--text-3)" }}>×{o.lotSize}</div>
                </div>
                <div className="row-between" style={{ marginTop: 4 }}>
                  <div style={{ fontSize: 11, color: "var(--text-2)" }}>cost {o.cost != null ? `₹${o.cost.toLocaleString()}` : "—"}</div>
                  <div style={{ fontSize: 10, color: o.withinBudget ? "var(--up)" : "var(--down)" }}>
                    {o.withinBudget == null ? "" : (o.withinBudget ? "in budget" : "over budget")}
                  </div>
                </div>
              </div>
            ))}
          </div>
        </>
      )}
    </div>
  );
};

Object.assign(window, {
  PositionsScreen, PartialExitModal, AddMoreModal, EquityTable, OptionsTable,
  AlgosScreen, AlgoConfigModal,
  AlgoMonitorScreen, ReportsScreen, OrdersScreen, JournalScreen,
  BacktestScreen, SettingsScreen, StrategyGuideScreen,
  MomentumBurstLiveScreen, OptionDipBuyerLiveScreen, CandleBurstLiveScreen,
  MaxProfitLiveScreen, TradesScreen,
});
