// Pairs page — coin-by-coin ratio heatmap, color by effective score.
const { Card, Pill, fmtNum, fmtPct, fmtTs } = window.UI;

// adapt one apiPair (string decimals + updated_at_ms) to the table-cell
// shape this page already renders.
function adaptPair(p) {
  return {
    from: p.from,
    to: p.to,
    current: parseFloat(p.current_ratio || '0') || 0,
    baseline: parseFloat(p.baseline || '0') || 0,
    raw_score: parseFloat(p.raw_score || '0') || 0,
    eff_score: parseFloat(p.eff_score || '0') || 0,
    last_decision: 'observed',
    margin: 0,
    multiplier: 0,
    ema_alpha: 0,
    updated_at: p.updated_at_ms || 0,
  };
}

function PagePairs({ app }) {
  const acct = (app.accounts || []).find(a => a.id === app.account) || null;
  const accountID = acct && acct.accountID;
  const [selected, setSelected] = React.useState(null);

  const { data: rawPairs, error, loading, refresh } = window.API.useAPI(
    () => accountID ? window.API.get('/api/v1/pairs', { account_id: accountID }) : Promise.resolve([]),
    [accountID],
  );

  // Pairs come exclusively from the backend. The matrix is empty until
  // the strategy scout has populated baselines (M11.2). No mock fallback.
  const pairs = (rawPairs && Array.isArray(rawPairs)) ? rawPairs.map(adaptPair) : [];

  // Coin axis prefers any coin we've actually seen on a pair; otherwise
  // fall back to the configured account's coin list so the matrix
  // shows the empty grid rather than nothing at all.
  const coins = React.useMemo(() => {
    const set = new Set();
    for (const p of pairs) { set.add(p.from); set.add(p.to); }
    if (set.size > 0) return Array.from(set).sort();
    if (acct && Array.isArray(acct.coins)) {
      return acct.coins.filter(c => c !== acct.bridge).sort();
    }
    return [];
  }, [pairs.length, acct && (acct.coins || []).join(','), acct && acct.bridge]);

  const findPair = (a, b) => pairs.find(p => p.from === a && p.to === b);

  // map effective score to color: -0.05 red → 0 grey → +0.05 green
  const cellColor = (eff) => {
    if (eff == null) return null;
    const t = Math.max(-0.05, Math.min(0.05, eff)) / 0.05; // -1..1
    if (t > 0) {
      const a = Math.abs(t);
      return `rgba(95, 207, 149, ${0.06 + a * 0.45})`;
    } else {
      const a = Math.abs(t);
      return `rgba(224, 114, 98, ${0.06 + a * 0.45})`;
    }
  };

  return (
    <div className="p-4 space-y-4">
      <div className="flex items-end justify-between">
        <div>
          <h1 className="text-[16px] font-medium text-ink-0">pair matrix</h1>
          <p className="mono text-[11px] text-ink-3 mt-0.5">
            effective score = raw_score − 2·fee − slippage_from − slippage_to − spread − safety. positive = jump candidate.
            {' · '}
            {loading && <span className="text-ink-3">loading…</span>}
            {error && <span className="text-neg-0">api error</span>}
            {!loading && !error && (pairs.length ? <span className="text-pos-0">live</span> : <span className="text-ink-3">no pairs scouted yet</span>)}
            <button onClick={refresh} className="ml-2 text-inf-0 hover:text-ink-0 underline-offset-2 hover:underline">refresh</button>
          </p>
        </div>
        <Legend />
      </div>

      <Card padded={false}>
        <div className="overflow-auto scrollbar">
          <table className="border-collapse">
            <thead>
              <tr>
                <th className="bg-bg-1 sticky left-0 z-10 border-b border-r border-line-0 px-3 py-2 mono text-[10px] uppercase tracking-[0.1em] text-ink-3 text-left w-20">from \ to</th>
                {coins.map(c => (
                  <th key={c} className="border-b border-line-0 mono text-[11px] text-ink-1 px-3 py-2 text-center w-[88px]">{c}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {coins.map(from => (
                <tr key={from}>
                  <th className="bg-bg-1 sticky left-0 z-10 border-r border-line-0 px-3 py-1.5 mono text-[11px] text-ink-1 text-left">{from}</th>
                  {coins.map(to => {
                    if (from === to) {
                      const isHeld = !!(acct && from === acct.current_coin);
                      return (
                        <td key={to} className="text-center align-middle border-l border-t border-line-0 bg-bg-2/40 w-[88px] h-[58px]">
                          {isHeld ? (
                            <div className="flex flex-col items-center gap-0.5">
                              <span className="mono text-[9px] uppercase tracking-[0.14em] text-pos-0">held</span>
                              <span className="mono text-[12px] text-ink-0">{from}</span>
                            </div>
                          ) : (
                            <span className="text-ink-4 mono text-[14px]">·</span>
                          )}
                        </td>
                      );
                    }
                    const p = findPair(from, to);
                    const isSelected = selected && selected.from === from && selected.to === to;
                    return (
                      <td key={to}
                        onClick={() => setSelected(p)}
                        className={`text-center align-middle border-l border-t border-line-0 w-[88px] h-[58px] cursor-pointer transition-all ${isSelected ? 'outline outline-1 outline-inf-0 outline-offset-[-1px]' : 'hover:outline hover:outline-1 hover:outline-line-2 hover:outline-offset-[-1px]'}`}
                        style={{ backgroundColor: cellColor(p?.eff_score) }}
                      >
                        {p && (
                          <div className="flex flex-col leading-none">
                            <span className={`mono text-[11px] num ${p.eff_score > 0.005 ? 'text-pos-0' : p.eff_score < -0.005 ? 'text-neg-0' : 'text-ink-1'}`}>
                              {p.eff_score >= 0 ? '+' : ''}{(p.eff_score*100).toFixed(2)}
                            </span>
                            <span className="mono text-[9.5px] text-ink-3 mt-1">{fmtNum(p.current, 4)}</span>
                          </div>
                        )}
                      </td>
                    );
                  })}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </Card>

      {selected && <PairDrawer pair={selected} onClose={() => setSelected(null)} />}
    </div>
  );
}

function Legend() {
  const stops = [-0.05, -0.025, -0.01, 0, 0.01, 0.025, 0.05];
  return (
    <div className="flex items-center gap-3 text-[10.5px] mono text-ink-3">
      <span>eff. score</span>
      <div className="flex">
        {stops.map(s => {
          const t = Math.max(-0.05, Math.min(0.05, s)) / 0.05;
          const bg = t > 0
            ? `rgba(95,207,149,${0.06 + Math.abs(t)*0.45})`
            : t < 0
            ? `rgba(224,114,98,${0.06 + Math.abs(t)*0.45})`
            : '#161b22';
          return <div key={s} className="w-7 h-3 border-r border-line-0 last:border-r-0" style={{ backgroundColor: bg }}></div>;
        })}
      </div>
      <span>−5%</span>
      <span className="text-ink-2">0</span>
      <span>+5%</span>
    </div>
  );
}

function PairDrawer({ pair, onClose }) {
  // synthetic ratio history
  const history = React.useMemo(() => {
    const out = [];
    let v = pair.baseline;
    const target = pair.current;
    for (let i = 0; i < 100; i++) {
      const lerp = i / 99;
      v = pair.baseline + (target - pair.baseline) * lerp + Math.sin(i * 0.4) * pair.baseline * 0.005;
      out.push({ t: Date.now() - (100 - i) * 60000, ratio: v, baseline: pair.baseline });
    }
    return out;
  }, [pair]);

  const RC = window.Recharts;
  return (
    <>
      <div className="fixed inset-0 bg-black/40 z-40" onClick={onClose}></div>
      <aside className="fixed top-0 right-0 bottom-0 w-[460px] bg-bg-1 border-l border-line-1 z-50 flex flex-col">
        <header className="h-12 px-4 flex items-center justify-between border-b border-line-0">
          <div className="flex items-center gap-2">
            <span className="mono text-[13px] text-ink-0">{pair.from}</span>
            <Icon.ArrowRight size={13} className="text-ink-3"/>
            <span className="mono text-[13px] text-ink-0">{pair.to}</span>
            <Pill tone={pair.eff_score > 0.005 ? 'pos' : pair.eff_score < -0.005 ? 'neg' : 'ink'} className="ml-2">
              {pair.last_decision.replace(/_/g,' ')}
            </Pill>
          </div>
          <button onClick={onClose} className="p-1 text-ink-2 hover:text-ink-0"><Icon.X size={14}/></button>
        </header>
        <div className="p-4 space-y-4 overflow-auto scrollbar">
          {/* ratio vs baseline chart */}
          <div>
            <div className="text-[10px] uppercase tracking-[0.14em] text-ink-3 mono mb-2">ratio vs baseline · 100 ticks</div>
            <div style={{ height: 180 }}>
              <RC.ResponsiveContainer>
                <RC.LineChart data={history} margin={{ top: 6, right: 6, left: 0, bottom: 0 }}>
                  <RC.CartesianGrid stroke="#1f2630" vertical={false}/>
                  <RC.XAxis dataKey="t" hide />
                  <RC.YAxis tick={{ fontSize: 10, fontFamily: 'JetBrains Mono', fill: '#5b6573' }} axisLine={false} tickLine={false} width={56} tickFormatter={(v)=>v.toFixed(3)} />
                  <RC.Tooltip content={({active,payload}) => active && payload?.length ? (
                    <div className="bg-bg-2 border border-line-1 px-2 py-1 mono text-[11px]">
                      <div className="text-ink-0">{payload[0].payload.ratio.toFixed(5)}</div>
                      <div className="text-ink-3">base {payload[0].payload.baseline.toFixed(5)}</div>
                    </div>
                  ) : null}/>
                  <RC.Line type="monotone" dataKey="ratio" stroke="#7aaed8" strokeWidth={1.25} dot={false} isAnimationActive={false}/>
                  <RC.Line type="monotone" dataKey="baseline" stroke="#7d8896" strokeDasharray="3 3" strokeWidth={1} dot={false} isAnimationActive={false}/>
                </RC.LineChart>
              </RC.ResponsiveContainer>
            </div>
          </div>

          {/* numeric breakdown */}
          <div className="grid grid-cols-2 gap-px bg-line-0">
            <KV label="current ratio" value={fmtNum(pair.current, 5)} />
            <KV label="baseline (ema)" value={fmtNum(pair.baseline, 5)} />
            <KV label="raw score" value={fmtPct(pair.raw_score, 3)} tone={pair.raw_score >= 0 ? 'pos' : 'neg'} />
            <KV label="effective score" value={fmtPct(pair.eff_score, 3)} tone={pair.eff_score >= 0 ? 'pos' : 'neg'} />
          </div>

          <div className="bg-bg-2 border border-line-0">
            <div className="px-3 py-2 border-b border-line-0 text-[10px] uppercase tracking-[0.14em] text-ink-3 mono">parameters</div>
            <div className="divide-y divide-line-0">
              <KV2 k="margin" v={fmtPct(pair.margin, 2)} />
              <KV2 k="multiplier" v={pair.multiplier.toFixed(2) + '×'} />
              <KV2 k="ema_alpha" v={pair.ema_alpha.toFixed(3)} />
              <KV2 k="last decision" v={pair.last_decision} />
            </div>
          </div>
        </div>
      </aside>
    </>
  );
}

function KV({ label, value, tone }) {
  return (
    <div className="bg-bg-1 px-3 py-2">
      <div className="text-[9.5px] uppercase tracking-[0.14em] text-ink-3 mono">{label}</div>
      <div className={`mono text-[14px] num mt-0.5 ${tone === 'pos' ? 'text-pos-0' : tone === 'neg' ? 'text-neg-0' : 'text-ink-0'}`}>{value}</div>
    </div>
  );
}
function KV2({ k, v }) {
  return (
    <div className="px-3 py-1.5 flex items-center justify-between mono text-[11.5px]">
      <span className="text-ink-3">{k}</span>
      <span className="text-ink-1">{v}</span>
    </div>
  );
}

window.PagePairs = PagePairs;
