// Settings page — API keys, exchange config, risk params, security, env vars.
const { useState: usSet, useMemo: umSet } = React;

function SettingsPage({ accent, activeExchange = "binance", setActiveExchange }) {
  const [tab, setTab] = usSet("exchange");
  const tabs = [
    { id: "exchange",  label: "Exchange",       icon: <IconLayers size={14} /> },
    { id: "strategy",  label: "Strategy",       icon: <IconChart size={14} /> },
    { id: "risk",      label: "Risk",           icon: <IconShield size={14} /> },
    { id: "webhook",   label: "Webhook",        icon: <IconSignal size={14} /> },
    { id: "telegram",  label: "Telegram",       icon: <IconTelegram size={14} /> },
    { id: "security",  label: "Security",       icon: <IconKey size={14} /> },
    { id: "env",       label: "Environment",    icon: <IconTerm size={14} /> },
    { id: "danger",    label: "Danger zone",    icon: <IconAlert size={14} /> },
  ];
  return (
    <div style={{ display: "grid", gridTemplateColumns: "220px 1fr", gap: "var(--row-gap)", alignItems: "flex-start" }}>
      {/* Tabs sidebar */}
      <aside style={{
        position: "sticky", top: 88,
        background: "linear-gradient(180deg, rgba(20,26,42,0.6), rgba(15,19,32,0.6))",
        border: "1px solid var(--line)", borderRadius: 14, padding: 8,
        display: "flex", flexDirection: "column", gap: 2,
      }}>
        {tabs.map((t) => {
          const active = t.id === tab;
          return (
            <button key={t.id} onClick={() => setTab(t.id)} className="focus-ring" style={{
              display: "flex", alignItems: "center", gap: 10, padding: "10px 12px", borderRadius: 8, border: 0,
              background: active ? "var(--accent-soft)" : "transparent",
              color: active ? "var(--text)" : "var(--text-2)",
              fontSize: 13, fontWeight: active ? 500 : 400, textAlign: "left",
              transition: "background .15s",
            }}
            onMouseEnter={(e) => { if (!active) e.currentTarget.style.background = "rgba(255,255,255,0.04)"; }}
            onMouseLeave={(e) => { if (!active) e.currentTarget.style.background = "transparent"; }}>
              <span style={{ color: active ? "var(--accent)" : "var(--text-3)" }}>{t.icon}</span>
              <span style={{ flex: 1 }}>{t.label}</span>
              {t.id === "danger" && <span style={{ width: 6, height: 6, borderRadius: 999, background: "var(--loss)" }} />}
            </button>
          );
        })}
      </aside>

      <div style={{ minWidth: 0 }}>
        {tab === "exchange" && <ExchangeSettings activeExchange={activeExchange} setActiveExchange={setActiveExchange} />}
        {tab === "strategy" && <StrategySettings activeExchange={activeExchange} />}
        {tab === "risk"     && <RiskSettings activeExchange={activeExchange} />}
        {tab === "webhook"  && <WebhookSettings />}
        {tab === "telegram" && <TelegramSettings />}
        {tab === "security" && <SecuritySettings activeExchange={activeExchange} />}
        {tab === "env"      && <EnvSettings activeExchange={activeExchange} />}
        {tab === "danger"   && <DangerZone />}
      </div>
    </div>
  );
}

// =====================================================================
function SettingsCard({ title, subtitle, children, footer }) {
  return (
    <Card title={title} subtitle={subtitle}>
      <div>{children}</div>
      {footer && (
        <div style={{ marginTop: 16, paddingTop: 16, borderTop: "1px solid var(--line)", display: "flex", justifyContent: "flex-end", gap: 8 }}>
          {footer}
        </div>
      )}
    </Card>
  );
}

