// Control — kill-switch, force-jump (2-step + TOTP), config reload.
const { Card, Pill, fmtTs } = window.UI;

function PageControl({ app, setApp }) {
  return (
    <div className="p-4 space-y-4">
      <div>
        <h1 className="text-[16px] font-medium text-ink-0">control</h1>
        <p className="mono text-[11px] text-ink-3 mt-0.5">operator actions · changes here move real funds in <span className="text-neg-0">live</span> mode</p>
      </div>

      <div className="grid grid-cols-12 gap-4">
        <div className="col-span-5"><KillSwitchCard app={app} setApp={setApp}/></div>
        <div className="col-span-4"><ForceJumpCard app={app}/></div>
        <div className="col-span-3"><ReloadCard /></div>
      </div>
    </div>
  );
}

function KillSwitchCard({ app, setApp }) {
  const [confirm, setConfirm] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');
  const halted = app.halted;
  const reason = halted || '';

  const halt = async () => {
    if (confirm.trim() !== 'HALT') return;
    setBusy(true); setErr('');
    try {
      const r = await window.API.post('/api/v1/control/halt', { reason: 'manual: stopped via /control by operator' });
      setApp(s => ({ ...s, halted: r.reason || 'manual halt' }));
      setConfirm('');
    } catch (e) {
      setErr(e.message || 'halt failed');
    } finally { setBusy(false); }
  };
  const resume = async () => {
    setBusy(true); setErr('');
    try {
      await window.API.post('/api/v1/control/resume', {});
      setApp(s => ({ ...s, halted: null }));
    } catch (e) {
      setErr(e.message || 'resume failed');
    } finally { setBusy(false); }
  };

  return (
    <Card title="kill-switch" sub={halted ? 'halted' : 'running'} padded={false} className="h-full">
      <div className="p-4 space-y-4">
        <div className={`p-4 border ${halted ? 'border-neg-1/40 bg-neg-2/15' : 'border-pos-1/40 bg-pos-2/15'}`}>
          <div className="flex items-center gap-3">
            <div className={`w-10 h-10 grid place-items-center ${halted ? 'bg-neg-1 text-bg-0' : 'bg-pos-1 text-bg-0'}`}>
              {halted ? <Icon.Halt size={20}/> : <Icon.Power size={20}/>}
            </div>
            <div className="flex-1">
              <div className={`mono text-[14px] uppercase tracking-[0.14em] font-semibold ${halted ? 'text-neg-0' : 'text-pos-0'}`}>
                {halted ? 'system halted' : 'system running'}
              </div>
              {halted && (
                <div className="mono text-[11px] text-ink-2 mt-1 leading-relaxed break-all">{reason}</div>
              )}
              {/* "last trip" needs an api_events lookup that ships in
                  M11.2 alongside the risk gate; suppressed for now to
                  avoid showing a fake timestamp. */}
            </div>
          </div>
        </div>

        {!halted ? (
          <div className="space-y-2">
            <label className="block">
              <span className="text-[10.5px] uppercase tracking-[0.14em] text-ink-3 mono">type <span className="text-amb-0">HALT</span> to confirm</span>
              <input value={confirm} onChange={e => setConfirm(e.target.value)} placeholder="HALT" disabled={busy}
                className="mt-1 w-full bg-bg-2 border border-line-1 mono text-[13px] tracking-[0.2em] uppercase px-3 h-9 text-amb-0 focus:border-neg-1 outline-none disabled:opacity-50"/>
            </label>
            <button disabled={busy || confirm.trim() !== 'HALT'} onClick={halt}
              className="w-full h-10 mono text-[12px] uppercase tracking-[0.14em] flex items-center justify-center gap-2 bg-neg-2 border border-neg-1 text-ink-0 hover:bg-neg-1 disabled:opacity-30 disabled:cursor-not-allowed transition-colors">
              <Icon.Halt size={14}/> {busy ? 'halting…' : 'halt all accounts'}
            </button>
            <p className="mono text-[10.5px] text-ink-3 leading-relaxed">stops the dispatcher; in-flight orders are reconciled but no new intents are emitted. persists across restart.</p>
          </div>
        ) : (
          <div className="space-y-2">
            <button onClick={resume} disabled={busy} className="w-full h-10 mono text-[12px] uppercase tracking-[0.14em] flex items-center justify-center gap-2 bg-pos-2 border border-pos-1 text-ink-0 hover:bg-pos-1 disabled:opacity-50">
              <Icon.Power size={14}/> {busy ? 'resuming…' : 'resume bot'}
            </button>
            <p className="mono text-[10.5px] text-ink-3 leading-relaxed">resume re-arms the dispatcher. risk gates are re-evaluated before any new order is sent.</p>
          </div>
        )}
        {err && (
          <div className="bg-neg-2/30 border border-neg-1/40 p-2 mono text-[11px] text-neg-0 break-all">{err}</div>
        )}
      </div>
    </Card>
  );
}

