/* AI Scan — ad-hoc chart analysis for any ticker */

const _adhocHooks = React;
const _useState   = _adhocHooks.useState;
const _useEffect  = _adhocHooks.useEffect;
const _useRef     = _adhocHooks.useRef;
const _useCallback = _adhocHooks.useCallback;

// ── Ticker catalogue ─────────────────────────────────────────────────────────

const CRYPTO_LIST = [
  { sym: 'BTC',  name: 'Bitcoin',          exchange: 'BINANCE', tvSym: 'BTCUSDT.P' },
  { sym: 'ETH',  name: 'Ethereum',         exchange: 'BINANCE', tvSym: 'ETHUSDT.P' },
  { sym: 'SOL',  name: 'Solana',           exchange: 'BINANCE', tvSym: 'SOLUSDT.P' },
  { sym: 'BNB',  name: 'BNB',              exchange: 'BINANCE', tvSym: 'BNBUSDT.P' },
  { sym: 'XRP',  name: 'XRP',              exchange: 'BINANCE', tvSym: 'XRPUSDT.P' },
  { sym: 'ADA',  name: 'Cardano',          exchange: 'BINANCE', tvSym: 'ADAUSDT.P' },
  { sym: 'AVAX', name: 'Avalanche',        exchange: 'BINANCE', tvSym: 'AVAXUSDT.P' },
  { sym: 'DOT',  name: 'Polkadot',         exchange: 'BINANCE', tvSym: 'DOTUSDT.P' },
  { sym: 'LINK', name: 'Chainlink',        exchange: 'BINANCE', tvSym: 'LINKUSDT.P' },
  { sym: 'ATOM', name: 'Cosmos',           exchange: 'BINANCE', tvSym: 'ATOMUSDT.P' },
  { sym: 'NEAR', name: 'NEAR Protocol',    exchange: 'BINANCE', tvSym: 'NEARUSDT.P' },
  { sym: 'APT',  name: 'Aptos',            exchange: 'BINANCE', tvSym: 'APTUSDT.P' },
  { sym: 'ARB',  name: 'Arbitrum',         exchange: 'BINANCE', tvSym: 'ARBUSDT.P' },
  { sym: 'OP',   name: 'Optimism',         exchange: 'BINANCE', tvSym: 'OPUSDT.P' },
  { sym: 'INJ',  name: 'Injective',        exchange: 'BINANCE', tvSym: 'INJUSDT.P' },
  { sym: 'SUI',  name: 'Sui',              exchange: 'BINANCE', tvSym: 'SUIUSDT.P' },
  { sym: 'TIA',  name: 'Celestia',         exchange: 'BINANCE', tvSym: 'TIAUSDT.P' },
  { sym: 'DOGE', name: 'Dogecoin',         exchange: 'BINANCE', tvSym: 'DOGEUSDT.P' },
  { sym: 'PEPE', name: 'Pepe',             exchange: 'BINANCE', tvSym: 'PEPEUSDT.P' },
  { sym: 'WIF',  name: 'dogwifhat',        exchange: 'BINANCE', tvSym: 'WIFUSDT.P' },
  { sym: 'JUP',  name: 'Jupiter',          exchange: 'BINANCE', tvSym: 'JUPUSDT.P' },
  { sym: 'LTC',  name: 'Litecoin',         exchange: 'BINANCE', tvSym: 'LTCUSDT.P' },
  { sym: 'BCH',  name: 'Bitcoin Cash',     exchange: 'BINANCE', tvSym: 'BCHUSDT.P' },
  { sym: 'XLM',  name: 'Stellar',          exchange: 'BINANCE', tvSym: 'XLMUSDT.P' },
  { sym: 'HBAR', name: 'Hedera',           exchange: 'BINANCE', tvSym: 'HBARUSDT.P' },
  { sym: 'FIL',  name: 'Filecoin',         exchange: 'BINANCE', tvSym: 'FILUSDT.P' },
  { sym: 'AAVE', name: 'Aave',             exchange: 'BINANCE', tvSym: 'AAVEUSDT.P' },
  { sym: 'UNI',  name: 'Uniswap',          exchange: 'BINANCE', tvSym: 'UNIUSDT.P' },
  { sym: 'CRV',  name: 'Curve',            exchange: 'BINANCE', tvSym: 'CRVUSDT.P' },
  { sym: 'MATIC',name: 'Polygon',          exchange: 'BINANCE', tvSym: 'MATICUSDT.P' },
];