// =====================================================================
function ExchangeSettings({ activeExchange = "binance", setActiveExchange }) {
  const [mode, setMode] = usSet(activeExchange === "kraken" ? "paper" : "testnet");
  const [showKey, setShow1] = usSet(false);
  const [showSec, setShow2] = usSet(false);
  const ex = EXCHANGES[activeExchange] || EXCHANGES.binance;
  const select = (id) => {
    setActiveExchange && setActiveExchange(id);
    // Auto-select paper when switching to Kraken (no public testnet)
    if (id === "kraken" && mode === "testnet") setMode("paper");
    if (id === "binance" && mode === "paper") setMode("testnet");
  };
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--row-gap)" }}>
      {/* Active exchange picker — new in v3 */}
      <SettingsCard title="Active exchange" subtitle="Single-active per deploy · sets ACTIVE_EXCHANGE in .env">
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
          {["binance", "kraken"].map((id) => {
            const e = EXCHANGES[id];
            const active = id === activeExchange;
            return (
              <button key={id} onClick={() => select(id)} className="focus-ring" style={{
                padding: 16, borderRadius: 12, textAlign: "left",
                background: active ? "var(--accent-soft)" : "rgba(255,255,255,0.02)",
                border: "1px solid " + (active ? "rgba(0,212,170,0.4)" : "var(--line)"),
                color: "var(--text)", cursor: "pointer",
                display: "flex", flexDirection: "column", gap: 12,
                transition: "all .15s",
              }}>
                <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
                  <span style={{
                    width: 18, height: 18, borderRadius: 999,
                    border: "2px solid " + (active ? "var(--accent)" : "var(--text-3)"),
                    background: active ? "var(--accent)" : "transparent",
                    display: "flex", alignItems: "center", justifyContent: "center",
                  }}>{active && <span style={{ width: 6, height: 6, borderRadius: 999, background: "#06150F" }} />}</span>
                  <e.Icon size={22} />
                  <span style={{ fontSize: 14, fontWeight: 600, flex: 1 }}>{e.name}</span>
                  <code className="mono" style={{ fontSize: 10, color: "var(--text-3)" }}>ACTIVE_EXCHANGE={e.id}</code>
                </div>
                <div style={{ fontSize: 11.5, color: "var(--text-2)", lineHeight: 1.5 }}>{e.full} · {e.quirks}</div>
                <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8, fontSize: 10.5 }}>
                  <span style={{ color: "var(--text-3)" }}>Fees <span className="mono" style={{ color: "var(--text)" }}>{e.fees.maker.toFixed(2)}/{e.fees.taker.toFixed(2)}%</span></span>
                  <span style={{ color: "var(--text-3)" }}>SL <span className="mono" style={{ color: "var(--text)" }}>{e.stopLoss}</span></span>
                  <span style={{ color: "var(--text-3)" }}>Testnet <span className="mono" style={{ color: e.testnet ? "var(--profit)" : "var(--warn)" }}>{e.testnet ? "yes" : "paper-only"}</span></span>
                  <span style={{ color: "var(--text-3)" }}>RTT <span className="mono" style={{ color: "var(--text)" }}>{e.rttMs}ms</span></span>
                </div>
              </button>
            );
          })}
        </div>
      </SettingsCard>

      <SettingsCard title="Trading mode" subtitle="MUST default to testnet · Kraken uses paper-trade (no public testnet)">
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 12 }}>
          <ModeCard
            active={mode === "testnet"}
            onClick={() => setMode("testnet")}
            label="Testnet"
            sub={ex.testnet ? "Paper trade with simulated funds · " + ex.name + " spot testnet" : "Not available on Kraken — use Paper instead"}
            tag={ex.testnet ? "Safe · default" : "Unavailable"}
            tagColor={ex.testnet ? "var(--profit)" : "var(--text-3)"}
            disabled={!ex.testnet}
          />
          <ModeCard
            active={mode === "paper"}
            onClick={() => setMode("paper")}
            label="Paper"
            sub="Simulated balance + live market data. Required for Kraken; useful as a dry-run on Binance."
            tag="Safe · simulated"
            tagColor="var(--info)"
          />
          <ModeCard
            active={mode === "live"}
            onClick={() => setMode("live")}
            label="Live trading"
            sub={"Real funds on " + ex.name + " · trades execute on the production API"}
            tag="Risk of capital loss"
            tagColor="var(--loss)"
          />
        </div>
        {mode === "live" && (
          <div style={{ marginTop: 14, padding: 14, borderRadius: 10, background: "rgba(242,63,92,0.08)", border: "1px solid rgba(242,63,92,0.25)", display: "flex", gap: 12, alignItems: "flex-start" }}>
            <IconAlert size={18} style={{ color: "var(--loss)", flex: "0 0 18px", marginTop: 1 }} />
            <div style={{ fontSize: 12.5, color: "var(--text)", lineHeight: 1.55 }}>
              <strong style={{ color: "var(--loss)" }}>Live mode is destructive.</strong> Confirm the bot has run 7+ days in {ex.testnet ? "testnet" : "paper"},
              circuit breakers are armed, and Telegram alerts are working before flipping this switch.
              You will be prompted to type <code className="mono" style={{ color: "var(--warn)" }}>I-UNDERSTAND-THE-RISK</code> to confirm.
            </div>
          </div>
        )}
        {mode === "paper" && (
          <div style={{ marginTop: 14, padding: 14, borderRadius: 10, background: "rgba(96,165,250,0.06)", border: "1px solid rgba(96,165,250,0.2)", display: "flex", gap: 12, alignItems: "flex-start" }}>
            <IconAlert size={18} style={{ color: "var(--info)", flex: "0 0 18px", marginTop: 1 }} />
            <div style={{ fontSize: 12.5, color: "var(--text)", lineHeight: 1.55 }}>
              Paper-trade mode simulates fills against live order-book prices. Used as the default for Kraken because <strong>Kraken has no public testnet API</strong>.
              P&L, drawdown, and circuit breakers all behave identically to live — only the orders are never sent.
            </div>
          </div>
        )}
      </SettingsCard>

      {/* Credentials — keyed by active exchange */}
      <SettingsCard title={ex.name + " API credentials"} subtitle={"Stored encrypted at rest · loaded from .env · only " + ex.id.toUpperCase() + "_API_* keys are read"}>
        <FieldRow label="Exchange" hint={"v1.1 supports Binance + Kraken. Switch above to flip ACTIVE_EXCHANGE."}>
          <div style={{ display: "flex", alignItems: "center", gap: 10, padding: "10px 14px", borderRadius: 8, border: "1px solid var(--line-strong)", background: "rgba(255,255,255,0.02)" }}>
            <ex.Icon size={20} />
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 13, fontWeight: 500 }}>{ex.full}</div>
              <div style={{ fontSize: 11, color: "var(--text-3)" }} className="mono">CCXT id · {ex.ccxtId} · spot · native {ex.nativeSymbol}</div>
            </div>
            <Badge variant="accent">● active</Badge>
          </div>
        </FieldRow>

        <FieldRow label="API Key" hint={"From " + ex.name + " → API Management. Bot needs Read + Spot trade. Never enable Withdraw."}>
          <div style={{ display: "flex", gap: 8 }}>
            <TextInput value={showKey ? (activeExchange === "binance" ? "k4Hg2QnR9mTpZ7LkV8sBjW1NfYeXuApCx" : "KRKN-7s4dPx9LqMzVtR8nKpJ1") : "k4Hg2QnR9mTpZ7L•••••••••••••••••"} mono />
            <IconBtn title={showKey ? "Hide" : "Show"} onClick={() => setShow1(!showKey)}>{showKey ? <IconEyeOff size={14} /> : <IconEye size={14} />}</IconBtn>
            <IconBtn title="Copy"><IconCopy size={14} /></IconBtn>
          </div>
        </FieldRow>

        <FieldRow label="API Secret" hint={activeExchange === "kraken" ? "Kraken secret is base64-encoded. CCXT handles nonce-based auth automatically." : "Treat as a password. Anyone with this key can trade on your account."}>
          <div style={{ display: "flex", gap: 8 }}>
            <TextInput value={showSec ? (activeExchange === "binance" ? "X9pQ7vM4nK2Lj1WtR8sZyB6dF3cVuG5h" : "base64:K8Pq...==") : "••••••••••••••••••••••••••••••••"} mono type={showSec ? "text" : "password"} />
            <IconBtn title={showSec ? "Hide" : "Show"} onClick={() => setShow2(!showSec)}>{showSec ? <IconEyeOff size={14} /> : <IconEye size={14} />}</IconBtn>
          </div>
        </FieldRow>

        <FieldRow label="Permissions verified" hint="The bot probes your key on save to confirm permissions are minimal.">
          <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
            <PermRow label="Spot trading"   ok />
            <PermRow label="Read account"   ok />
            <PermRow label="Withdraw"       ok={false} required="must be OFF" />
            <PermRow label="Futures"        ok={false} required="not needed for MVP" />
          </div>
        </FieldRow>

        <FieldRow label="Connection test" hint={"Last verified 14s ago · " + ex.rttMs + "ms round-trip to " + ex.name}>
          <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
            <Badge variant="profit">● Connected</Badge>
            <span className="mono" style={{ fontSize: 11.5, color: "var(--text-3)" }}>spot · {ex.testnet ? "testnet" : "paper"} · balance: $10,000.00 USDT</span>
            <PrimaryBtn ghost icon={<IconRefresh size={13} />} style={{ marginLeft: "auto" }}>Re-test</PrimaryBtn>
          </div>
        </FieldRow>

        <FieldRow label="Rate limit" hint={"CCXT enableRateLimit honours " + ex.name + "'s ceiling automatically."}>
          <div style={{ display: "flex", alignItems: "center", gap: 12, fontSize: 12.5, color: "var(--text-2)" }}>
            <span className="mono">{ex.rateLimit}</span>
            {!ex.oco && <Badge variant="warn">stricter — auto extra-delay on Kraken</Badge>}
          </div>
        </FieldRow>
      </SettingsCard>
    </div>
  );
}