function ForceJumpCard({ app }) {
  const acct = (app.accounts || []).find(a => a.id === app.account) || null;
  const coins = (acct && Array.isArray(acct.coins))
    ? acct.coins.filter(c => c !== acct.bridge)
    : [];
  const initialFrom = (acct && acct.current_coin) || coins[0] || '';
  const initialTo = coins.find(c => c !== initialFrom) || '';
  const [step, setStep] = React.useState(1);
  const [from, setFrom] = React.useState(initialFrom);
  const [to, setTo] = React.useState(initialTo);
  const [note, setNote] = React.useState('');
  const [nonce, setNonce] = React.useState('');
  const [code, setCode] = React.useState('');
  const [entered, setEntered] = React.useState('');
  const [done, setDone] = React.useState(false);
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');

  const request = async () => {
    setBusy(true); setErr('');
    try {
      const r = await window.API.post('/api/v1/control/force-jump', {
        action: 'request',
        account_id: acct ? acct.accountID : 0,
        from, to, note,
      });
      setNonce(r.nonce || ''); setCode(r.code || ''); setStep(2);
    } catch (e) { setErr(e.message || 'request failed'); }
    finally { setBusy(false); }
  };
  const confirm = async () => {
    setBusy(true); setErr('');
    try {
      await window.API.post('/api/v1/control/force-jump', {
        action: 'confirm', nonce, code: entered,
      });
      setDone(true);
    } catch (e) { setErr(e.message || 'confirm failed'); }
    finally { setBusy(false); }
  };
  const reset = () => { setStep(1); setNonce(''); setCode(''); setEntered(''); setDone(false); setNote(''); setErr(''); };

  return (
    <Card title="force-jump" sub="manual override" padded={false} className="h-full">
      <div className="p-4 space-y-3">
        {/* progress */}
        <div className="flex items-center gap-1.5">
          <StepDot active={step >= 1} done={step > 1}>request</StepDot>
          <div className={`flex-1 h-px ${step > 1 ? 'bg-pos-0' : 'bg-line-0'}`}></div>
          <StepDot active={step >= 2} done={done}>confirm</StepDot>
        </div>

        {step === 1 && !done && (
          <>
            <div className="grid grid-cols-2 gap-2">
              <label className="block">
                <span className="text-[10px] uppercase tracking-[0.14em] text-ink-3 mono">from</span>
                <select value={from} onChange={e => setFrom(e.target.value)}
                  className="mt-1 w-full bg-bg-2 border border-line-1 mono text-[12px] h-8 px-2 text-ink-0 outline-none">
                  {coins.map(c => <option key={c}>{c}</option>)}
                </select>
              </label>
              <label className="block">
                <span className="text-[10px] uppercase tracking-[0.14em] text-ink-3 mono">to</span>
                <select value={to} onChange={e => setTo(e.target.value)}
                  className="mt-1 w-full bg-bg-2 border border-line-1 mono text-[12px] h-8 px-2 text-ink-0 outline-none">
                  {coins.filter(c => c !== from).map(c => <option key={c}>{c}</option>)}
                </select>
              </label>
            </div>
            <div className="bg-bg-2 px-3 py-2 mono text-[11px] flex items-center justify-center gap-2">
              <span className="text-ink-1">{from}</span>
              <Icon.ArrowRight size={11} className="text-ink-3"/>
              <span className="text-ink-1">{to}</span>
            </div>
            <label className="block">
              <span className="text-[10px] uppercase tracking-[0.14em] text-ink-3 mono">note (optional)</span>
              <input value={note} onChange={e => setNote(e.target.value)} placeholder="reason for manual jump"
                className="mt-1 w-full bg-bg-2 border border-line-1 mono text-[12px] h-8 px-2 text-ink-1 outline-none"/>
            </label>
            <button onClick={request} disabled={busy}
              className="w-full h-9 mono text-[11.5px] uppercase tracking-[0.12em] bg-bg-2 border border-line-2 text-ink-0 hover:bg-bg-3 disabled:opacity-50">
              {busy ? 'requesting…' : 'request →'}
            </button>
            {err && <div className="bg-neg-2/30 border border-neg-1/40 p-2 mono text-[11px] text-neg-0 break-all">{err}</div>}
          </>
        )}

        {step === 2 && !done && (
          <>
            <div className="bg-bg-0 border border-line-0 p-3 space-y-2">
              <div className="flex items-center justify-between">
                <span className="text-[10px] uppercase tracking-[0.14em] text-ink-3 mono">nonce</span>
                <span className="mono text-[11.5px] text-ink-1">{nonce}</span>
              </div>
              <div>
                <span className="text-[10px] uppercase tracking-[0.14em] text-ink-3 mono">verification code</span>
                <div className="mt-1 mono text-[28px] tracking-[0.4em] text-amb-0 text-center font-medium">{code}</div>
                <p className="mono text-[10px] text-ink-3 text-center mt-1">re-enter below</p>
              </div>
            </div>
            <input value={entered} onChange={e => setEntered(e.target.value.replace(/\D/g,'').slice(0,6))}
              placeholder="000000" autoFocus
              className="w-full bg-bg-2 border border-line-1 mono text-[20px] tracking-[0.4em] text-center h-12 text-ink-0 focus:border-amb-0 outline-none"/>
            <div className="grid grid-cols-2 gap-2">
              <button onClick={reset} disabled={busy} className="h-9 mono text-[11px] uppercase tracking-[0.12em] border border-line-1 text-ink-2 hover:text-ink-0 disabled:opacity-50">cancel</button>
              <button disabled={busy || entered.length !== 6} onClick={confirm}
                className="h-9 mono text-[11.5px] uppercase tracking-[0.12em] bg-amb-1/30 border border-amb-1 text-amb-0 hover:bg-amb-1/50 disabled:opacity-30 disabled:cursor-not-allowed">
                {busy ? 'confirming…' : 'confirm jump'}
              </button>
            </div>
            {err && <div className="bg-neg-2/30 border border-neg-1/40 p-2 mono text-[11px] text-neg-0 break-all">{err}</div>}
          </>
        )}

        {done && (
          <div className="text-center space-y-3 py-4">
            <div className="w-10 h-10 mx-auto grid place-items-center bg-pos-2 border border-pos-1"><Icon.Check size={18} className="text-pos-0"/></div>
            <div className="mono text-[12px] text-ink-0">force-jump submitted</div>
            <div className="mono text-[11px] text-ink-3">{from} → {to} · queued in outbox</div>
            <button onClick={reset} className="mono text-[11px] text-inf-0 hover:text-ink-0">new request</button>
          </div>
        )}
      </div>
    </Card>
  );
}