const STOCK_LIST = [
  { sym: 'AAPL',  name: 'Apple',           exchange: 'NASDAQ', tvSym: 'AAPL' },
  { sym: 'MSFT',  name: 'Microsoft',       exchange: 'NASDAQ', tvSym: 'MSFT' },
  { sym: 'NVDA',  name: 'NVIDIA',          exchange: 'NASDAQ', tvSym: 'NVDA' },
  { sym: 'AMZN',  name: 'Amazon',          exchange: 'NASDAQ', tvSym: 'AMZN' },
  { sym: 'GOOGL', name: 'Alphabet',        exchange: 'NASDAQ', tvSym: 'GOOGL' },
  { sym: 'META',  name: 'Meta',            exchange: 'NASDAQ', tvSym: 'META' },
  { sym: 'TSLA',  name: 'Tesla',           exchange: 'NASDAQ', tvSym: 'TSLA' },
  { sym: 'NFLX',  name: 'Netflix',         exchange: 'NASDAQ', tvSym: 'NFLX' },
  { sym: 'AMD',   name: 'AMD',             exchange: 'NASDAQ', tvSym: 'AMD' },
  { sym: 'INTC',  name: 'Intel',           exchange: 'NASDAQ', tvSym: 'INTC' },
  { sym: 'JPM',   name: 'JPMorgan Chase',  exchange: 'NYSE',   tvSym: 'JPM' },
  { sym: 'GS',    name: 'Goldman Sachs',   exchange: 'NYSE',   tvSym: 'GS' },
  { sym: 'BAC',   name: 'Bank of America', exchange: 'NYSE',   tvSym: 'BAC' },
  { sym: 'JNJ',   name: 'Johnson & Johnson', exchange: 'NYSE', tvSym: 'JNJ' },
  { sym: 'UNH',   name: 'UnitedHealth',    exchange: 'NYSE',   tvSym: 'UNH' },
  { sym: 'XOM',   name: 'ExxonMobil',      exchange: 'NYSE',   tvSym: 'XOM' },
  { sym: 'CVX',   name: 'Chevron',         exchange: 'NYSE',   tvSym: 'CVX' },
  { sym: 'COST',  name: 'Costco',          exchange: 'NASDAQ', tvSym: 'COST' },
  { sym: 'WMT',   name: 'Walmart',         exchange: 'NYSE',   tvSym: 'WMT' },
  { sym: 'HD',    name: 'Home Depot',      exchange: 'NYSE',   tvSym: 'HD' },
  { sym: 'V',     name: 'Visa',            exchange: 'NYSE',   tvSym: 'V' },
  { sym: 'MA',    name: 'Mastercard',      exchange: 'NYSE',   tvSym: 'MA' },
  { sym: 'COIN',  name: 'Coinbase',        exchange: 'NASDAQ', tvSym: 'COIN' },
  { sym: 'MSTR',  name: 'MicroStrategy',   exchange: 'NASDAQ', tvSym: 'MSTR' },
  { sym: 'PLTR',  name: 'Palantir',        exchange: 'NYSE',   tvSym: 'PLTR' },
  { sym: 'UBER',  name: 'Uber',            exchange: 'NYSE',   tvSym: 'UBER' },
  { sym: 'SOFI',  name: 'SoFi Technologies', exchange: 'NASDAQ', tvSym: 'SOFI' },
  { sym: 'SPY',   name: 'S&P 500 ETF',     exchange: 'AMEX',   tvSym: 'SPY' },
  { sym: 'QQQ',   name: 'Nasdaq ETF',      exchange: 'NASDAQ', tvSym: 'QQQ' },
  { sym: 'GLD',   name: 'Gold ETF',        exchange: 'AMEX',   tvSym: 'GLD' },
];

const ALL_TICKERS = [
  ...CRYPTO_LIST.map(t => ({ ...t, type: 'Crypto' })),
  ...STOCK_LIST.map(t  => ({ ...t, type: 'Stock'  })),
];

// ── Term → TradingView interval ──────────────────────────────────────────────

const TERMS = [
  { id: 'scalp',    label: 'Scalp',    sub: '5m chart',  interval: '5'   },
  { id: 'day',      label: 'Day',      sub: '1H chart',  interval: '60'  },
  { id: 'swing',    label: 'Swing',    sub: '4H chart',  interval: '240' },
  { id: 'position', label: 'Position', sub: 'Daily chart', interval: 'D' },
  { id: 'macro',    label: 'Macro',    sub: 'Weekly chart', interval: 'W' },
];

// ── Helpers ──────────────────────────────────────────────────────────────────

const ADHOC_COOLDOWN_MS = 4 * 60 * 60 * 1000;

function timeAgo(iso) {
  if (!iso) return '—';
  const ms = Date.now() - new Date(iso.endsWith('Z') ? iso : iso + 'Z').getTime();
  if (ms < 60000) return 'just now';
  if (ms < 3600000) return Math.floor(ms / 60000) + 'm ago';
  if (ms < 86400000) return Math.floor(ms / 3600000) + 'h ago';
  return Math.floor(ms / 86400000) + 'd ago';
}

function cooldownLeft(iso) {
  if (!iso) return 0;
  const elapsed = Date.now() - new Date(iso.endsWith('Z') ? iso : iso + 'Z').getTime();
  return Math.max(0, ADHOC_COOLDOWN_MS - elapsed);
}

function fmtCooldown(ms) {
  if (ms <= 0) return '';
  const h = Math.floor(ms / 3600000);
  const m = Math.floor((ms % 3600000) / 60000);
  return h > 0 ? `${h}h ${m}m` : `${m}m`;
}

function biasColor(bias) {
  if (!bias) return 'var(--text-3)';
  const b = bias.toLowerCase();
  if (b === 'bullish' || b === 'bull') return 'var(--bull)';
  if (b === 'bearish' || b === 'bear') return 'var(--bear)';
  return 'var(--text-3)';
}

function biasBg(bias) {
  if (!bias) return 'var(--bg-card)';
  const b = bias.toLowerCase();
  if (b === 'bullish' || b === 'bull') return 'var(--bull-bg)';
  if (b === 'bearish' || b === 'bear') return 'var(--bear-bg)';
  return 'var(--bg-card)';
}

function biasLabel(bias) {
  if (!bias) return '—';
  const b = bias.toLowerCase();
  if (b === 'bullish' || b === 'bull') return 'BULLISH';
  if (b === 'bearish' || b === 'bear') return 'BEARISH';
  return bias.toUpperCase();
}

// ── Autocomplete Input ────────────────────────────────────────────────────────