function ModeCard({ active, onClick, label, sub, tag, tagColor, disabled }) {
  return (
    <button onClick={disabled ? undefined : onClick} disabled={disabled} className="focus-ring" style={{
      padding: 16, borderRadius: 12, textAlign: "left",
      background: active ? "var(--accent-soft)" : "rgba(255,255,255,0.02)",
      border: "1px solid " + (active ? "rgba(0,212,170,0.4)" : "var(--line)"),
      color: "var(--text)", cursor: disabled ? "not-allowed" : "pointer",
      display: "flex", flexDirection: "column", gap: 8,
      transition: "all .15s", opacity: disabled ? 0.4 : 1,
    }}>
      <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
        <span style={{
          width: 18, height: 18, borderRadius: 999,
          border: "2px solid " + (active ? "var(--accent)" : "var(--text-3)"),
          background: active ? "var(--accent)" : "transparent",
          display: "flex", alignItems: "center", justifyContent: "center",
        }}>
          {active && <span style={{ width: 6, height: 6, borderRadius: 999, background: "#06150F" }} />}
        </span>
        <span style={{ fontSize: 14, fontWeight: 600 }}>{label}</span>
        <span style={{ marginLeft: "auto", fontSize: 10, fontWeight: 600, padding: "2px 7px", borderRadius: 4, color: tagColor, background: "rgba(255,255,255,0.04)", letterSpacing: 0.3, textTransform: "uppercase" }}>{tag}</span>
      </div>
      <div style={{ fontSize: 12, color: "var(--text-2)", lineHeight: 1.5 }}>{sub}</div>
    </button>
  );
}