function StepDot({ active, done, children }) {
  return (
    <div className="flex items-center gap-1.5">
      <div className={`w-4 h-4 grid place-items-center mono text-[9px] ${done ? 'bg-pos-1 text-bg-0' : active ? 'bg-bg-3 border border-line-2 text-ink-0' : 'bg-bg-2 border border-line-0 text-ink-3'}`}>
        {done ? '✓' : (active ? '•' : '·')}
      </div>
      <span className={`text-[10px] uppercase tracking-[0.14em] mono ${active ? 'text-ink-1' : 'text-ink-3'}`}>{children}</span>
    </div>
  );
}

function ReloadCard() {
  const [state, setState] = React.useState('idle'); // idle, loading, ok, diff
  const reload = () => {
    setState('loading');
    setTimeout(() => setState(Math.random() > 0.5 ? 'ok' : 'diff'), 700);
  };
  return (
    <Card title="config reload" sub="from disk" padded={false} className="h-full">
      <div className="p-4 space-y-3">
        <p className="mono text-[10.5px] text-ink-3 leading-relaxed">re-reads <span className="text-ink-1">configs/bot.yaml</span>. compatible changes apply hot; incompatible diffs are reported.</p>
        <button onClick={reload} disabled={state === 'loading'}
          className="w-full h-9 mono text-[11.5px] uppercase tracking-[0.12em] bg-bg-2 border border-line-2 text-ink-0 hover:bg-bg-3 inline-flex items-center justify-center gap-2 disabled:opacity-50">
          <Icon.Reload size={13} className={state === 'loading' ? 'animate-spin' : ''}/>
          {state === 'loading' ? 'reloading…' : 'reload bot.yaml'}
        </button>
        {state === 'ok' && (
          <div className="bg-pos-2/20 border border-pos-1/30 p-2 mono text-[11px] text-pos-0 flex items-center gap-2">
            <Icon.Check size={12}/> reload ok · 0 incompatible
          </div>
        )}
        {state === 'diff' && (
          <div className="bg-amb-1/15 border border-amb-1/30 p-2 mono text-[11px] space-y-1">
            <div className="text-amb-0 flex items-center gap-2"><Icon.AlertTri size={12}/> 2 incompatible changes</div>
            <pre className="text-ink-2 leading-relaxed text-[10.5px]">
{`- accounts[0].bridge: USDT → USDC
- strategy.binance-main.ema_alpha: 0.05 → 0.01`}
            </pre>
            <div className="text-ink-3 text-[10px] mt-1">requires bot restart to apply</div>
          </div>
        )}
      </div>
    </Card>
  );
}

window.PageControl = PageControl;