function AdhocTickerInput({ value, onChange, assetType }) {
  const [query,    setQuery]    = _useState(value || '');
  const [open,     setOpen]     = _useState(false);
  const [results,  setResults]  = _useState([]);
  const [searching,setSearching]= _useState(false);
  const wrapRef  = _useRef(null);
  const timerRef = _useRef(null);

  // Instant local suggestions for very short queries, API search otherwise
  _useEffect(() => {
    const q = query.trim();
    if (!q) { setResults([]); setOpen(false); return; }

    // Always show local matches immediately
    const local = ALL_TICKERS.filter(t => {
      if (assetType !== 'All' && t.type !== assetType) return false;
      const ql = q.toLowerCase();
      return t.sym.toLowerCase().includes(ql) || t.name.toLowerCase().includes(ql);
    }).slice(0, 6);
    setResults(local);
    setOpen(true);

    // Debounce API search
    clearTimeout(timerRef.current);
    timerRef.current = setTimeout(async () => {
      setSearching(true);
      try {
        const r = await fetch(`/api/ticker-search?q=${encodeURIComponent(q)}`);
        const json = await r.json();
        if (json.ok && Array.isArray(json.data) && json.data.length > 0) {
          const apiResults = json.data.filter(t => assetType === 'All' || t.type === assetType);
          // Merge: API results first, deduplicated against local
          const localSyms = new Set(local.map(t => t.sym + t.exchange));
          const merged = [
            ...apiResults,
            ...local.filter(t => !apiResults.some(a => a.sym === t.sym && a.exchange === t.exchange)),
          ].slice(0, 10);
          setResults(merged);
          setOpen(true);
        }
      } catch (_) {}
      setSearching(false);
    }, 320);

    return () => clearTimeout(timerRef.current);
  }, [query, assetType]);

  // Close dropdown on outside click
  _useEffect(() => {
    const handler = e => { if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, []);

  const select = t => {
    setQuery(t.sym);
    setOpen(false);
    onChange(t);
  };

  return (
    <div ref={wrapRef} style={{ position: 'relative', flex: 1 }}>
      <input
        value={query}
        onChange={e => { setQuery(e.target.value); onChange(null); }}
        onFocus={() => query.trim() && setOpen(true)}
        placeholder="Any ticker or name — BP, SPCX, Solana, gold…"
        style={{
          width: '100%', boxSizing: 'border-box',
          background: 'var(--bg-card)', border: '1px solid var(--border-soft)',
          color: 'var(--text)', borderRadius: 7, padding: '9px 12px',
          fontSize: 13, fontFamily: 'var(--font-sans)', outline: 'none',
        }}
      />
      {searching && (
        <span style={{ position: 'absolute', right: 10, top: '50%', transform: 'translateY(-50%)', fontSize: 10, color: 'var(--text-4)' }}>searching…</span>
      )}
      {open && results.length > 0 && (
        <div style={{
          position: 'absolute', top: '100%', left: 0, right: 0, zIndex: 100,
          background: 'var(--bg-app)', border: '1px solid var(--border-soft)',
          borderRadius: 7, marginTop: 4, overflow: 'hidden',
          boxShadow: '0 8px 24px rgba(0,0,0,0.4)',
        }}>
          {results.map((t, i) => (
            <button key={i} onMouseDown={() => select(t)} style={{
              width: '100%', display: 'flex', alignItems: 'center', gap: 10,
              padding: '8px 12px', background: 'transparent', border: 'none',
              color: 'var(--text)', cursor: 'pointer', textAlign: 'left',
              borderBottom: '1px solid var(--border-soft)',
            }}
              onMouseEnter={e => e.currentTarget.style.background = 'var(--bg-card)'}
              onMouseLeave={e => e.currentTarget.style.background = 'transparent'}
            >
              <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--gold)', minWidth: 52 }}>{t.sym}</span>
              <span style={{ fontSize: 12, color: 'var(--text-2)', flex: 1 }}>{t.name}</span>
              <span style={{ fontSize: 10, color: 'var(--text-4)', fontFamily: 'var(--font-mono)' }}>{t.exchange}</span>
              <span style={{
                fontSize: 9.5, padding: '1px 6px', borderRadius: 4, marginLeft: 4,
                background: t.type === 'Crypto' ? 'rgba(245,176,65,0.15)' : 'rgba(100,149,237,0.15)',
                color: t.type === 'Crypto' ? 'var(--gold)' : 'var(--info)',
                fontFamily: 'var(--font-mono)', letterSpacing: '0.04em',
              }}>{t.type}</span>
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

// ── Run form bar ─────────────────────────────────────────────────────────────

function AdhocForm({ onCreated, user }) {
  const [assetType,   setAssetType]   = _useState('All');
  const [ticker,      setTicker]      = _useState(null);
  const [term,        setTerm]        = _useState('swing');
  const [running,     setRunning]     = _useState(false);
  const [err,         setErr]         = _useState('');

  const canRun = ticker && !running && !!user;

  async function handleRun() {
    if (!canRun) return;
    setRunning(true);
    setErr('');
    const t = TERMS.find(t => t.id === term) || TERMS[2];
    try {
      const res = await fetch('/api/ai/adhoc', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          ticker:    ticker.sym,
          exchange:  ticker.exchange,
          tv_symbol: ticker.tvSym,
          term:      t.id,
          interval:  t.interval,
        }),
      });
      const json = await res.json();
      if (!json.ok) throw new Error(json.error || 'Failed');
      onCreated(json.id);
    } catch (e) {
      setErr(e.message);
    } finally {
      setRunning(false);
    }
  }

  return (
    <div style={{
      background: 'var(--bg-card)', border: '1px solid var(--border-soft)',
      borderRadius: 10, padding: '16px 18px', marginBottom: 18,
    }}>
      <div style={{ fontSize: 11.5, color: 'var(--text-3)', marginBottom: 12, letterSpacing: '0.06em', textTransform: 'uppercase' }}>New Analysis</div>

      {/* Asset type toggle */}
      <div style={{ display: 'flex', gap: 6, marginBottom: 12 }}>
        {['All', 'Crypto', 'Stock'].map(a => (
          <button key={a} onClick={() => setAssetType(a)} style={{
            padding: '4px 12px', borderRadius: 5, border: '1px solid var(--border-soft)',
            background: assetType === a ? 'var(--gold)' : 'var(--bg-elev)',
            color: assetType === a ? 'var(--bg-base)' : 'var(--text-3)',
            fontSize: 11.5, fontWeight: assetType === a ? 600 : 400,
            cursor: 'pointer', fontFamily: 'var(--font-sans)',
          }}>{a}</button>
        ))}
      </div>

      {/* Ticker + run button row */}
      <div style={{ display: 'flex', gap: 10, alignItems: 'flex-start', marginBottom: 12 }}>
        <AdhocTickerInput value="" onChange={setTicker} assetType={assetType} />
        {user ? (
          <button onClick={handleRun} disabled={!canRun} style={{
            display: 'flex', alignItems: 'center', gap: 6,
            padding: '9px 16px', borderRadius: 7,
            background: canRun ? 'var(--gold)' : 'var(--bg-elev)',
            border: 'none', color: canRun ? 'var(--bg-base)' : 'var(--text-4)',
            fontSize: 12.5, fontWeight: 600, cursor: canRun ? 'pointer' : 'not-allowed',
            fontFamily: 'var(--font-sans)', whiteSpace: 'nowrap', flexShrink: 0,
            opacity: running ? 0.6 : 1,
          }}>
            {running ? 'Running…' : 'Run Analysis'}
          </button>
        ) : (
          // Browsing (and reading past results) stays open to everyone — running a
          // new analysis spends AI credits, so it needs a signed-in account.
          <InlineSignIn label="Sign in to run an analysis" />
        )}
      </div>

      {/* Term pills */}
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4 }}>
        {TERMS.map(t => (
          <button key={t.id} onClick={() => setTerm(t.id)} style={{
            padding: '5px 8px', borderRadius: 6, border: '1px solid var(--border-soft)',
            background: term === t.id ? 'var(--bg-elev)' : 'transparent',
            color: term === t.id ? 'var(--text)' : 'var(--text-3)',
            fontSize: 11, cursor: 'pointer', fontFamily: 'var(--font-sans)',
            boxShadow: term === t.id ? '0 0 0 1px var(--gold)' : 'none',
          }}>
            {t.label}
            <span style={{ display: 'block', fontSize: 9.5, color: 'var(--text-4)', marginTop: 1 }}>{t.sub}</span>
          </button>
        ))}
      </div>

      {err && <div style={{ marginTop: 10, fontSize: 11.5, color: 'var(--bear)' }}>{err}</div>}
    </div>
  );
}

// ── History list ─────────────────────────────────────────────────────────────

function AdhocHistoryItem({ item, active, onClick, onRerun, onDelete, user }) {
  const [cooldown,    setCooldown]    = _useState(() => cooldownLeft(item.updated_at || item.created_at));
  const [confirming,  setConfirming]  = _useState(false);
  _useEffect(() => {
    const id = setInterval(() => setCooldown(cooldownLeft(item.updated_at || item.created_at)), 10000);
    return () => clearInterval(id);
  }, [item.updated_at, item.created_at]);

  const canRerun = item.status === 'done' || item.status === 'error';
  // Re-run spends AI credits same as a new analysis — signed-out just doesn't get
  // the button state at all rather than a click that would 401.
  const rerunBlocked = cooldown > 0 || !user;

  const statusDot = {
    pending: { color: 'var(--text-4)',  label: 'pending' },
    running: { color: 'var(--gold)',    label: 'running' },
    done:    { color: 'var(--bull)',    label: 'done'    },
    error:   { color: 'var(--bear)',    label: 'error'   },
  }[item.status] || { color: 'var(--text-4)', label: item.status };

  return (
    <div onClick={onClick} style={{
      padding: '10px 14px', borderRadius: 8, cursor: 'pointer',
      background: active ? 'var(--bg-elev)' : 'transparent',
      border: active ? '1px solid var(--border-soft)' : '1px solid transparent',
      marginBottom: 4, transition: 'background 0.1s',
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 3 }}>
        <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, fontWeight: 600, color: 'var(--gold)' }}>{item.ticker}</span>
        <span style={{ fontSize: 10.5, color: 'var(--text-3)', background: 'var(--bg-card)', padding: '1px 6px', borderRadius: 4 }}>{item.term}</span>
        {item.bias && (
          <span style={{
            fontSize: 10, padding: '1px 6px', borderRadius: 4,
            background: biasBg(item.bias), color: biasColor(item.bias),
            fontFamily: 'var(--font-mono)', fontWeight: 700,
            marginLeft: 'auto', flexShrink: 0,
          }}>{biasLabel(item.bias)}</span>
        )}
      </div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
        <span style={{ fontSize: 9.5, color: statusDot.color, display: 'flex', alignItems: 'center', gap: 4 }}>
          <span style={{ width: 5, height: 5, borderRadius: '50%', background: statusDot.color, display: 'inline-block' }} />
          {statusDot.label}
        </span>
        <span style={{ fontSize: 9.5, color: 'var(--text-4)', marginLeft: 'auto' }}>{timeAgo(item.updated_at || item.created_at)}</span>
        {canRerun && (
          <button onClick={e => { e.stopPropagation(); onRerun(item.id); }} disabled={rerunBlocked}
            title={!user ? 'Sign in to re-run' : cooldown > 0 ? `Cooldown: ${fmtCooldown(cooldown)}` : 'Re-run'} style={{
            fontSize: 9.5, padding: '2px 6px', borderRadius: 4,
            background: 'var(--bg-app)', border: '1px solid var(--border-soft)',
            color: rerunBlocked ? 'var(--text-4)' : 'var(--text-2)',
            cursor: rerunBlocked ? 'not-allowed' : 'pointer',
            fontFamily: 'var(--font-sans)',
          }}>{cooldown > 0 ? fmtCooldown(cooldown) : 'Re-run'}</button>
        )}
        {confirming ? (
          <span style={{ display: 'flex', alignItems: 'center', gap: 4, marginLeft: 2 }}>
            <span style={{ fontSize: 9.5, color: 'var(--text-3)' }}>Delete?</span>
            <button onClick={e => { e.stopPropagation(); onDelete(item.id); }} style={{
              fontSize: 9.5, padding: '2px 7px', borderRadius: 4,
              background: 'var(--bear)', border: 'none',
              color: '#fff', cursor: 'pointer', fontFamily: 'var(--font-sans)', fontWeight: 600,
            }}>Yes</button>
            <button onClick={e => { e.stopPropagation(); setConfirming(false); }} style={{
              fontSize: 9.5, padding: '2px 7px', borderRadius: 4,
              background: 'var(--bg-app)', border: '1px solid var(--border-soft)',
              color: 'var(--text-2)', cursor: 'pointer', fontFamily: 'var(--font-sans)',
            }}>No</button>
          </span>
        ) : (
          <button onClick={e => { e.stopPropagation(); setConfirming(true); }} title="Delete" style={{
            fontSize: 11, padding: '2px 5px', borderRadius: 4,
            background: 'transparent', border: '1px solid transparent',
            color: 'var(--text-4)', cursor: 'pointer', lineHeight: 1,
          }}
            onMouseEnter={e => { e.currentTarget.style.color = 'var(--bear)'; e.currentTarget.style.borderColor = 'var(--bear)'; }}
            onMouseLeave={e => { e.currentTarget.style.color = 'var(--text-4)'; e.currentTarget.style.borderColor = 'transparent'; }}
          >✕</button>
        )}
      </div>
    </div>
  );
}

// ── Result panel ─────────────────────────────────────────────────────────────

function AdhocHistoryPanel({ item, onClose, onSelect }) {
  const [rows, setRows] = _useState([]);
  const [loading, setLoading] = _useState(true);

  _useEffect(() => {
    if (!item) return;
    setLoading(true);
    fetch(`/api/ai/adhoc/history?ticker=${encodeURIComponent(item.ticker)}&term=${encodeURIComponent(item.term)}&interval=${encodeURIComponent(item.interval)}`)
      .then(r => r.json())
      .then(j => { if (j.ok) setRows(j.data || []); })
      .catch(() => {})
      .finally(() => setLoading(false));
  }, [item?.ticker, item?.term, item?.interval]);

  const trapColor = tp => tp >= 0.8 ? 'var(--bear)' : tp >= 0.6 ? '#f59e0b' : tp >= 0.35 ? 'var(--gold)' : 'var(--bull)';

  return (
    <div style={{
      position: 'fixed', inset: 0, zIndex: 1000,
      background: 'oklch(0 0 0 / 0.55)', display: 'flex', alignItems: 'center', justifyContent: 'center',
    }} onClick={onClose}>
      <div style={{
        background: 'var(--bg-card)', border: '1px solid var(--border-soft)',
        borderRadius: 12, width: '90vw', maxWidth: 820, maxHeight: '80vh',
        display: 'flex', flexDirection: 'column', overflow: 'hidden',
      }} onClick={e => e.stopPropagation()}>
        <div style={{ display: 'flex', alignItems: 'center', padding: '14px 18px', borderBottom: '1px solid var(--border-soft)' }}>
          <span style={{ fontWeight: 600, fontSize: 13 }}>
            {item?.ticker} · {item?.term} · {item?.interval} — run history
          </span>
          <button onClick={onClose} style={{
            marginLeft: 'auto', background: 'transparent', border: 'none',
            color: 'var(--text-4)', cursor: 'pointer', fontSize: 18, lineHeight: 1,
          }}>×</button>
        </div>
        <div style={{ overflowY: 'auto', flex: 1 }}>
          {loading && <div style={{ padding: 30, textAlign: 'center', color: 'var(--text-4)', fontSize: 12 }}>Loading…</div>}
          {!loading && rows.length === 0 && <div style={{ padding: 30, textAlign: 'center', color: 'var(--text-4)', fontSize: 12 }}>No history found</div>}
          {!loading && rows.length > 0 && (
            <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 11.5 }}>
              <thead>
                <tr style={{ color: 'var(--text-4)', fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.06em', borderBottom: '1px solid var(--border-soft)' }}>
                  <th style={{ padding: '8px 18px', textAlign: 'left' }}>Date / Time</th>
                  <th style={{ padding: '8px 12px', textAlign: 'left' }}>Bias</th>
                  <th style={{ padding: '8px 12px', textAlign: 'left' }}>Confidence</th>
                  <th style={{ padding: '8px 12px', textAlign: 'left' }}>Trap %</th>
                  <th style={{ padding: '8px 18px', textAlign: 'left', maxWidth: 260 }}>Summary</th>
                </tr>
              </thead>
              <tbody>
                {rows.map(r => (
                  <tr key={r.id} onClick={() => onSelect(r.id)} style={{
                    borderBottom: '1px solid var(--border-soft)', cursor: 'pointer',
                    transition: 'background 0.1s',
                  }}
                  onMouseEnter={e => e.currentTarget.style.background = 'var(--bg-elev)'}
                  onMouseLeave={e => e.currentTarget.style.background = ''}>
                    <td style={{ padding: '10px 18px', fontFamily: 'var(--font-mono)', color: 'var(--text-3)', whiteSpace: 'nowrap' }}>
                      {(r.created_at || '').replace('T', ' ').replace('Z', '').slice(0, 16)}
                    </td>
                    <td style={{ padding: '10px 12px' }}>
                      <span style={{
                        fontSize: 10, fontWeight: 700, padding: '2px 8px', borderRadius: 4,
                        color: r.bias === 'bullish' ? 'var(--bull)' : r.bias === 'bearish' ? 'var(--bear)' : 'var(--text-3)',
                        background: r.bias === 'bullish' ? 'var(--bull-bg)' : r.bias === 'bearish' ? 'var(--bear-bg)' : 'var(--bg-elev)',
                      }}>{(r.bias || 'neutral').toUpperCase()}</span>
                    </td>
                    <td style={{ padding: '10px 12px', fontFamily: 'var(--font-mono)', color: 'var(--text-2)' }}>
                      {r.confidence != null ? Math.round(r.confidence * 100) + '%' : '—'}
                    </td>
                    <td style={{ padding: '10px 12px', fontFamily: 'var(--font-mono)', fontWeight: 600 }}>
                      {r.trap_probability != null
                        ? <span style={{ color: trapColor(r.trap_probability) }}>{Math.round(r.trap_probability * 100)}%</span>
                        : <span style={{ color: 'var(--text-4)' }}>—</span>}
                    </td>
                    <td style={{ padding: '10px 18px', color: 'var(--text-3)', maxWidth: 260, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                      {r.summary || '—'}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          )}
        </div>
      </div>
    </div>
  );
}

function AdhocResult({ item, onShowHistory }) {
  if (!item) {
    return (
      <div style={{ display: 'grid', placeItems: 'center', height: '100%', color: 'var(--text-4)', fontSize: 13 }}>
        Select an analysis from the list to view results
      </div>
    );
  }

  if (item.status === 'pending' || item.status === 'running') {
    return (
      <div style={{ display: 'grid', placeItems: 'center', height: '100%' }}>
        <div style={{ textAlign: 'center' }}>
          <div style={{ fontSize: 13, color: 'var(--text-3)', marginBottom: 8 }}>
            {item.status === 'running' ? 'Analysis in progress…' : 'Queued — starting soon…'}
          </div>
          <div style={{ fontSize: 11, color: 'var(--text-4)' }}>{item.ticker} · {item.term}</div>
          <div style={{ marginTop: 16, display: 'flex', gap: 6, justifyContent: 'center' }}>
            {[0,1,2].map(i => (
              <span key={i} style={{
                width: 6, height: 6, borderRadius: '50%', background: 'var(--gold)',
                animation: `dotBlink 1.2s ${i * 0.2}s infinite ease-in-out`,
                display: 'inline-block',
              }} />
            ))}
          </div>
        </div>
      </div>
    );
  }

  if (item.status === 'error') {
    return (
      <div style={{ padding: 20 }}>
        <div style={{ fontSize: 12.5, color: 'var(--bear)', marginBottom: 8 }}>Analysis failed</div>
        <div style={{ fontSize: 11.5, color: 'var(--text-3)', fontFamily: 'var(--font-mono)' }}>{item.error_msg || 'Unknown error'}</div>
      </div>
    );
  }

  const analysis = item.gemini_json || {};
  const levels   = Array.isArray(item.key_levels_summary) ? item.key_levels_summary : [];
  const imgSrc   = item.annotated_image_url || item.screenshot_url;
  const setups   = Array.isArray(analysis.setups) ? analysis.setups : [];

  const confidence = typeof analysis.confidence === 'number' ? analysis.confidence : item.confidence;

  // Split narrative into Context (PART 1) and Action Plan (PART 2)
  const rawNarrative = (analysis.narrative || analysis.summary || '').trim();
  let narrativeContext = '', narrativeAction = '';
  if (rawNarrative) {
    const p2idx = rawNarrative.search(/PART\s*2/i);
    if (p2idx > 0) {
      narrativeContext = rawNarrative.slice(0, p2idx).replace(/PART\s*1[^\n]*\n?/i, '').trim();
      narrativeAction  = rawNarrative.slice(p2idx).replace(/PART\s*2[^\n]*\n?/i, '').trim();
    } else {
      const paras = rawNarrative.split(/\n\n+/).filter(s => s.trim());
      if (paras.length > 1) {
        narrativeAction  = paras[paras.length - 1];
        narrativeContext = paras.slice(0, -1).join('\n\n');
      } else {
        narrativeContext = rawNarrative;
      }
    }
  }

  const sLabel = { fontSize: 9.5, color: 'var(--text-4)', letterSpacing: '0.12em', textTransform: 'uppercase', marginBottom: 10, fontWeight: 500 };
  const sBody  = { fontSize: 12.5, color: 'var(--text-2)', lineHeight: 1.75, whiteSpace: 'pre-line' };

  function fmtPrice(v) {
    if (v == null) return '—';
    const n = parseFloat(v);
    return isNaN(n) ? String(v) : n.toLocaleString(undefined, { maximumFractionDigits: 2 });
  }

  return (
    <div style={{ overflowY: 'auto', height: '100%' }}>
      {/* Header row */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 16, flexWrap: 'wrap' }}>
        <div>
          <div style={{ fontSize: 20, fontWeight: 600, letterSpacing: '-0.01em' }}>{item.ticker}</div>
          <div style={{ fontSize: 11.5, color: 'var(--text-3)', marginTop: 1 }}>{item.exchange} · {item.term} · {timeAgo(item.updated_at || item.created_at)}</div>
        </div>
        <button onClick={() => onShowHistory && onShowHistory(item)} style={{
          marginLeft: 8, fontSize: 10.5, padding: '4px 10px', borderRadius: 6,
          background: 'var(--bg-elev)', border: '1px solid var(--border-soft)',
          color: 'var(--text-3)', cursor: 'pointer', fontFamily: 'var(--font-sans)',
        }}>History</button>
        {item.bias && (
          <div style={{
            marginLeft: 'auto',
            padding: '8px 16px', borderRadius: 8,
            background: biasBg(item.bias), border: `1px solid ${biasColor(item.bias)}44`,
            textAlign: 'center',
          }}>
            <div style={{ fontSize: 9.5, color: 'var(--text-4)', letterSpacing: '0.1em', textTransform: 'uppercase' }}>Bias</div>
            <div style={{ fontSize: 15, fontWeight: 700, color: biasColor(item.bias), marginTop: 1 }}>{biasLabel(item.bias)}</div>
            {confidence != null && (
              <div style={{ fontSize: 10, color: 'var(--text-3)', marginTop: 2 }}>
                {Math.round(confidence * 100)}% confidence
              </div>
            )}
          </div>
        )}
      </div>

      {/* Chart image */}
      {imgSrc && (
        <div style={{
          borderRadius: 8, overflow: 'hidden', marginBottom: 16,
          border: '1px solid var(--border-soft)',
        }}>
          <img src={imgSrc} alt={`${item.ticker} chart`} style={{ width: '100%', display: 'block' }} />
        </div>
      )}

      {/* ── Context ──────────────────────────────────────────── */}
      {narrativeContext && (
        <div style={{ background: 'var(--bg-card)', border: '1px solid var(--border-soft)', borderRadius: 8, padding: '14px 16px', marginBottom: 12 }}>
          <div style={sLabel}>What I see</div>
          <div style={sBody}>{narrativeContext}</div>
        </div>
      )}

      {/* ── Smart Money Perspective ───────────────────────────── */}
      {(analysis.trap_probability != null || analysis.smart_money_thesis) && (() => {
        const tp    = analysis.trap_probability ?? 0;
        const pct   = Math.round(tp * 100);
        const color = tp >= 0.8 ? 'var(--bear)' : tp >= 0.6 ? '#f59e0b' : tp >= 0.35 ? 'var(--gold)' : 'var(--bull)';
        const label = tp >= 0.8 ? 'Near-certain trap' : tp >= 0.6 ? 'High trap risk' : tp >= 0.35 ? 'Moderate trap risk' : 'Low trap risk';
        return (
          <div style={{ background: 'var(--bg-card)', border: '1px solid var(--border-soft)', borderLeft: `3px solid ${color}`, borderRadius: 8, padding: '14px 16px', marginBottom: 12 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 10 }}>
              <div style={sLabel}>Smart money perspective</div>
              <div style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: 8 }}>
                <div style={{ width: 70, height: 4, borderRadius: 2, background: 'var(--bg-elev)', overflow: 'hidden' }}>
                  <div style={{ width: pct + '%', height: '100%', background: color, borderRadius: 2 }} />
                </div>
                <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11.5, color, fontWeight: 700 }}>{pct}%</span>
                <span style={{ fontSize: 10, color: 'var(--text-4)' }}>{label}</span>
              </div>
            </div>
            {analysis.smart_money_thesis && (
              <div style={{ fontSize: 12.5, color: 'var(--text-2)', lineHeight: 1.65 }}>{analysis.smart_money_thesis}</div>
            )}
          </div>
        );
      })()}

      {/* ── Trade Setups ─────────────────────────────────────── */}
      {setups.length > 0 && (
        <div style={{ background: 'var(--bg-card)', border: '1px solid var(--border-soft)', borderRadius: 8, padding: '14px 16px', marginBottom: 12 }}>
          <div style={sLabel}>Trade setup{setups.length > 1 ? 's' : ''}</div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
            {setups.map((s, i) => {
              const isLong = String(s.direction).toLowerCase() === 'long';
              const dir    = isLong ? 'LONG' : 'SHORT';
              const dColor = isLong ? 'var(--bull)' : 'var(--bear)';
              const dBg    = isLong ? 'var(--bull-bg)' : 'var(--bear-bg)';
              return (
                <div key={i} style={{ borderRadius: 6, border: '1px solid var(--border-soft)', overflow: 'hidden' }}>
                  {/* Direction header */}
                  <div style={{ background: dBg, padding: '7px 12px', display: 'flex', alignItems: 'center', gap: 8 }}>
                    <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, fontWeight: 700, color: dColor }}>{dir}</span>
                    {s.rr != null && (
                      <span style={{ marginLeft: 'auto', fontFamily: 'var(--font-mono)', fontSize: 10.5, color: 'var(--text-3)' }}>{parseFloat(s.rr).toFixed(1)}R</span>
                    )}
                  </div>
                  {/* Numbers grid */}
                  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', borderBottom: '1px solid var(--border-soft)' }}>
                    {[
                      { label: 'Entry zone', value: `${fmtPrice(s.entry_zone_low)} – ${fmtPrice(s.entry_zone_high)}`, color: 'var(--text)' },
                      { label: 'Stop loss',  value: fmtPrice(s.sl),  color: 'var(--bear)' },
                      { label: 'Take profit',value: fmtPrice(s.tp),  color: 'var(--bull)' },
                    ].map((c, j) => (
                      <div key={j} style={{ padding: '10px 12px', borderRight: j < 2 ? '1px solid var(--border-soft)' : 'none' }}>
                        <div style={{ fontSize: 9, color: 'var(--text-4)', letterSpacing: '0.1em', textTransform: 'uppercase', marginBottom: 4 }}>{c.label}</div>
                        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12.5, color: c.color, fontWeight: 600 }}>{c.value}</div>
                      </div>
                    ))}
                  </div>
                  {/* Confluence chips */}
                  {Array.isArray(s.confluence_factors) && s.confluence_factors.length > 0 && (
                    <div style={{ padding: '8px 12px', display: 'flex', flexWrap: 'wrap', gap: 5, borderBottom: s.reasoning ? '1px solid var(--border-soft)' : 'none' }}>
                      {s.confluence_factors.map((f, k) => (
                        <span key={k} style={{ fontSize: 10, padding: '2px 7px', borderRadius: 4, background: 'var(--bg-elev)', color: 'var(--text-3)' }}>{f}</span>
                      ))}
                    </div>
                  )}
                  {/* Reasoning */}
                  {s.reasoning && (
                    <div style={{ padding: '9px 12px', fontSize: 11.5, color: 'var(--text-3)', lineHeight: 1.6 }}>{s.reasoning}</div>
                  )}
                </div>
              );
            })}
          </div>
        </div>
      )}

      {/* ── Action Plan ──────────────────────────────────────── */}
      {narrativeAction && (
        <div style={{ background: 'var(--bg-card)', border: '1px solid var(--border-soft)', borderLeft: '3px solid var(--gold)', borderRadius: 8, padding: '14px 16px', marginBottom: 12 }}>
          <div style={sLabel}>My next move</div>
          <div style={{ ...sBody, color: 'var(--text)', fontStyle: 'italic' }}>{narrativeAction}</div>
        </div>
      )}

      {/* ── Key Levels ───────────────────────────────────────── */}
      {levels.length > 0 && (
        <div style={{ background: 'var(--bg-card)', border: '1px solid var(--border-soft)', borderRadius: 8, padding: '14px 16px', marginBottom: 12 }}>
          <div style={sLabel}>Key levels</div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
            {levels.map((lvl, i) => (
              <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                <span style={{
                  fontSize: 9.5, padding: '2px 7px', borderRadius: 4, fontFamily: 'var(--font-mono)',
                  background: lvl.type === 'resistance' ? 'var(--bear-bg)' : lvl.type === 'support' ? 'var(--bull-bg)' : 'var(--bg-elev)',
                  color: lvl.type === 'resistance' ? 'var(--bear)' : lvl.type === 'support' ? 'var(--bull)' : 'var(--text-3)',
                  minWidth: 64, textAlign: 'center', flexShrink: 0,
                }}>{lvl.type || 'level'}</span>
                <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text)' }}>{lvl.price != null ? lvl.price.toLocaleString() : '—'}</span>
                {lvl.note && <span style={{ fontSize: 11, color: 'var(--text-3)' }}>{lvl.note}</span>}
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

// ── Main section ─────────────────────────────────────────────────────────────

function W_AdhocSection({ user }) {
  const [items,       setItems]       = _useState([]);
  const [selected,    setSelected]    = _useState(null);
  const [detail,      setDetail]      = _useState(null);
  const [historyFor,  setHistoryFor]  = _useState(null);
  const pollRef = _useRef(null);

  const load = _useCallback(async () => {
    try {
      const res  = await fetch('/api/ai/adhoc');
      const json = await res.json();
      if (json.ok) setItems(json.data || []);
    } catch (_) {}
  }, []);

  // Load on mount + poll every 8s
  _useEffect(() => {
    load();
    pollRef.current = setInterval(load, 8000);
    return () => clearInterval(pollRef.current);
  }, [load]);

  // Keep detail in sync with items (status may change while running)
  _useEffect(() => {
    if (selected == null) return;
    const found = items.find(i => i.id === selected);
    if (found) setDetail(found);
  }, [items, selected]);

  const selectItem = async (id) => {
    setSelected(id);
    const found = items.find(i => i.id === id);
    if (found) { setDetail(found); return; }
    try {
      const res  = await fetch(`/api/ai/adhoc/${id}`);
      const json = await res.json();
      if (json.ok) setDetail(json.data);
    } catch (_) {}
  };

  const handleCreated = (id) => {
    load();
    selectItem(id);
  };

  const handleRerun = async (id) => {
    if (!user) return; // button is disabled in this state; guard the handler too
    try {
      const res  = await fetch(`/api/ai/adhoc/${id}/rerun`, { method: 'POST' });
      const json = await res.json();
      if (!json.ok) {
        if (json.error === 'cooldown') {
          alert(`Cooldown active — try again in ${fmtCooldown(json.wait_seconds * 1000)}`);
        } else {
          alert(json.error || 'Re-run failed');
        }
        return;
      }
      // Rerun created a new row — select it so the result panel tracks the new analysis
      load();
      selectItem(json.id);
    } catch (_) {}
  };

  const handleDelete = async (id) => {
    try {
      await fetch(`/api/ai/adhoc/${id}`, { method: 'DELETE' });
      setItems(prev => prev.filter(i => i.id !== id));
      if (selected === id) { setSelected(null); setDetail(null); }
    } catch (_) {}
  };

  const handleHistorySelect = async (id) => {
    setHistoryFor(null);
    await selectItem(id);
  };

  return (
    <div className="rg-split" style={{ display: 'grid', gridTemplateColumns: '280px 1fr', gap: 14, alignItems: 'start' }}>
      {/* History modal */}
      {historyFor && (
        <AdhocHistoryPanel
          item={historyFor}
          onClose={() => setHistoryFor(null)}
          onSelect={handleHistorySelect}
        />
      )}

      {/* Left column: form + recent analyses */}
      <div>
        <AdhocForm onCreated={handleCreated} user={user} />

        <div style={{ background: 'var(--bg-card)', border: '1px solid var(--border-soft)', borderRadius: 10, padding: '12px 10px' }}>
          <div style={{ fontSize: 10.5, color: 'var(--text-4)', letterSpacing: '0.1em', textTransform: 'uppercase', padding: '0 4px', marginBottom: 10 }}>
            Recent
            {items.length > 0 && <span style={{ marginLeft: 8, color: 'var(--text-3)' }}>{items.length}</span>}
          </div>
          {items.length === 0 ? (
            <div style={{ fontSize: 11.5, color: 'var(--text-4)', padding: '8px 4px' }}>No analyses yet</div>
          ) : (
            items.map(item => (
              <AdhocHistoryItem
                key={item.id}
                item={item}
                active={item.id === selected}
                onClick={() => selectItem(item.id)}
                onRerun={handleRerun}
                onDelete={handleDelete}
                user={user}
              />
            ))
          )}
        </div>
      </div>

      {/* Right column: result viewer */}
      <div style={{
        background: 'var(--bg-card)', border: '1px solid var(--border-soft)',
        borderRadius: 10, padding: '16px 18px',
        minHeight: 480, maxHeight: '80vh', overflow: 'hidden',
        display: 'flex', flexDirection: 'column',
      }}>
        <AdhocResult item={detail} onShowHistory={setHistoryFor} />
      </div>
    </div>
  );
}