function PermRow({ label, ok, required }) {
  const expected = required != null ? !ok : ok;
  const c = expected ? "var(--profit)" : "var(--loss)";
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 12 }}>
      <span style={{ color: c }}>{expected ? <IconCheck size={14} /> : <IconX size={14} />}</span>
      <span style={{ color: "var(--text-2)" }}>{label}</span>
      <span className="mono" style={{ marginLeft: "auto", fontSize: 10.5, color: "var(--text-3)" }}>{required || (ok ? "enabled" : "disabled")}</span>
    </div>
  );
}

// =====================================================================
function StrategySettings({ activeExchange = "binance" }) {
  const ex = EXCHANGES[activeExchange] || EXCHANGES.binance;
  return (
    <SettingsCard title="Strategy parameters" subtitle="MVP runs a single pair · multi-pair ships in v2">
      <FieldRow label="Trading pair" hint={"Stored canonical as BTC/USDT · CCXT maps to " + ex.nativeSymbol + " on " + ex.name + ". TRADING_PAIR env var."}>
        <div style={{ display: "flex", alignItems: "center", gap: 10, padding: "10px 14px", borderRadius: 8, border: "1px solid var(--line-strong)", background: "rgba(255,255,255,0.02)" }}>
          <div style={{ width: 24, height: 24, borderRadius: 6, background: "#F7931A", display: "flex", alignItems: "center", justifyContent: "center", color: "#fff", fontWeight: 700, fontSize: 12 }}>₿</div>
          <div style={{ flex: 1 }}>
            <div style={{ fontFamily: "JetBrains Mono", fontSize: 13, fontWeight: 500 }}>BTC/USDT</div>
            <div className="mono" style={{ fontSize: 10.5, color: "var(--text-3)", marginTop: 2 }}>native on {ex.name}: {ex.nativeSymbol} · normalised by CCXT</div>
          </div>
          <Badge>Spot</Badge>
        </div>
      </FieldRow>

      <FieldRow label="Timeframe" hint="Must match the TradingView Pine Script chart timeframe.">
        <SegmentedRadio value="5m" options={["1m", "5m", "15m", "1h", "4h", "1d"]} />
      </FieldRow>

      <FieldRow label="Signal source" hint="MVP uses TradingView Pine v5. Bot does not calculate indicators.">
        <div style={{ display: "flex", alignItems: "center", gap: 10, padding: "10px 14px", borderRadius: 8, border: "1px solid var(--line-strong)", background: "rgba(255,255,255,0.02)" }}>
          <IconTV size={20} />
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 13, fontWeight: 500 }}>TradingView Pine v5</div>
            <div className="mono" style={{ fontSize: 11, color: "var(--text-3)" }}>EMA(9/21) Cross + RSI(14) &gt; 50 filter</div>
          </div>
          <PrimaryBtn ghost icon={<IconExternal size={13} />}>Open script</PrimaryBtn>
        </div>
      </FieldRow>

      <FieldRow label="Order type" hint="MVP is locked to market orders. Limit orders ship in v2.">
        <SegmentedRadio value="MARKET" options={["MARKET", "LIMIT"]} disabledOptions={["LIMIT"]} />
      </FieldRow>

      <FieldRow label="Max concurrent positions" hint="No pyramiding — additional signals are rejected while a position is open.">
        <SegmentedRadio value="1" options={["1", "2", "3", "Unlimited"]} disabledOptions={["2", "3", "Unlimited"]} />
      </FieldRow>

      <FieldRow label="Take profit" hint="Deferred for MVP — exits via reverse signal or stop loss only.">
        <div style={{ display: "flex", alignItems: "center", gap: 10, fontSize: 12.5, color: "var(--text-3)" }}>
          <Toggle value={false} />
          <span>Disabled · v2 will add fixed & trailing TP</span>
        </div>
      </FieldRow>
    </SettingsCard>
  );
}

