// page-themes.jsx — 題材熱度（NEW，1:1 對齊設計檔，2026-05-10）
// 設計檔結構：ThemeHeatmap (treemap) + ThemeDetail + RisingThemes + FadingThemes
// D1 接線：themes.themes、industry_pool_full、portfolio + watchlist (judging leaders)
// 使用者新增題材 → localStorage 'user_themes_v1'（後續可同步 D1）
// 重要 export：window.ThemesPage / window.SectorPage（讓舊路由 sector 也指過來）
(function(){
  const T = window.STOCK_TOKENS;

  const fmtSign = (n, d = 2) => (n == null) ? '—' : (n > 0 ? '+' : '') + Number(n).toFixed(d);
  const pctClass = (n) => n > 0 ? 'up' : n < 0 ? 'down' : 'flat';

  const USER_THEMES_KEY = 'user_themes_v1';
  function loadUserThemes() {
    try { return JSON.parse(localStorage.getItem(USER_THEMES_KEY) || '[]'); }
    catch { return []; }
  }
  function saveUserThemes(arr) { localStorage.setItem(USER_THEMES_KEY, JSON.stringify(arr)); }

  function ThemesPage() {
    const live = window.STOCK_DATA_LIVE || {};
    const liveThemes = live.themes?.themes || [];
    const sectorStrength = live.sector_strength?.sectors || [];

    // 合併 D1 themes + sector_strength + 使用者新增
    const merged = React.useMemo(() => {
      const map = new Map();
      liveThemes.forEach(t => {
        map.set(t.name, {
          name: t.name,
          heat: Number(t.heat) || 0,
          chg: Number(t.chg ?? t.heat * 0.5) || 0,
          leaders: t.stocks || [],
          note: t.trigger || '',
        });
      });
      sectorStrength.forEach(s => {
        if (!map.has(s.industry)) {
          map.set(s.industry, {
            name: s.industry,
            heat: Math.round(s.strength_score || 0),
            chg: Number(s.avg_chg_5d ?? 0),
            leaders: (s.top_3 || []).map(x => x.code),
            note: '5d 強弱 ' + (s.avg_chg_5d >= 0 ? '+' : '') + (s.avg_chg_5d ?? 0) + '%',
          });
        }
      });
      loadUserThemes().forEach(t => {
        if (!map.has(t.name)) map.set(t.name, { ...t, _user: true });
      });
      return [...map.values()];
    }, [liveThemes, sectorStrength]);

    const [themes, setThemes] = React.useState(merged);
    const [selectedName, setSelectedName] = React.useState(merged[0]?.name);

    React.useEffect(() => {
      setThemes(merged);
      if (!merged.find(m => m.name === selectedName)) setSelectedName(merged[0]?.name);
    }, [merged.length]);

    const selected = themes.find(t => t.name === selectedName) || themes[0];

    function addTheme() {
      const name = window.prompt('新題材名稱（例如：人形機器人）');
      if (!name || !name.trim()) return;
      if (themes.some(t => t.name === name.trim())) { alert('題材名稱已存在'); return; }
      const note = window.prompt('題材說明（選填）', '') || '';
      const newTheme = { name: name.trim(), note, heat: 50, chg: 0, leaders: [], _user: true };
      const next = [newTheme, ...themes];
      setThemes(next);
      saveUserThemes(next.filter(t => t._user));
      setSelectedName(newTheme.name);
    }
    function removeTheme(name) {
      if (!window.confirm(`刪除題材「${name}」？`)) return;
      const next = themes.filter(t => t.name !== name);
      setThemes(next);
      saveUserThemes(next.filter(t => t._user));
      if (selectedName === name) setSelectedName(next[0]?.name);
    }
    function addStockToTheme(themeName, code) {
      const next = themes.map(t => t.name === themeName
        ? { ...t, leaders: [...new Set([...(t.leaders || []), code])] }
        : t);
      setThemes(next);
      saveUserThemes(next.filter(t => t._user));
    }
    function removeStockFromTheme(themeName, code) {
      const next = themes.map(t => t.name === themeName
        ? { ...t, leaders: (t.leaders || []).filter(c => c !== code) }
        : t);
      setThemes(next);
      saveUserThemes(next.filter(t => t._user));
    }

    return (
      <div style={{ padding: 16, maxWidth: 1400, margin: '0 auto' }}>
        <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', paddingBottom: 16, borderBottom: '1px solid var(--line)' }}>
          <div>
            <div className="mono" style={{ fontSize: 11, color: 'var(--fg-3)', letterSpacing: '.1em' }}>
              THEMES · LIVE · {themes.length} TRACKED
            </div>
            <div style={{ fontSize: 22, fontWeight: 600, color: 'var(--fg-0)', marginTop: 4 }}>題材 / 產業熱度</div>
            <div style={{ fontSize: 12.5, color: 'var(--fg-2)', marginTop: 2 }}>
              新聞密度、社群熱度、相關個股漲跌綜合指標。可自訂題材並加入個股
            </div>
          </div>
          <button className="btn btn-primary" onClick={addTheme} style={{ alignSelf: 'center' }}>＋ 新增題材</button>
        </div>

        {themes.length === 0 ? (
          <div className="panel" style={{ padding: '60px 20px', textAlign: 'center', marginTop: 16 }}>
            <div className="mono" style={{ fontSize: 11, color: 'var(--fg-3)', letterSpacing: '.08em' }}>// NO THEMES DATA</div>
          </div>
        ) : (
          <>
            <ThemeHeatmap themes={themes} selected={selected} setSelectedName={setSelectedName} />
            {selected && (
              <div style={{ marginTop: 12 }}>
                <ThemeDetail
                  theme={selected}
                  onAddStock={code => addStockToTheme(selected.name, code)}
                  onRemoveStock={code => removeStockFromTheme(selected.name, code)}
                  onDelete={selected._user ? () => removeTheme(selected.name) : null}
                />
              </div>
            )}
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, marginTop: 12 }}>
              <RisingThemes themes={themes} />
              <FadingThemes themes={themes} />
            </div>
          </>
        )}
      </div>
    );
  }
  window.ThemesPage = ThemesPage;
  // 舊路由 sector 也指向新題材頁
  window.SectorPage = ThemesPage;

  // ── ThemeHeatmap：treemap 風格 ────────────────────────────────────
  function ThemeHeatmap({ themes: themesIn, selected, setSelectedName }) {
    const themes = [...themesIn].sort((a, b) => b.heat - a.heat);
    return (
      <div className="panel" style={{ padding: 4, marginTop: 16 }}>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(12, 1fr)', gridAutoRows: 60, gap: 4 }}>
          {themes.map((t, i) => {
            const size = i < 3 ? { gridColumn: 'span 4', gridRow: 'span 2' }
                       : i < 7 ? { gridColumn: 'span 3', gridRow: 'span 1' }
                       : { gridColumn: 'span 2', gridRow: 'span 1' };
            let color;
            if (t.chg < -0.5) color = 'var(--down)';
            else if (t.chg < 0) color = 'var(--down-soft)';
            else if (t.heat >= 80 || t.chg > 2.5) color = 'var(--up)';
            else if (t.chg > 0 || t.heat >= 55) color = 'var(--up-soft)';
            else color = 'var(--fg-3)';
            const intensity = Math.min(1, t.heat / 100);
            return (
              <div key={t.name} className="heat-cell" style={{
                ...size,
                background: color,
                opacity: 0.55 + intensity * 0.45,
                outline: selected?.name === t.name ? '2px solid var(--accent)' : 'none',
              }}
              onClick={() => setSelectedName(t.name)}>
                <div>
                  <div style={{ fontSize: i < 3 ? 16 : i < 7 ? 13 : 11, fontWeight: 600, lineHeight: 1.2 }}>{t.name}</div>
                  <div className="mono" style={{ fontSize: 10, opacity: 0.85 }}>{t.note}</div>
                </div>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end' }}>
                  <span className="mono" style={{ fontSize: i < 3 ? 13 : 11, opacity: 0.9 }}>熱度 {t.heat}</span>
                  <span className="num" style={{ fontSize: i < 3 ? 14 : 12, fontWeight: 600 }}>{fmtSign(t.chg, 1)}%</span>
                </div>
              </div>
            );
          })}
        </div>
      </div>
    );
  }

  // ── ThemeDetail ──────────────────────────────────────────────────
  function ThemeDetail({ theme, onAddStock, onRemoveStock, onDelete }) {
    const live = window.STOCK_DATA_LIVE || {};
    const [adding, setAdding] = React.useState(false);
    const [q, setQ] = React.useState('');

    // 從 picks + portfolio 組 stocks pool
    const stocksPool = [];
    (live.picks?.picks || []).forEach(p => stocksPool.push({ code: p.code, name: p.name, price: p.current_price, pct: p.change_pct }));
    (live.portfolio?.holdings || []).forEach(h => {
      if (!stocksPool.find(s => s.code === h.code)) stocksPool.push({ code: h.code, name: h.name, price: h.current_price, pct: 0 });
    });

    const leaders = (theme.leaders || []).map(c => {
      const s = stocksPool.find(x => x.code === c);
      return s || { code: c, name: '—', price: null, pct: null };
    });
    const candidates = q.trim() ? stocksPool.filter(s =>
      !theme.leaders.includes(s.code) && (s.code.includes(q) || (s.name || '').includes(q))
    ).slice(0, 8) : [];

    return (
      <div className="panel">
        <div className="panel-h">
          <span className="label">{theme.name}{theme._user && <span className="pill" style={{ marginLeft: 6 }}>USER</span>}</span>
          <span style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
            <span className="pill">熱度 {theme.heat}</span>
            {onDelete && <button className="btn" onClick={onDelete} style={{ fontSize: 11, padding: '4px 10px', color: 'var(--down)' }}>刪除題材</button>}
          </span>
        </div>
        <div style={{ padding: 14, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 20 }}>
          <div>
            <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, marginBottom: 12 }}>
              <span className="num" style={{ fontSize: 24, fontWeight: 600, color: theme.chg > 0 ? 'var(--up)' : theme.chg < 0 ? 'var(--down)' : 'var(--fg-3)' }}>
                {fmtSign(theme.chg, 2)}%
              </span>
              <span className="mono" style={{ fontSize: 11, color: 'var(--fg-3)' }}>類股當日漲跌</span>
            </div>
            <div style={{ fontSize: 12, color: 'var(--fg-2)', lineHeight: 1.6 }}>
              {theme.note || <span style={{ color: 'var(--fg-3)' }}>（尚無說明）</span>}
            </div>
          </div>
          <div>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
              <span className="mono" style={{ fontSize: 9.5, color: 'var(--fg-3)', letterSpacing: '.08em' }}>相關個股 · {leaders.length} 檔</span>
              {theme._user && (
                <button className="btn" style={{ fontSize: 11, padding: '4px 10px' }} onClick={() => setAdding(!adding)}>
                  {adding ? '取消' : '＋ 加入個股'}
                </button>
              )}
            </div>
            {adding && (
              <div style={{ marginBottom: 8, position: 'relative' }}>
                <input autoFocus value={q} onChange={e => setQ(e.target.value)}
                  placeholder="輸入代碼或名稱…" style={{ width: '100%', background: 'var(--bg-2)' }} />
                {candidates.length > 0 && (
                  <div style={{ position: 'absolute', top: '100%', left: 0, right: 0, background: 'var(--bg-1)', border: '1px solid var(--line-2)', borderRadius: 3, zIndex: 5, marginTop: 2, maxHeight: 220, overflow: 'auto' }}>
                    {candidates.map(s => (
                      <div key={s.code} onClick={() => { onAddStock(s.code); setQ(''); setAdding(false); }}
                        style={{ padding: '8px 10px', cursor: 'pointer', display: 'flex', justifyContent: 'space-between', fontSize: 12 }}
                        onMouseEnter={e => e.currentTarget.style.background = 'var(--hover)'}
                        onMouseLeave={e => e.currentTarget.style.background = ''}>
                        <span><span className="mono" style={{ color: 'var(--fg-2)' }}>{s.code}</span> <span style={{ color: 'var(--fg-0)' }}>{s.name}</span></span>
                        {s.pct != null && <span className={`num ${pctClass(s.pct)}`}>{fmtSign(s.pct)}%</span>}
                      </div>
                    ))}
                  </div>
                )}
              </div>
            )}
            <div style={{ display: 'grid', gap: 6 }}>
              {leaders.length === 0 ? (
                <div style={{ fontSize: 12, color: 'var(--fg-3)', padding: '16px 10px', textAlign: 'center', border: '1px dashed var(--line-2)', borderRadius: 3 }}>
                  尚未加入個股
                </div>
              ) : leaders.map(s => (
                <div key={s.code} style={{ display: 'grid', gridTemplateColumns: '1fr auto auto auto', gap: 10, padding: '8px 10px', background: 'var(--bg-2)', borderRadius: 3, alignItems: 'center' }}>
                  <span>
                    <span className="mono" style={{ color: 'var(--fg-2)', fontSize: 12 }}>{s.code}</span>
                    <span style={{ marginLeft: 8, color: 'var(--fg-0)', fontSize: 12.5 }}>{s.name}</span>
                  </span>
                  {s.price != null && <span className="num" style={{ fontSize: 12 }}>{s.price}</span>}
                  {s.pct != null && <span className={`num ${pctClass(s.pct)}`} style={{ fontSize: 12, fontWeight: 600, minWidth: 50, textAlign: 'right' }}>{fmtSign(s.pct)}%</span>}
                  {theme._user && (
                    <button onClick={() => onRemoveStock(s.code)} style={{ background: 'transparent', border: 'none', color: 'var(--fg-3)', cursor: 'pointer', fontSize: 14, padding: '0 4px' }} title="移除">×</button>
                  )}
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>
    );
  }

  function RisingThemes({ themes: themesIn }) {
    const themes = [...themesIn].sort((a, b) => b.chg - a.chg).slice(0, 5);
    return (
      <div className="panel">
        <div className="panel-h">
          <span className="label">▲ 強勢題材 TOP 5</span>
          <span className="pill">當日</span>
        </div>
        <div>
          {themes.map((t, i) => (
            <div key={t.name} style={{
              display: 'grid', gridTemplateColumns: '20px 1fr auto auto', gap: 10,
              padding: '10px 14px', alignItems: 'center',
              borderBottom: i === themes.length - 1 ? 'none' : '1px solid var(--line)',
            }}>
              <span className="mono" style={{ fontSize: 10, color: 'var(--up)' }}>{i + 1}</span>
              <div>
                <div style={{ fontSize: 13, color: 'var(--fg-0)' }}>{t.name}</div>
                <div style={{ fontSize: 10.5, color: 'var(--fg-3)' }}>{t.note}</div>
              </div>
              <span className="mono chip-up chip">熱 {t.heat}</span>
              <span className="num up" style={{ fontWeight: 600, minWidth: 60, textAlign: 'right' }}>{fmtSign(t.chg, 1)}%</span>
            </div>
          ))}
        </div>
      </div>
    );
  }

  function FadingThemes({ themes: themesIn }) {
    const themes = [...themesIn].sort((a, b) => a.chg - b.chg).slice(0, 5);
    return (
      <div className="panel">
        <div className="panel-h">
          <span className="label">▼ 退潮題材 TOP 5</span>
          <span className="pill">當日</span>
        </div>
        <div>
          {themes.map((t, i) => (
            <div key={t.name} style={{
              display: 'grid', gridTemplateColumns: '20px 1fr auto auto', gap: 10,
              padding: '10px 14px', alignItems: 'center',
              borderBottom: i === themes.length - 1 ? 'none' : '1px solid var(--line)',
            }}>
              <span className="mono" style={{ fontSize: 10, color: 'var(--down)' }}>{i + 1}</span>
              <div>
                <div style={{ fontSize: 13, color: 'var(--fg-0)' }}>{t.name}</div>
                <div style={{ fontSize: 10.5, color: 'var(--fg-3)' }}>{t.note}</div>
              </div>
              <span className="mono chip" style={{ background: 'var(--bg-3)' }}>熱 {t.heat}</span>
              <span className={`num ${t.chg < 0 ? 'down' : 'flat'}`} style={{ fontWeight: 600, minWidth: 60, textAlign: 'right' }}>{fmtSign(t.chg, 1)}%</span>
            </div>
          ))}
        </div>
      </div>
    );
  }

})();
