// tab-futures.jsx — Futures standalone tab
// Data sources: /api/futures (30s interval) | /api/futures-history (60s interval) | /api/ai-observation?tab=futures (once)
// Primary: ES + NQ with term structure | Price history chart | Secondary: YM + CL + GC | COT accordion | Observer note

window.TabFutures = function() {
  const [data,        setData]       = React.useState(null);
  const [loading,     setLoading]    = React.useState(true);
  const [fetchError,  setFetchError] = React.useState(false);
  const [lastUpdated, setLastUpdated]= React.useState(null);
  const [cotOpen,     setCotOpen]    = React.useState(false);
  const [history,     setHistory]    = React.useState([]);
  const [activeAnnotation, setActiveAnnotation] = React.useState(null); // index of tapped marker

  const fetchData = React.useCallback(async () => {
    try {
      const res = await fetch(`${API_BASE}/api/futures`, { headers: API_HEADERS });
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      const json = await res.json();
      setData(json);
      setLastUpdated(new Date());
      setFetchError(false);
      setLoading(false);
    } catch (_err) {
      setFetchError(true);
      setLoading(false);
    }
  }, []);

  React.useEffect(() => {
    fetchData();
    const id = setInterval(fetchData, 30_000);
    return () => clearInterval(id);
  }, [fetchData]);

  const fetchHistory = React.useCallback(async () => {
    try {
      const res = await fetch(`${API_BASE}/api/futures-history`, { headers: API_HEADERS });
      if (!res.ok) return;
      const json = await res.json();
      if (Array.isArray(json)) setHistory(json);
    } catch (_) {}
  }, []);

  React.useEffect(() => {
    fetchHistory();
    const id = setInterval(fetchHistory, 60_000);
    return () => clearInterval(id);
  }, [fetchHistory]);

  const futures = data?.futures        ?? [];
  const term    = data?.term_structure    ?? null;
  const nqTerm  = data?.nq_term_structure ?? null;
  const cot     = data?.cot               ?? null;

  const getF = sym => futures.find(f => f.symbol === sym);

  const updatedStr = lastUpdated
    ? lastUpdated.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', timeZone: 'America/New_York' })
    : '—';
  const stalenessLabel = (fetchError && lastUpdated)
    ? `Last updated ${updatedStr} · refresh failed`
    : `Prices delayed ~10 min · Updated ${updatedStr}`;

  // ── Formatters ────────────────────────────────────────────────────────────────
  function fmtPrice(p) {
    if (p == null) return '—';
    return p.toLocaleString('en-US', { minimumFractionDigits: 0, maximumFractionDigits: 2 });
  }

  function fmtCot(n) {
    if (n == null) return '—';
    const sign = n >= 0 ? '+' : '';
    if (Math.abs(n) >= 1_000_000) return `${sign}${(n / 1_000_000).toFixed(1)}M`;
    if (Math.abs(n) >= 1_000)     return `${sign}${(n / 1_000).toFixed(1)}k`;
    return `${sign}${n}`;
  }

  function cotInterpret(net) {
    if (net == null) return '';
    if (net < -50_000)  return 'Net short — bearish lean';
    if (net < 0)        return 'Slightly short';
    if (net > 50_000)   return 'Net long — bullish lean';
    return 'Near neutral';
  }

  // ── Skeleton ──────────────────────────────────────────────────────────────────
  if (loading) {
    return (
      <div className="space-y-4">
        <div className="flex items-center justify-between">
          <span className="text-[11px] font-bold text-white uppercase tracking-widest">FUTURES</span>
          <div className="skel h-3 w-44 rounded" />
        </div>
        <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
          {[0,1].map(i => (
            <div key={i} className="bg-surface rounded-xl border border-line shadow-card p-4">
              <div className="skel h-4 w-24 mb-3 rounded" />
              <div className="skel h-8 w-32 mb-2 rounded" />
              <div className="skel h-4 w-20 rounded" />
            </div>
          ))}
        </div>
        <div className="grid grid-cols-2 sm:grid-cols-3 gap-2">
          {[0,1,2].map(i => (
            <div key={i} className="bg-cardDeep rounded-lg border border-line/40 p-3">
              <div className="skel h-3 w-10 mb-2 rounded" />
              <div className="skel h-5 w-20 mb-1.5 rounded" />
              <div className="skel h-3 w-14 rounded" />
            </div>
          ))}
        </div>
      </div>
    );
  }

  // Derive a plain-English interpretation from the actual spread value and front price
  function spreadInterpretation(structure, spread, frontPrice) {
    if (!structure || spread == null) return null;
    const pct = frontPrice > 0 ? (Math.abs(spread) / frontPrice * 100) : null;
    if (structure === 'contango') {
      if (pct != null) {
        if (pct > 1.5) return 'Heavy carry — unusual spread, watch for a snap back';
        if (pct > 0.8) return 'Moderate carry premium — within seasonal norms';
        return 'Light contango — near-normal seasonal carry';
      }
      if (Math.abs(spread) > 100) return 'Heavy carry — watch for a snap back';
      if (Math.abs(spread) > 40)  return 'Moderate carry premium';
      return 'Light contango — normal seasonal carry';
    }
    // backwardation
    if (pct != null && pct > 0.5) return 'Strong backwardation — near-term supply premium';
    return 'Mild backwardation — spot demand firm';
  }

  // ── Term structure badge ──────────────────────────────────────────────────────
  function TermBadge({ termData, frontPrice }) {
    if (!termData?.structure) return null;
    const isContango = termData.structure === 'contango';
    const interp = spreadInterpretation(termData.structure, termData.total_spread, frontPrice);
    return (
      <>
        <div className={`flex items-center gap-1.5 mt-2 text-xs ${isContango ? 'text-orange-400' : 'text-ok'}`}>
          <span className="font-bold">{isContango ? '▲' : '▼'}</span>
          <span className="font-semibold">{isContango ? 'Contango' : 'Backwardation'}</span>
          {termData.total_spread != null && (
            <span className="text-tmuted">&mdash; {Math.abs(termData.total_spread).toFixed(0)} pts spread</span>
          )}
        </div>
        {interp && (
          <div className={`mt-1 text-[10px] leading-snug ${isContango ? 'text-orange-300' : 'text-ok'}`}>
            {interp}
          </div>
        )}
      </>
    );
  }

  // ── Primary card — ES / NQ ────────────────────────────────────────────────────
  function PrimaryCard({ sym, name, termData }) {
    const f = getF(sym);
    return (
      <div className="bg-surface rounded-xl border border-line shadow-card p-4">
        <div className="flex items-start justify-between mb-2">
          <div>
            <span className="font-mono font-bold text-white text-sm">{sym}</span>
            <span className="text-tmuted text-[10px] ml-1.5">{name}</span>
          </div>
          <ChangePill pct={f?.change_pct} />
        </div>
        <div className="font-mono text-white text-2xl font-extrabold num-pop tracking-tight">
          {fmtPrice(f?.price)}
        </div>
        <TermBadge termData={termData} frontPrice={f?.price ?? 0} />
        {(f?.volume ?? 0) > 0 && (
          <div className="text-[9px] text-tmuted mt-1.5">Vol {fmtVol(f.volume)}</div>
        )}
      </div>
    );
  }

  // ── Secondary card — YM / CL / GC ────────────────────────────────────────────
  function SecondaryCard({ sym, name }) {
    const f = getF(sym);
    return (
      <div className="bg-cardDeep rounded-lg border border-line/40 p-3 h-full">
        <div className="flex items-center justify-between mb-1">
          <span className="font-mono font-bold text-white text-[11px]">{sym}</span>
          <span className="text-tmuted text-[9px] truncate ml-1 max-w-[60px]">{name}</span>
        </div>
        <div className="font-mono text-white text-base font-bold num-pop leading-tight">
          {fmtPrice(f?.price)}
        </div>
        <div className="mt-1.5">
          <ChangePill pct={f?.change_pct} />
        </div>
      </div>
    );
  }

  // ── COT accordion ─────────────────────────────────────────────────────────────
  function CotAccordion({ cotData }) {
    if (!cotData) return null;
    const esNet = cotData.es_specs_net;
    const nqNet = cotData.nq_specs_net;
    return (
      <div className="bg-surface rounded-xl border border-line shadow-card overflow-hidden">
        <button
          className="w-full section-bar px-3 py-2.5 flex items-center justify-between tap rounded-t-xl"
          onClick={() => setCotOpen(o => !o)}
        >
          <span className="section-h text-sm">COT Positioning</span>
          <span
            className="text-tmuted text-xs"
            style={{ display: 'inline-block', transition: 'transform 0.2s', transform: cotOpen ? 'rotate(90deg)' : 'rotate(0deg)' }}
          >▶</span>
        </button>
        <div style={{ maxHeight: cotOpen ? '260px' : '0', overflow: 'hidden', transition: 'max-height 0.25s ease' }}>
          <div className="px-3 pt-3 pb-1 grid grid-cols-2 gap-3">
            <div className="bg-cardDeep rounded-lg p-2.5 border border-line/40">
              <div className="text-[10px] text-tmuted uppercase tracking-wider mb-1">ES Specs Net</div>
              <div className={`font-mono font-bold text-sm num-pop ${(esNet ?? 0) < 0 ? 'text-danger' : 'text-ok'}`}>
                {fmtCot(esNet)}
              </div>
              <div className="text-[10px] text-tmuted mt-0.5">{cotInterpret(esNet)}</div>
            </div>
            <div className="bg-cardDeep rounded-lg p-2.5 border border-line/40">
              <div className="text-[10px] text-tmuted uppercase tracking-wider mb-1">NQ Specs Net</div>
              <div className={`font-mono font-bold text-sm num-pop ${(nqNet ?? 0) < 0 ? 'text-danger' : 'text-ok'}`}>
                {fmtCot(nqNet)}
              </div>
              <div className="text-[10px] text-tmuted mt-0.5">{cotInterpret(nqNet)}</div>
            </div>
          </div>
          <div className="px-3 pb-3 mt-2 border-t border-line/30 pt-2">
            <span className="text-[10px] text-tmuted">Report date: {cotData.report_date}</span>
            <span className="text-[10px] text-tmuted ml-2">· ES commercial: {fmtCot(cotData.es_commercial_net)}</span>
          </div>
        </div>
      </div>
    );
  }

  // ── ES Price History Chart (SVG) ─────────────────────────────────────────────
  function ESHistoryChart({ rows, activeIdx, onMarkerTap }) {
    if (!rows || rows.length < 2) {
      return (
        <div className="bg-surface rounded-xl border border-line shadow-card p-4">
          <div className="text-[11px] font-bold text-white uppercase tracking-widest mb-3">ES Price History</div>
          <div className="text-[11px] text-tmuted text-center py-6">Collecting data — check back once futures hours begin</div>
        </div>
      );
    }

    const W = 600, H = 120, PAD_L = 48, PAD_R = 12, PAD_T = 10, PAD_B = 24;
    const prices  = rows.map(r => r.es_price).filter(p => p != null);
    const minP    = Math.min(...prices);
    const maxP    = Math.max(...prices);
    // Enforce ±10 pt minimum spread so flat-tape sessions don't collapse y-axis labels
    const MID_SPREAD = 20;
    const rawRange   = maxP - minP;
    const displayMin = rawRange < MID_SPREAD ? (minP + maxP) / 2 - MID_SPREAD / 2 : minP;
    const displayMax = rawRange < MID_SPREAD ? (minP + maxP) / 2 + MID_SPREAD / 2 : maxP;
    const range      = displayMax - displayMin;

    const toX = i => PAD_L + (i / (rows.length - 1)) * (W - PAD_L - PAD_R);
    const toY = p => PAD_T + (1 - (p - displayMin) / range) * (H - PAD_T - PAD_B);

    // Build polyline points — skip nulls
    const validPoints = rows.map((r, i) => r.es_price != null ? `${toX(i)},${toY(r.es_price)}` : null).filter(Boolean);
    const polyline = validPoints.join(' ');

    // Y-axis labels: 3 ticks
    const yTicks = [displayMin, displayMin + range * 0.5, displayMax];

    // X-axis: first and last time
    const fmtTime = iso => {
      try {
        return new Date(iso + 'Z').toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', timeZone: 'America/New_York' });
      } catch (_) { return ''; }
    };

    // Annotation markers
    const markers = rows.map((r, i) => r.observer_annotation ? { i, r } : null).filter(Boolean);

    const activeAnnotationText = activeIdx != null && rows[activeIdx]?.observer_annotation
      ? rows[activeIdx].observer_annotation
      : null;

    return (
      <div className="bg-surface rounded-xl border border-line shadow-card p-4">
        <div className="flex items-center justify-between mb-2">
          <span className="text-[11px] font-bold text-white uppercase tracking-widest">ES Price History</span>
          <span className="text-[9px] text-tmuted">{rows.length} pts · tap dot for Observer note</span>
        </div>

        <div style={{ width: '100%', overflowX: 'auto' }}>
          <svg
            viewBox={`0 0 ${W} ${H}`}
            style={{ width: '100%', minWidth: '280px', height: 'auto', display: 'block' }}
            preserveAspectRatio="none"
          >
            {/* Grid lines */}
            {yTicks.map((tick, ti) => (
              <line key={ti}
                x1={PAD_L} y1={toY(tick)} x2={W - PAD_R} y2={toY(tick)}
                stroke="#1e3a5f" strokeWidth="0.5"
              />
            ))}

            {/* Y-axis labels */}
            {yTicks.map((tick, ti) => (
              <text key={ti}
                x={PAD_L - 4} y={toY(tick) + 3.5}
                textAnchor="end" fontSize="8" fill="#64748b"
              >
                {tick.toLocaleString('en-US', { maximumFractionDigits: 0 })}
              </text>
            ))}

            {/* X-axis labels */}
            <text x={PAD_L} y={H - 4} textAnchor="start" fontSize="8" fill="#64748b">
              {fmtTime(rows[0]?.recorded_at)}
            </text>
            <text x={W - PAD_R} y={H - 4} textAnchor="end" fontSize="8" fill="#64748b">
              {fmtTime(rows[rows.length - 1]?.recorded_at)}
            </text>

            {/* Price line */}
            <polyline
              points={polyline}
              fill="none"
              stroke="#3b82f6"
              strokeWidth="1.5"
              strokeLinejoin="round"
              strokeLinecap="round"
            />

            {/* Annotation markers */}
            {markers.map(({ i, r }) => {
              if (r.es_price == null) return null;
              const cx = toX(i), cy = toY(r.es_price);
              const isActive = activeIdx === i;
              return (
                <g key={i} style={{ cursor: 'pointer' }} onClick={() => onMarkerTap(i)}>
                  <circle cx={cx} cy={cy} r="8" fill="transparent" />
                  <circle cx={cx} cy={cy} r={isActive ? 5 : 3.5}
                    fill={isActive ? '#f59e0b' : '#fbbf24'}
                    stroke={isActive ? '#fff' : '#1e3a5f'}
                    strokeWidth={isActive ? 1.5 : 1}
                  />
                </g>
              );
            })}
          </svg>
        </div>

        {/* Annotation text — expands below chart when a marker is tapped */}
        {activeAnnotationText && (
          <div className="mt-2 pt-2 border-t border-line/40">
            <div className="flex items-center justify-between mb-1">
              <span className="text-[10px] font-semibold text-yellow-400">🤖 Observer note</span>
              <button
                className="text-[10px] text-tmuted tap px-1"
                onClick={() => onMarkerTap(null)}
              >✕</button>
            </div>
            <p className="text-[11px] text-slate-300 leading-snug italic">"{activeAnnotationText}"</p>
          </div>
        )}
      </div>
    );
  }

  // ── Render ────────────────────────────────────────────────────────────────────
  return (
    <div className="space-y-4">

      {/* Header bar */}
      <div className="flex items-center justify-between">
        <span className="text-[11px] font-bold text-white uppercase tracking-widest">FUTURES</span>
        <span className={`text-[10px] ${fetchError ? 'text-warn' : 'text-tmuted'}`}>
          {stalenessLabel}
        </span>
      </div>

      {/* Observer note — futures tab; falls back to market observation until first futures observation writes */}
      <AIObserver tab="futures" fallbackTab="market" />

      {/* Primary — ES + NQ with term structure */}
      <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
        <PrimaryCard sym="ES" name="E-mini S&P 500" termData={term} />
        <PrimaryCard sym="NQ" name="Nasdaq 100"     termData={nqTerm} />
      </div>

      {/* ES price history chart with Observer annotation markers */}
      <ESHistoryChart
        rows={history}
        activeIdx={activeAnnotation}
        onMarkerTap={idx => setActiveAnnotation(prev => prev === idx ? null : idx)}
      />

      {/* Secondary — YM full-width on mobile, three in a row on sm+ */}
      <div className="grid grid-cols-2 sm:grid-cols-3 gap-2">
        <div className="col-span-2 sm:col-span-1">
          <SecondaryCard sym="YM" name="Dow E-mini" />
        </div>
        <SecondaryCard sym="CL" name="Crude Oil" />
        <SecondaryCard sym="GC" name="Gold" />
      </div>

      {/* COT accordion — collapsed by default */}
      <CotAccordion cotData={cot} />

    </div>
  );
};