function SegmentedRadio({ value, options, disabledOptions = [] }) {
  return (
    <div style={{ display: "inline-flex", padding: 3, background: "rgba(255,255,255,0.04)", borderRadius: 8, gap: 2 }}>
      {options.map((o) => {
        const active = o === value;
        const disabled = disabledOptions.includes(o);
        return (
          <button key={o} disabled={disabled} className="focus-ring" style={{
            padding: "6px 14px", borderRadius: 6, fontSize: 12, fontWeight: 500, border: 0,
            background: active ? "rgba(255,255,255,0.08)" : "transparent",
            color: disabled ? "var(--text-3)" : active ? "var(--text)" : "var(--text-2)",
            fontFamily: "JetBrains Mono", cursor: disabled ? "not-allowed" : "pointer",
            opacity: disabled ? 0.4 : 1,
          }}>{o}</button>
        );
      })}
    </div>
  );
}

// =====================================================================
function RiskSettings({ activeExchange = "binance" }) {
  const ex = EXCHANGES[activeExchange] || EXCHANGES.binance;
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--row-gap)" }}>
      <SettingsCard title="Position sizing" subtitle="How much capital each trade uses">
        <FieldRow label="Risk per trade" hint="% of equity to risk per signal. Lower = safer, but smaller wins.">
          <SliderSetting value={1.0} min={0.5} max={3.0} step={0.1} unit="%" envKey="RISK_PER_TRADE_PCT" />
        </FieldRow>
        <FieldRow label="Stop loss distance" hint={"% below entry where the " + ex.stopLoss.toLowerCase() + " is placed."}>
          <SliderSetting value={2.0} min={1.0} max={4.0} step={0.1} unit="%" envKey="STOP_LOSS_PCT" />
        </FieldRow>
        <FieldRow label="Stop loss placement" hint={ex.oco ? "Binance supports native OCO orders · survives bot crashes." : "Kraken's OCO equivalent is conditional close — attached to opening order via close param."}>
          <SegmentedRadio
            value={ex.oco ? "OCO" : "Conditional close"}
            options={ex.oco ? ["OCO", "Internal"] : ["Conditional close", "Internal"]}
          />
        </FieldRow>
        <FieldRow label="Min notional" hint={ex.name + " minimum order value, queried at startup."}>
          <TextInput value="10" suffix={ex.name === "Kraken" ? "USD" : "USDT"} mono />
        </FieldRow>
      </SettingsCard>

      <SettingsCard title="Circuit breakers" subtitle="Auto-halt conditions">
        <FieldRow label="Max daily loss" hint="Halts trading until 00:00 UTC if breached. Recommended: 2–3%.">
          <SliderSetting value={3.0} min={1.0} max={5.0} step={0.5} unit="%" envKey="MAX_DAILY_LOSS_PCT" warn={3.0} />
        </FieldRow>
        <FieldRow label="Max drawdown (kill switch)" hint="Permanent halt — requires manual restart.">
          <SliderSetting value={15.0} min={5.0} max={25.0} step={1.0} unit="%" envKey="MAX_DRAWDOWN_PCT" warn={15.0} />
        </FieldRow>
        <FieldRow label="Max consecutive losses" hint="Auto-pause after N losses in a row.">
          <SegmentedRadio value="5" options={["3", "5", "7", "10", "Off"]} />
        </FieldRow>
        <FieldRow label="Daily reset time" hint="UTC time the daily loss counter resets.">
          <TextInput value="00:00" suffix="UTC" mono />
        </FieldRow>
        <FieldRow label="Auto-resume" hint="When circuit breaker trips, resume automatically after N hours, or require manual restart.">
          <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
            <Toggle value={false} />
            <span style={{ fontSize: 12, color: "var(--text-2)" }}>Require manual /resume command via Telegram</span>
          </div>
        </FieldRow>
      </SettingsCard>

      <SettingsCard title="Signal deduplication" subtitle="Drop duplicate TradingView webhooks">
        <FieldRow label="Enabled" hint="TradingView can retry webhooks on network blips. Drop same signal_id within window.">
          <Toggle value={true} />
        </FieldRow>
        <FieldRow label="Window" hint="How long to remember signal IDs.">
          <SegmentedRadio value="60s" options={["30s", "60s", "120s", "300s"]} />
        </FieldRow>
      </SettingsCard>
    </div>
  );
}

function SliderSetting({ value, min, max, step, unit, envKey, warn }) {
  const pct = ((value - min) / (max - min)) * 100;
  const warnPct = warn != null ? ((warn - min) / (max - min)) * 100 : null;
  return (
    <div>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 8 }}>
        <span className="mono" style={{ fontSize: 18, fontWeight: 600, color: "var(--accent)" }}>{value}{unit}</span>
        <span className="mono" style={{ fontSize: 11, color: "var(--text-3)" }}>{envKey}</span>
      </div>
      <div style={{ position: "relative", height: 6, background: "rgba(255,255,255,0.05)", borderRadius: 3 }}>
        <div style={{ width: pct + "%", height: "100%", background: "var(--accent)", borderRadius: 3 }} />
        <div style={{ position: "absolute", left: `calc(${pct}% - 6px)`, top: -4, width: 14, height: 14, borderRadius: 999, background: "var(--accent)", border: "2px solid var(--bg)" }} />
        {warnPct != null && (
          <div style={{ position: "absolute", left: warnPct + "%", top: -3, bottom: -3, width: 1, background: "var(--warn)" }} title="warning threshold" />
        )}
      </div>
      <div className="mono" style={{ display: "flex", justifyContent: "space-between", marginTop: 6, fontSize: 10, color: "var(--text-3)" }}>
        <span>{min}{unit}</span>
        <span>{max}{unit}</span>
      </div>
    </div>
  );
}

