// Helm — 流派觀察名單(台股)。讀靜態 watchlist.json(離線由 scripts/gen-watchlist.js 用同一引擎算好),
//   分 品質/成長/價值/存股 四派,點任一檔 → 開個股健檢。教材型、非投資建議。
(function () {
  const DOT = { green: "var(--value-positive)", yellow: "var(--accent-brass)", red: "var(--value-negative)", gray: "var(--text-tertiary)" };
  function Dot({ light }) { return <span style={{ display: "inline-block", width: 10, height: 10, borderRadius: "50%", background: DOT[light] || DOT.gray, flexShrink: 0 }} />; }
  const ORDER = ["quality", "growth", "value", "dividend", "finance"];
  // 估值位階白話:用絕對本益比帶(沒有個股10年位階資料時的誠實版)——只對「偏貴」示警,提醒好公司≠好價格
  function valNote(p) {
    if (p.pe == null || !(p.pe > 0)) return null;
    if (p.pe > 40) return "本益比 " + p.pe + " 倍偏很高 —— 市場給它很高的成長期待,成長一放緩就容易修正,別追在最熱的時候";
    if (p.pe > 25) return "本益比 " + p.pe + " 倍偏高 —— 有成長溢價,好公司也可能買在貴價位";
    return null;
  }
  // 獲利在衰退 → 高殖利率可能是股價跌出來的(存股派最容易踩的坑)
  function epsNote(p) {
    return (p.epsYoY != null && p.epsYoY < 0) ? "但 EPS 年減 " + Math.abs(Math.round(p.epsYoY)) + "% —— 獲利在衰退,高殖利率可能是股價跌出來的,點進去看是不是在吃老本" : null;
  }
  var _wlData = null, _wlScroll = 0;   // 模組層:快取名單 + 記住捲動位置,撐過 unmount(返回時即時還原)

  // 迷你回測預覽:點開即時抓 10 年、跑定期定額、跟大盤比(報酬%與金額無關,故只顯示%)。教材、非投資建議。
  function MiniBacktest({ code, market }) {
    const B = window.HelmBacktest;
    const [open, setOpen] = React.useState(false);
    const [data, setData] = React.useState(null);
    const [loading, setLoading] = React.useState(false);
    const [err, setErr] = React.useState(false);
    const [years, setYears] = React.useState(10);
    function load() {
      if (data || loading) return;
      var getter = market === "us" ? (window.HelmStockData && window.HelmStockData.getUsBacktest) : (window.HelmStockData && window.HelmStockData.getBacktest);
      if (!getter) { setErr(true); return; }
      setLoading(true);
      getter(code).then(function (d) { setLoading(false); if (!d || !d.ok) { setErr(true); return; } setData(d); }).catch(function () { setLoading(false); setErr(true); });
    }
    function toggle() { var n = !open; setOpen(n); if (n) load(); }
    var r = null;
    if (data && B && data.prices && data.prices.length) {
      var last = data.prices[data.prices.length - 1].date;
      var startDate = (Number(last.slice(0, 4)) - years) + last.slice(4);
      var s = B.dca(data.prices, 10000, startDate);
      var bch = B.dca(data.bench, 10000, startDate);
      if (s) r = { ret: s.ret, bret: bch ? bch.ret : null, benchIsSelf: data.benchIsSelf, yrs: Math.round(B.monthsBetween(s.startDate, last) / 12 * 10) / 10 };
    }
    var benchName = market === "us" ? "S&P 500" : "0050";
    return (
      <div className="wl-mini">
        <button type="button" className="wl-mini__toggle" onClick={toggle} aria-expanded={open}>
          <i className="ph ph-clock-counter-clockwise" aria-hidden="true" /> 回測:早幾年買的話? <i className={"ph " + (open ? "ph-caret-up" : "ph-caret-down")} aria-hidden="true" />
        </button>
        {open && (
          <div className="wl-mini__body">
            {loading && <span className="wl-mini__msg">抓 10 年歷史中…</span>}
            {err && <span className="wl-mini__msg">歷史資料不足或抓取失敗,點進健檢看完整回測。</span>}
            {r && (
              <div>
                <div className="wl-mini__segs">{[1, 3, 5, 10].map(function (y) { var dis = data.availYears >= 2 && y > data.availYears; return <button key={y} type="button" disabled={dis} className={"wl-mini__seg" + (years === y ? " is-on" : "")} onClick={function () { setYears(y); }}>{y} 年</button>; })}</div>
                <div className="wl-mini__stat"><span>近 {r.yrs} 年每月定額,這檔</span><b className={r.ret >= 0 ? "fx-pl--up" : "fx-pl--down"}>{r.ret >= 0 ? "+" : ""}{Math.round(r.ret * 100)}%</b></div>
                {!r.benchIsSelf && r.bret != null && <div className="wl-mini__stat wl-mini__stat--bench"><span>同期大盤 {benchName}</span><b>{r.bret >= 0 ? "+" : ""}{Math.round(r.bret * 100)}%</b></div>}
                <p className="wl-mini__note">{(!r.benchIsSelf && r.bret != null) ? (r.ret > r.bret ? "這檔過去贏大盤,但你當年挑不中、過去也 ≠ 未來。" : "這檔過去還輸大盤——多數個股長期贏不了指數。") : "過去績效不代表未來。"} 教材、非投資建議。</p>
              </div>
            )}
          </div>
        )}
      </div>
    );
  }

  function WatchlistScreen({ onClose, onOpenStock }) {
    const [data, setData] = React.useState(_wlData);
    const [err, setErr] = React.useState(null);
    const [watchTick, setWatchTick] = React.useState(0);
    function toggleWatch(code, name) {
      if (!window.HelmWatch) return;
      if (window.HelmWatch.has(code)) window.HelmWatch.remove(code);
      else window.HelmWatch.add(code, name, "tw");
      setWatchTick(function (t) { return t + 1; });
    }
    const scrollRef = React.useRef(null);
    const restoredRef = React.useRef(false);
    React.useEffect(function () {
      fetch("watchlist.json?v=147").then(function (r) { return r.json(); }).then(function (d) { _wlData = d; setData(d); }).catch(function (e) { setErr(String((e && e.message) || e)); });
    }, []);
    React.useLayoutEffect(function () {
      if (!restoredRef.current && data && scrollRef.current) { scrollRef.current.scrollTop = _wlScroll; restoredRef.current = true; }
    }, [data]);

    return (
      <div className="fpage" role="dialog" aria-modal="true" aria-label="流派觀察名單">
        <div className="fpage__panel">
          <header className="fpage__bar">
            <button className="fpage__cancel" onClick={onClose}><i className="ph ph-arrow-left" aria-hidden="true" />返回</button>
            <span className="fpage__title">流派觀察名單</span>
            <span aria-hidden="true" />
          </header>
          <div className="fpage__scroll" ref={scrollRef} onScroll={function (e) { _wlScroll = e.currentTarget.scrollTop; }}>
            <div className="fpage__body">
              <section className="fpage__card">
                <p className="prot-sum__note">四種投資流派各自會挑什麼股票——<b>給新手觀察學習,不是推薦買進</b>。點任一檔看完整健檢。{data ? <>資料 {data.asOf} · 篩選 {data.scored} 檔知名股。</> : null}</p>
                <p className="wl-legend"><b>左邊圓點＝健檢綜合燈號</b>:<span className="wl-legend__i"><Dot light="green" />好且不算貴</span><span className="wl-legend__i"><Dot light="yellow" />及格、有要注意的</span><span className="wl-legend__i"><Dot light="red" />有明顯弱點</span>。右邊數字＝健檢總分(60+ 算不錯、40 出頭代表只是「符合這派某一條」、其他面向偏弱)。<b>被選進名單 ≠ 高分</b>,綠燈很稀有是正常的,點進去看細項才準。</p>
                <p className="wl-howto">💡 <b>建議用法:</b>挑一個你看得懂的產業,點兩三檔比較它們的健檢差在哪、當作練習看財報——<b>不是從這裡挑一檔買</b>。真要投入前,先回首頁看你的整體資產 / 緊急預備金夠不夠。</p>
              </section>

              {err && <section className="fpage__card"><div className="fx-advice fx-advice--mid"><span className="fx-advice__txt">⚠️ 名單載入失敗:{err}</span></div></section>}
              {!data && !err && <section className="fpage__card"><div className="fx-now"><span className="fx-now__unit">載入名單中</span><span className="fx-now__rate">…</span></div></section>}

              {data && ORDER.map(function (key) {
                const st = data.styles[key];
                if (!st) return null;
                return (
                  <section key={key} className="fpage__card wl-style">
                    <div className="wl-style__head">
                      <i className={"ph " + st.icon} aria-hidden="true" />
                      <span className="wl-style__label">{st.label}</span>
                      <span className="wl-style__sub">{st.sub}</span>
                    </div>
                    <p className="wl-style__blurb">{st.blurb}</p>
                    <div className="wl-picks">
                      {st.picks.length === 0
                        ? <div className="wl-empty">本輪沒有符合的(門檻嚴、寧缺勿濫)</div>
                        : st.picks.map(function (p) {
                          var watched = !!(window.HelmWatch && window.HelmWatch.has(p.code));
                          return (
                            <div key={p.code} className="wl-pick">
                              <div className="wl-pick__row">
                              <button type="button" className="wl-pick__main" onClick={function () { onOpenStock(p.code); }}>
                                <Dot light={p.light} />
                                <span className="wl-pick__l">
                                  <span className="wl-pick__name">{p.name}<span className="wl-pick__code t-num">{p.code}</span>{p.overall != null && <span className={"wl-pick__score wl-pick__score--" + (p.light || "gray")}>{p.overall}</span>}{p.unreliable && <span className="wl-pick__warn">不給綠燈</span>}</span>
                                  <span className="wl-pick__why">{p.why}</span>
                                  {valNote(p) && <span className="wl-pick__note">{valNote(p)}</span>}
                                  {epsNote(p) && <span className="wl-pick__note wl-pick__note--warn">⚠️ {epsNote(p)}</span>}
                                </span>
                                <span className="wl-pick__pricecol">
                                  <span className="wl-pick__price t-num" style={{ color: p.changePct > 0 ? "var(--value-negative)" : p.changePct < 0 ? "var(--value-positive)" : "var(--text-primary)" }}>{p.price != null ? p.price : "—"}</span>
                                  {p.changePct != null && <span className="wl-pick__chg t-num" style={{ color: p.changePct > 0 ? "var(--value-negative)" : p.changePct < 0 ? "var(--value-positive)" : "var(--text-tertiary)" }}>今日 {p.changePct > 0 ? "+" : ""}{p.changePct}%</span>}
                                </span>
                                <i className="ph ph-caret-right wl-pick__chev" aria-hidden="true" />
                              </button>
                              <button type="button" className={"wl-pick__star" + (watched ? " is-on" : "")} onClick={function () { toggleWatch(p.code, p.name); }} aria-pressed={watched} aria-label={watched ? "已在觀察清單,點擊移除" : "加入觀察清單"} title={watched ? "已在觀察清單" : "加入觀察清單"}>
                                <i className="ph ph-star" aria-hidden="true" />
                              </button>
                              </div>
                              <MiniBacktest code={p.code} market="tw" />
                            </div>
                          );
                        })}
                    </div>
                    {st.picks.length === 1 && <p className="wl-scarce">⚠️ 這派目前只篩到 1 檔——代表現在「又符合這派、又不是地雷」的標的很稀少,這是市場現況,不是叫你非買這檔不可。</p>}
                  </section>
                );
              })}

              {data && data.excluded && data.excluded.length > 0 && (
                <section className="fpage__card stk-disclaim">
                  <div className="fpage__card-head"><span className="t-overline"><i className="ph ph-warning" aria-hidden="true" /> 為什麼有些股沒入選(教學)</span></div>
                  <p className="stk-note">看起來便宜 ≠ 值得買。最常見陷阱是<b>景氣循環股在獲利高峰</b>:低本益比、高獲利,其實往往是該賣的訊號。點進去看健檢的警語。</p>
                  <div className="wl-excl">
                    {data.excluded.map(function (e) {
                      return (
                        <button key={e.code} type="button" className="wl-excl__row" onClick={function () { onOpenStock(e.code); }}>
                          <span className="wl-excl__name">{e.name}<span className="t-num"> {e.code}</span></span>
                          <span className="wl-excl__reason">{e.reason}</span>
                        </button>
                      );
                    })}
                  </div>
                </section>
              )}

              <section className="fpage__card stk-disclaim">
                <p className="stk-note">名單由規則引擎自動產生(與「個股健檢」同一套評分),從約 30 檔知名股篩出、定期更新。<b>不構成投資建議</b>;流派分類是教學用的概略歸類,實際投資前請看完整健檢、並衡量自身風險承受度。</p>
              </section>
            </div>
          </div>
        </div>
      </div>
    );
  }

  window.WatchlistScreen = WatchlistScreen;
})();
