/* src/v2/tools.jsx — HeatmapCard, ScreenerCard, EarningsCalCard.
   Each is a preview card linking to the full tool. */

const { useState: _tlS, useEffect: _tlE, useMemo: _tlM } = React;

// ---------- Heatmap cell color scale ----------
function heatColor(chPct) {
  const p = Math.max(-5, Math.min(5, chPct || 0));
  const abs = Math.abs(p) / 5;
  // Green for up, red for down; interpolate opacity
  if (p >= 0) return `oklch(0.58 ${(0.14 * abs).toFixed(3)} 152 / ${Math.max(0.12, abs * 0.85).toFixed(2)})`;
  return `oklch(0.58 ${(0.18 * abs).toFixed(3)} 28 / ${Math.max(0.12, abs * 0.85).toFixed(2)})`;
}

// ---------- Heatmap card ----------
function HeatmapCard() {
  const [stocks, setStocks] = _tlS([]);
  const [loading, setLoading] = _tlS(true);

  _tlE(() => {
    let alive = true;
    (async () => {
      try {
        const data = await window.TMT_API.getJSON('/screener-dynamic?type=most_actives&count=30');
        if (!alive || !data || !data.stocks) return;
        setStocks(data.stocks);
      } catch (e) { /* empty */ }
      finally { if (alive) setLoading(false); }
    })();
    return () => { alive = false; };
  }, []);

  // Group by sector for the heat-sec layout
  const bySector = _tlM(() => {
    const g = {};
    stocks.forEach(s => {
      const sec = s.sector || 'Other';
      if (!g[sec]) g[sec] = [];
      g[sec].push(s);
    });
    return Object.entries(g).sort((a, b) => b[1].length - a[1].length);
  }, [stocks]);

  return (
    <div className="card tool-card heat-card">
      <div className="card-hd">
        <span className="t">Heatmap</span>
        <a className="card-link" href="/heatmap.html">Full heatmap →</a>
        <span className="explain">S&amp;P most-active names, grouped by sector, sized equally, colored by % change.</span>
      </div>
      <div className="card-bd heat-bd">
        {loading && <div style={{ padding: 20, color: 'var(--ink-3)', fontStyle: 'italic', fontFamily: 'var(--serif)' }}>Loading heatmap…</div>}
        {!loading && stocks.length === 0 && <div style={{ padding: 20, color: 'var(--ink-3)' }}>No data.</div>}
        {!loading && stocks.length > 0 && (
          <div className="heat-grid">
            {bySector.map(([sector, items]) => (
              <div className="heat-sec" key={sector} style={{ flex: items.length }}>
                <div className="sec-lbl">{sector}<span className="w">{items.length}</span></div>
                <div className="sec-cells">
                  {items.map(s => (
                    <a
                      key={s.symbol}
                      className="cell"
                      href={'/details.html?symbol=' + encodeURIComponent(s.symbol)}
                      style={{ background: heatColor(s.changePercent), textDecoration: 'none' }}
                      title={s.name}
                    >
                      <span className="sym">{s.symbol}</span>
                      <span className="pct">{fmtPct(s.changePercent)}</span>
                    </a>
                  ))}
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

// ---------- Screener card ----------
const SCREENER_PRESETS = [
  { id: 'day_gainers',     label: 'Day gainers' },
  { id: 'day_losers',      label: 'Day losers' },
  { id: 'most_actives',    label: 'Most active' },
  { id: 'small_cap_gainers', label: 'Small-cap' },
  { id: 'undervalued_growth', label: 'Undervalued growth' },
];

function ScreenerCard() {
  const [preset, setPreset] = _tlS('day_gainers');
  const [rows, setRows] = _tlS([]);
  const [loading, setLoading] = _tlS(true);

  _tlE(() => {
    let alive = true;
    setLoading(true);
    (async () => {
      try {
        const data = await window.TMT_API.getJSON('/screener-dynamic?type=' + preset + '&count=12');
        if (!alive || !data || !data.stocks) return;
        setRows(data.stocks);
      } catch (e) { setRows([]); }
      finally { if (alive) setLoading(false); }
    })();
    return () => { alive = false; };
  }, [preset]);

  return (
    <div className="card tool-card screen-card">
      <div className="card-hd">
        <span className="t">Screener</span>
        <a className="card-link" href="/screener.html">Full screener →</a>
        <span className="explain">Preset scans over the Yahoo screener engine — click for the full research view.</span>
      </div>
      <div className="presets">
        {SCREENER_PRESETS.map(p => (
          <button key={p.id} className={preset === p.id ? 'on' : ''} onClick={() => setPreset(p.id)}>{p.label}</button>
        ))}
      </div>
      <div className="scr-thead">
        <span>Symbol</span>
        <span className="r">Price</span>
        <span className="r">% Chg</span>
        <span className="r">PE</span>
        <span className="r">52w Lo</span>
        <span className="r">—</span>
        <span className="r">52w Hi</span>
        <span className="r">Sector</span>
      </div>
      <div className="card-bd">
        {loading && <div style={{ padding: 20, color: 'var(--ink-3)', fontStyle: 'italic', fontFamily: 'var(--serif)' }}>Loading…</div>}
        {!loading && rows.map((r, i) => (
          <a key={r.symbol || i} className="scr-row" href={'/details.html?symbol=' + encodeURIComponent(r.symbol)} style={{ textDecoration: 'none' }}>
            <div className="sym-c">
              <span className="lbl">{r.symbol}</span>
              <span className="nm">{r.name || ''}</span>
            </div>
            <span className="r">{fmtPx(r.price)}</span>
            <span className={'pct ' + tone(r.changePercent)}>{fmtPct(r.changePercent)}</span>
            <span className="r">{r.trailingPE != null ? r.trailingPE.toFixed(1) : '—'}</span>
            <span className="r">{fmtPx(r.fiftyTwoWeekLow)}</span>
            <span className="r" style={{ color: 'var(--ink-4)' }}>—</span>
            <span className="r">{fmtPx(r.fiftyTwoWeekHigh)}</span>
            <span className="r" style={{ fontSize: 10, color: 'var(--ink-3)', fontFamily: 'var(--sans)' }}>{(r.sector || '').slice(0, 10)}</span>
          </a>
        ))}
      </div>
    </div>
  );
}

// ---------- Earnings calendar card ----------
function EarningsCalCard() {
  const [upcoming, setUpcoming] = _tlS([]);
  const [loading, setLoading] = _tlS(true);
  const [err, setErr] = _tlS(null);

  _tlE(() => {
    let alive = true;
    (async () => {
      try {
        const data = await window.TMT_API.getJSON('/earnings-calendar');
        if (!alive) return;
        // Response shape: { success, data: { upcoming: [{symbol, name, earningsDate, epsEstimate, callTime, marketCap, ...}] } }
        const rows = (data && data.success && data.data && Array.isArray(data.data.upcoming)) ? data.data.upcoming : [];
        setUpcoming(rows);
        if (rows.length === 0) setErr('No upcoming earnings this week.');
      } catch (e) {
        if (alive) setErr('Earnings calendar feed is connecting — see the full earnings view.');
      }
      finally { if (alive) setLoading(false); }
    })();
    return () => { alive = false; };
  }, []);

  // Group upcoming earnings into 5 weekday buckets starting today
  const days = _tlM(() => {
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    const buckets = [];
    for (let i = 0; i < 5; i++) {
      const d = new Date(today);
      d.setDate(today.getDate() + i);
      buckets.push({
        label: d.toLocaleDateString('en-US', { weekday: 'short' }).toUpperCase(),
        date: d.toISOString().slice(0, 10),
        dateLabel: d.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }),
        items: [],
      });
    }
    // Sort upcoming by marketCap desc so top caps surface first within each day
    const sorted = [...upcoming].sort((a, b) => (b.marketCap || 0) - (a.marketCap || 0));
    sorted.forEach(e => {
      if (!e.symbol || !e.earningsDate) return;
      const dt = new Date(e.earningsDate);
      if (isNaN(dt.getTime())) return;
      const key = dt.toISOString().slice(0, 10);
      const idx = buckets.findIndex(b => b.date === key);
      if (idx < 0) return;
      // Per-day cap to keep the tile readable
      if (buckets[idx].items.length >= 4) return;
      // callTime: "TAS" or "TNS" from Yahoo — map to AMC/BMO if known, else AMC
      const ct = String(e.callTime || '').toUpperCase();
      const when = (ct.includes('BMO') || ct.includes('TNS')) ? 'BMO' : 'AMC';
      buckets[idx].items.push({
        sym: e.symbol,
        name: e.name || e.symbol,
        estimate: e.epsEstimate,
        when,
      });
    });
    return buckets;
  }, [upcoming]);

  return (
    <div className="card tool-card earncal-card">
      <div className="card-hd">
        <span className="t">Earnings · this week</span>
        <a className="card-link" href="/earnings.html">Full earnings →</a>
        <span className="explain">Consensus EPS for upcoming prints across your watchlist seeds.</span>
      </div>
      <div className="card-bd earncal-bd">
        {loading && <div style={{ padding: 20, color: 'var(--ink-3)', fontStyle: 'italic', fontFamily: 'var(--serif)' }}>Loading earnings…</div>}
        {!loading && err && (
          <div style={{ padding: '18px 20px', color: 'var(--ink-2)', fontSize: 12.5, lineHeight: 1.5 }}>
            {err}{' '}
            <a href="/earnings.html" style={{ color: 'var(--cool)', textDecoration: 'none', fontWeight: 500 }}>Open earnings →</a>
          </div>
        )}
        {!loading && !err && (
          <div className="days">
            {days.map((d, i) => (
              <div className="day" key={i}>
                <div className="day-hd">{d.label}<span>{d.dateLabel}</span></div>
                <div className="day-body">
                  {d.items.length === 0 && <div style={{ color: 'var(--ink-4)', fontSize: 11, textAlign: 'center', padding: '14px 0' }}>—</div>}
                  {d.items.map((it, j) => (
                    <a key={j} className="ec-item" href={'/details.html?symbol=' + encodeURIComponent(it.sym)} style={{ textDecoration: 'none' }}>
                      <span className="sym">{it.sym}</span>
                      <span className={'when ' + (it.when === 'BMO' ? 'bmo' : 'amc')}>{it.when}</span>
                      <span className="mc">{it.name}</span>
                      <span className="est">EPS ${it.estimate != null ? Number(it.estimate).toFixed(2) : '—'}</span>
                    </a>
                  ))}
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { HeatmapCard, ScreenerCard, EarningsCalCard });