// =====================================================================
function WebhookSettings() {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--row-gap)" }}>
      <SettingsCard title="Webhook endpoint" subtitle="POST endpoint that receives TradingView alerts">
        <FieldRow label="URL" hint="Paste this into the TradingView alert 'Webhook URL' field.">
          <div style={{ display: "flex", gap: 8 }}>
            <TextInput value="https://api.helix.trade/webhook" mono />
            <IconBtn title="Copy"><IconCopy size={14} /></IconBtn>
          </div>
        </FieldRow>
        <FieldRow label="Webhook secret" hint="Passed in X-Webhook-Secret header. Bot rejects requests without it.">
          <div style={{ display: "flex", gap: 8 }}>
            <TextInput value="whsec_8K2pQ7v4M9nLj1WtR8sZyB6dF3cVuG5h" mono type="password" />
            <IconBtn title="Show"><IconEye size={14} /></IconBtn>
            <IconBtn title="Rotate"><IconRefresh size={14} /></IconBtn>
          </div>
        </FieldRow>
        <FieldRow label="Rate limit" hint="Max webhook hits per minute. Higher = more API load, more dedup work.">
          <SegmentedRadio value="10/min" options={["5/min", "10/min", "30/min", "60/min"]} />
        </FieldRow>
        <FieldRow label="IP allowlist" hint="Restrict to TradingView's webhook IPs only.">
          <div style={{ display: "flex", flexDirection: "column", gap: 6, fontFamily: "JetBrains Mono", fontSize: 12 }}>
            {["52.89.214.238", "34.212.75.30", "54.218.53.128", "52.32.178.7"].map((ip) => (
              <div key={ip} style={{ display: "flex", alignItems: "center", gap: 10, padding: "8px 12px", borderRadius: 6, background: "rgba(255,255,255,0.02)", border: "1px solid var(--line)" }}>
                <span style={{ color: "var(--profit)" }}>●</span>
                <span style={{ color: "var(--text-2)" }}>{ip}</span>
                <span style={{ marginLeft: "auto", color: "var(--text-3)", fontSize: 10.5 }}>TradingView</span>
              </div>
            ))}
          </div>
        </FieldRow>
      </SettingsCard>

      <SettingsCard title="Payload format" subtitle="Required JSON shape for incoming alerts">
        <CodeBlock>
          {"{\n"}
          {"  "}<span style={{ color: "#FCD34D" }}>"signal"</span>:    <span style={{ color: "var(--profit)" }}>"BUY"</span>{"     "}<span style={{ color: "var(--text-3)" }}>// or "SELL"</span>{"\n"}
          {"  "}<span style={{ color: "#FCD34D" }}>"symbol"</span>:    <span style={{ color: "var(--profit)" }}>"BTC/USDT"</span>{"\n"}
          {"  "}<span style={{ color: "#FCD34D" }}>"price"</span>:     <span style={{ color: "var(--info)" }}>{"{{close}}"}</span>{"\n"}
          {"  "}<span style={{ color: "#FCD34D" }}>"timestamp"</span>: <span style={{ color: "var(--info)" }}>{"{{timenow}}"}</span>{"\n"}
          {"  "}<span style={{ color: "#FCD34D" }}>"strategy"</span>:  <span style={{ color: "var(--profit)" }}>"ema_crossover"</span>{"\n"}
          {"  "}<span style={{ color: "#FCD34D" }}>"signal_id"</span>: <span style={{ color: "var(--info)" }}>{"{{strategy.order.id}}"}</span> <span style={{ color: "var(--text-3)" }}>// REQUIRED for dedup</span>{"\n"}
          {"}"}
        </CodeBlock>
      </SettingsCard>
    </div>
  );
}

// =====================================================================
function TelegramSettings() {
  return (
    <SettingsCard title="Telegram bot" subtitle="@BotFather setup · chat ID lookup">
      <FieldRow label="Bot token" hint="Get from @BotFather on Telegram. Format: 123456:ABC-DEF...">
        <TextInput value="••••••••••:••••••••••••••••••••••••••••••••" mono type="password" />
      </FieldRow>
      <FieldRow label="Chat ID" hint="Your personal Telegram user/chat ID. Only this ID can issue commands.">
        <TextInput value="487291842" mono />
      </FieldRow>
      <FieldRow label="Connection status" hint="Last successful delivery 6 seconds ago.">
        <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
          <Badge variant="profit">● Connected</Badge>
          <span className="mono" style={{ fontSize: 11.5, color: "var(--text-3)" }}>@AutoTraderBot · API v6.9</span>
          <PrimaryBtn ghost icon={<IconBolt size={13} />} style={{ marginLeft: "auto" }}>Send test</PrimaryBtn>
        </div>
      </FieldRow>
      <FieldRow label="Daily summary" hint="Send daily P&L recap at this UTC time.">
        <TextInput value="23:59" suffix="UTC" mono />
      </FieldRow>
    </SettingsCard>
  );
}

