// ————————————————————————————————————————————————————————————————
// Themes landing — summary grid of all themes (parent of theme detail)
// ————————————————————————————————————————————————————————————————

const { useState: ZLUS, useMemo: ZLUM } = React;

function ThemesList({ lang, onOpen }) {
  const [q, setQ] = ZLUS("");
  const [sortBy, setSortBy] = ZLUS("mcap");

  const items = ZLUM(() => {
    const list = window.THEMES.map((th) => {
      const tickers = th.tickers.filter((t) => window.STOCKS[t]);
      const chgs = tickers.map((t) => window.STOCKS[t].chg);
      const avg = chgs.length
        ? chgs.reduce((a, b) => a + b, 0) / chgs.length
        : 0;
      const up = chgs.filter((c) => c >= 0).length;
      const mcap = tickers.reduce(
        (a, t) => a + (window.STOCKS[t]?.mcap || 0),
        0,
      );
      // 90d index series — built from price data if available
      const anyP = window.PRICES[tickers[0]];
      const len = anyP ? Math.min(90, anyP.length) : 60;
      const series = [];
      for (let i = 0; i < len; i++) {
        let sum = 0,
          n = 0;
        for (const tk of tickers) {
          const p = window.pcs(window.PRICES[tk]);
          if (p && p[p.length - len + i] !== undefined) {
            sum += p[p.length - len + i];
            n++;
          }
        }
        if (n) series.push(sum / n);
      }
      // normalize series to index (100 start)
      const base = series[0] || 1;
      const norm = series.length ? series.map((v) => (v / base) * 100) : [];
      // news count touching theme
      const nNews = window.NEWS.filter((n) => n.themes?.includes(th.id)).length;
      const hasReport = !!window.themeReport(th.id);
      return {
        id: th.id,
        theme: th,
        count: tickers.length,
        avg,
        up,
        down: tickers.length - up,
        mcap,
        series: norm,
        nNews,
        hasReport,
      };
    });

    const s = (q || "").toLowerCase();
    let f = list
      .filter((it) => it.count > 0)
      .filter(
        (it) =>
          !s ||
          (it.theme.name || it.theme.label || "").toLowerCase().includes(s) ||
          (it.theme.jp || "").includes(q) ||
          it.theme.id.includes(s),
      );

    if (sortBy === "mcap") f.sort((a, b) => b.mcap - a.mcap);
    if (sortBy === "perf") f.sort((a, b) => b.avg - a.avg);
    if (sortBy === "size") f.sort((a, b) => b.count - a.count);
    if (sortBy === "name")
      f.sort((a, b) => (a.theme.name || "").localeCompare(b.theme.name || ""));
    return f;
  }, [q, sortBy, window._reportsReady]);  // recompute hasReport when the deferred report blob lands

  const totalMcap = items.reduce((a, b) => a + b.mcap, 0);
  const totalStocks = new Set(
    window.THEMES.flatMap((t) => t.tickers).filter((t) => window.STOCKS[t]),
  ).size;
  const totalThemes = items.length;

  return (
    <div className="themes-view">
      <header className="themes-hero">
        <div className="themes-hero-l">
          <div className="theme-hero-label">
            <span
              className="tc-dot"
              style={{
                background: "var(--accent)",
                boxShadow: "0 0 10px var(--accent)",
              }}
            />
            {lang === "jp" ? "テーマ概覧" : "Investment themes"}
          </div>
          <h1 className="theme-hero-n">
            {lang === "jp"
              ? "分野別・サプライチェーン"
              : "Themes & value chains"}
          </h1>
          <div className="theme-hero-sub">
            {
              window.THEMES.filter((t) =>
                t.tickers.some((x) => window.STOCKS[x]),
              ).length
            }{" "}
            {lang === "jp" ? "テーマ" : "themes"}
            <span className="dot">·</span>
            {totalStocks} {lang === "jp" ? "銘柄" : "unique tickers"}
            <span className="dot">·</span>¥{(totalMcap / 1000).toFixed(0)}T{" "}
            {lang === "jp" ? "時価総額合計" : "aggregate mcap"}
          </div>
        </div>
        <div className="themes-hero-r">
          <input
            className="reports-search"
            placeholder={lang === "jp" ? "テーマを検索…" : "Search themes…"}
            value={q}
            onChange={(e) => setQ(e.target.value)}
          />
          <div className="seg small">
            <button
              className={sortBy === "mcap" ? "on" : ""}
              onClick={() => setSortBy("mcap")}
            >
              {lang === "jp" ? "時価" : "Mcap"}
            </button>
            <button
              className={sortBy === "perf" ? "on" : ""}
              onClick={() => setSortBy("perf")}
            >
              {lang === "jp" ? "騰落" : "Perf"}
            </button>
            <button
              className={sortBy === "size" ? "on" : ""}
              onClick={() => setSortBy("size")}
            >
              {lang === "jp" ? "銘柄" : "Size"}
            </button>
            <button
              className={sortBy === "name" ? "on" : ""}
              onClick={() => setSortBy("name")}
            >
              A–Z
            </button>
          </div>
        </div>
      </header>

      <div className="themes-grid">
        {items.map((it, i) => (
          <button
            key={it.id}
            className="theme-tile"
            style={{ "--tc": it.theme.color, animationDelay: i * 40 + "ms" }}
            onClick={() => onOpen(it.id)}
          >
            <div className="theme-tile-band" />
            <div className="theme-tile-h">
              <div className="theme-tile-eyebrow">
                <span className="tc-dot" />
                <span>{lang === "jp" ? it.theme.jp : it.theme.name}</span>
              </div>
              <div className="theme-tile-sub">
                {lang === "jp" ? it.theme.name : it.theme.jp}
              </div>
            </div>

            <div className="theme-tile-chart">
              <window.Sparkline
                data={it.series.length ? it.series : [100, 100]}
                width={280}
                height={50}
                glow={true}
              />
            </div>

            <div className="theme-tile-stats">
              <div>
                <span>{lang === "jp" ? "銘柄" : "Stocks"}</span>
                <b>{it.count}</b>
              </div>
              <div>
                <span>{lang === "jp" ? "時価" : "Mcap"}</span>
                <b>¥{(it.mcap / 1000).toFixed(1)}T</b>
              </div>
              <div>
                <span>{lang === "jp" ? "平均" : "Avg"}</span>
                <b className={it.avg >= 0 ? "up" : "down"}>
                  {window.fmtPct(it.avg)}
                </b>
              </div>
              <div>
                <span>{lang === "jp" ? "上昇/下降" : "Adv"}</span>
                <b>
                  <span className="up">{it.up}</span>
                  <span className="sl">/</span>
                  <span className="down">{it.down}</span>
                </b>
              </div>
            </div>

            <div className="theme-tile-foot">
              <span className="theme-tile-flags">
                {it.nNews > 0 && (
                  <span className="tile-flag">📰 {it.nNews}</span>
                )}
                {it.hasReport && (
                  <span className="tile-flag rep">
                    {lang === "jp" ? "レポート有" : "report"}
                  </span>
                )}
              </span>
              <span className="theme-tile-cta">
                {lang === "jp" ? "開く →" : "Explore →"}
              </span>
            </div>
          </button>
        ))}
        {!items.length && (
          <div className="reports-empty">
            {lang === "jp" ? "該当するテーマがありません" : "No themes match"}
          </div>
        )}
      </div>
    </div>
  );
}

window.ThemesList = ThemesList;