// =====================================================================
function SecuritySettings({ activeExchange = "binance" }) {
  const ex = EXCHANGES[activeExchange] || EXCHANGES.binance;
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--row-gap)" }}>
      <SettingsCard title="Account security" subtitle="Protect your bot console">
        <FieldRow label="Two-factor authentication" hint="TOTP via Authy, 1Password, or Google Authenticator.">
          <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
            <Toggle value={true} />
            <Badge variant="profit">● Enabled</Badge>
            <PrimaryBtn ghost style={{ marginLeft: "auto" }}>Regenerate codes</PrimaryBtn>
          </div>
        </FieldRow>
        <FieldRow label="Session lifetime" hint="Auto-logout after inactivity.">
          <SegmentedRadio value="1h" options={["15m", "1h", "8h", "24h"]} />
        </FieldRow>
        <FieldRow label="IP allowlist (admin)" hint="Restrict dashboard access to specific IPs. Empty = allow all.">
          <TextInput value="84.198.42.118, 31.220.5.0/24" mono placeholder="comma-separated IPs or CIDR" />
        </FieldRow>
      </SettingsCard>

      <SettingsCard title="Infrastructure" subtitle="Where the bot runs">
        <FieldRow label="Deployment region" hint="Closer to exchange = lower latency.">
          <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
            <span className="mono" style={{ fontSize: 13, fontWeight: 500 }}>Dubai · Hetzner DC</span>
            <Badge variant="info">3.2ms to Binance</Badge>
          </div>
        </FieldRow>
        <FieldRow label="Exchange IP whitelisted" hint={"Bot's VPS IP must be added to " + ex.name + " API key whitelist."}>
          <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
            <span className="mono" style={{ fontSize: 13 }}>185.224.92.18</span>
            <Badge variant="profit">● Whitelisted on {ex.name}</Badge>
          </div>
        </FieldRow>
        <FieldRow label="API key audit" hint={"Verified the bot's " + ex.name + " key has Withdraw permission DISABLED."}>
          <Badge variant="profit">● Withdraw OFF · Trade ON · audit passed</Badge>
        </FieldRow>
        <FieldRow label="Audit log" hint="Track every config change. Required for compliance.">
          <Toggle value={true} label="Log all sensitive changes to /var/log/audit.log" />
        </FieldRow>
      </SettingsCard>

      <SettingsCard title="State recovery" subtitle="Reconcile DB with exchange on every startup">
        <FieldRow label="Reconcile on boot" hint="Compares last known DB state with exchange before resuming.">
          <Toggle value={true} label="Halt and alert if orphan position detected" />
        </FieldRow>
        <FieldRow label="Database backups" hint="SQLite snapshots before any schema migration.">
          <div style={{ fontSize: 12, color: "var(--text-2)", display: "flex", flexDirection: "column", gap: 6 }}>
            <span className="mono">trades.db.2026-05-15.bak · 1.4 MB</span>
            <span className="mono" style={{ color: "var(--text-3)" }}>trades.db.2026-05-14.bak · 1.3 MB</span>
            <span className="mono" style={{ color: "var(--text-3)" }}>trades.db.2026-05-13.bak · 1.3 MB</span>
          </div>
        </FieldRow>
      </SettingsCard>
    </div>
  );
}

// =====================================================================
function EnvSettings({ activeExchange = "binance" }) {
  const env = [
    { k: "ACTIVE_EXCHANGE",      v: activeExchange, req: true, desc: "binance | kraken · picks ExchangeClient at boot" },
    { k: "TRADING_MODE",         v: "testnet",    req: true,  desc: "testnet | live | paper (paper for Kraken)" },
    { k: "TRADING_PAIR",         v: "BTC/USDT",   req: false, desc: "CCXT-normalised symbol" },
    { k: "BINANCE_API_KEY",      v: activeExchange === "binance" ? "••••••••" : "—",   req: activeExchange === "binance", desc: "Only required when ACTIVE_EXCHANGE=binance" },
    { k: "BINANCE_API_SECRET",   v: activeExchange === "binance" ? "••••••••" : "—",   req: activeExchange === "binance", desc: "Only required when ACTIVE_EXCHANGE=binance" },
    { k: "KRAKEN_API_KEY",       v: activeExchange === "kraken" ? "••••••••" : "—",    req: activeExchange === "kraken",  desc: "Only required when ACTIVE_EXCHANGE=kraken" },
    { k: "KRAKEN_API_SECRET",    v: activeExchange === "kraken" ? "••••••••" : "—",    req: activeExchange === "kraken",  desc: "Base64-encoded private key" },
    { k: "TELEGRAM_BOT_TOKEN",   v: "••••••••",   req: true,  desc: "From @BotFather" },
    { k: "TELEGRAM_CHAT_ID",     v: "487291842",  req: true,  desc: "Personal chat ID" },
    { k: "WEBHOOK_SECRET",       v: "••••••••",   req: true,  desc: "Validates TradingView requests" },
    { k: "LOG_LEVEL",            v: "INFO",       req: false, desc: "DEBUG | INFO | WARNING" },
    { k: "RISK_PER_TRADE_PCT",   v: "1.0",        req: false, desc: "Default 1.0" },
    { k: "MAX_DAILY_LOSS_PCT",   v: "3.0",        req: false, desc: "Default 3.0" },
    { k: "MAX_DRAWDOWN_PCT",     v: "15.0",       req: false, desc: "Default 15.0" },
    { k: "STOP_LOSS_PCT",        v: "2.0",        req: false, desc: "Default 2.0" },
    { k: "MAX_CONSECUTIVE_LOSSES", v: "5",        req: false, desc: "Default 5" },
    { k: "HOST",                 v: "0.0.0.0",    req: false, desc: "FastAPI bind" },
    { k: "PORT",                 v: "8000",       req: false, desc: "FastAPI port" },
  ];
  return (
    <SettingsCard title="Environment variables" subtitle="Loaded from .env via pydantic-settings · never logged"
      footer={
        <>
          <PrimaryBtn ghost icon={<IconDown size={13} />}>Download .env.example</PrimaryBtn>
          <PrimaryBtn icon={<IconRefresh size={13} />}>Restart bot to apply</PrimaryBtn>
        </>
      }>
      <div style={{ overflowX: "auto" }}>
        <table style={{ width: "100%", borderCollapse: "collapse", fontSize: 12.5 }}>
          <thead>
            <tr style={{ color: "var(--text-3)", fontSize: 10.5, letterSpacing: 0.5, textTransform: "uppercase" }}>
              <th style={th()}>Key</th>
              <th style={th()}>Value</th>
              <th style={th()}>Required</th>
              <th style={th()}>Description</th>
            </tr>
          </thead>
          <tbody>
            {env.map((e) => (
              <tr key={e.k} style={{ borderTop: "1px solid var(--line)" }}>
                <td style={td()}><code className="mono" style={{ fontSize: 11, color: "var(--accent)" }}>{e.k}</code></td>
                <td style={td()}><span className="mono" style={{ fontSize: 11.5, color: "var(--text)" }}>{e.v}</span></td>
                <td style={td()}>
                  {e.req
                    ? <Badge variant="loss">required</Badge>
                    : <Badge>optional</Badge>}
                </td>
                <td style={td()}><span style={{ fontSize: 11.5, color: "var(--text-3)" }}>{e.desc}</span></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </SettingsCard>
  );
}

// =====================================================================
function DangerZone() {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--row-gap)" }}>
      <Card title="Danger zone" subtitle="Irreversible actions. Confirm twice."
        style={{ borderColor: "rgba(242,63,92,0.25)" }}>
        <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
          <DangerRow
            title="Close all positions at market"
            desc="Force-closes every open position via market orders. Use only in true emergency."
            btn="Close all"
            btnIcon={<IconStop size={13} />}
          />
          <DangerRow
            title="Reset trade history"
            desc="Deletes all trades, signals, and daily stats from SQLite. Cannot be undone."
            btn="Wipe history"
            btnIcon={<IconX size={13} />}
          />
          <DangerRow
            title="Disconnect exchange"
            desc="Removes Binance API key. Bot halts immediately."
            btn="Disconnect"
            btnIcon={<IconKey size={13} />}
          />
          <DangerRow
            title="Switch to live trading"
            desc="Real funds. Real losses. Confirm 7+ days of testnet runtime first."
            btn="Enable live mode"
            btnIcon={<IconBolt size={13} />}
          />
          <DangerRow
            title="Delete bot instance"
            desc="Tears down the FastAPI service, removes config, retains backups for 30 days."
            btn="Delete bot"
            btnIcon={<IconAlert size={13} />}
          />
        </div>
      </Card>
    </div>
  );
}

function DangerRow({ title, desc, btn, btnIcon }) {
  return (
    <div style={{
      display: "flex", alignItems: "center", gap: 16, padding: 14, borderRadius: 10,
      background: "rgba(242,63,92,0.04)", border: "1px solid rgba(242,63,92,0.18)",
    }}>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 13.5, fontWeight: 600, color: "var(--text)" }}>{title}</div>
        <div style={{ fontSize: 12, color: "var(--text-3)", marginTop: 3, lineHeight: 1.5 }}>{desc}</div>
      </div>
      <PrimaryBtn danger icon={btnIcon}>{btn}</PrimaryBtn>
    </div>
  );
}

Object.assign(window, { SettingsPage });
