// Helm — 論點追蹤器。方法論改編自開源 equity-research thesis-tracker(Apache-2.0):
//   買進當下寫「為什麼買 + 什麼情況認錯出場」;之後每季覆核逐條標 強化/不變/減弱;賣出時結案復盤。
//   對治的是「事後說服自己續抱」——先寫下來,才有得誠實檢討。資料存後端「論點」表(不進 getData,開這頁才抓)。
(function () {
  const NS = window.HelmDesignSystem_9613a7;
  const { Field, Input, Button, EmptyState } = NS;

  const VERDICTS = ["強化", "不變", "減弱"];
  function vColor(v) { return v === "強化" ? "var(--status-success)" : v === "減弱" ? "var(--status-error)" : "var(--text-tertiary)"; }
  function inferMarket(code) { return /^\d{4,6}[A-Z]?$/.test(String(code).trim().toUpperCase()) ? "tw" : "us"; }

  // 常見原因選項(可多選;不知道術語沒關係,點了就學會)+ 其他自填。AddEdit 也共用(window.HelmThesisPresets)。
  const PRESETS = {
    buy: ["產業龍頭、市佔第一", "有護城河(品牌/技術/轉換成本)", "搭上長期大趨勢(AI、電動化…)", "獲利穩定、年年配息(存股)", "財報體質好(高 ROE、高毛利)", "大跌錯殺、比我的估值便宜", "指數化長期投資(ETF)", "看好新產品/新市場"],
    exit: ["毛利或獲利連兩季惡化", "市佔被對手侵蝕", "當初的成長理由消失", "跌破我設的停損價", "經營層誠信出問題", "人生需要用錢"],
    sell: ["出場條件觸發(照紀律執行)", "達到我的估值/目標價", "換到更好的標的", "論點被推翻(基本面變壞)", "人生需要現金", "情緒撐不住(誠實承認,下次改進)", "停損出場"],
  };
  function Chips({ options, value, onChange }) {
    return (
      <div style={{ display: "flex", flexWrap: "wrap", gap: 6, margin: "2px 0 8px" }}>
        {options.map(function (op) {
          var on = value.indexOf(op) >= 0;
          return (
            <button key={op} type="button" aria-pressed={on}
              onClick={function () { onChange(on ? value.filter(function (x) { return x !== op; }) : value.concat([op])); }}
              style={{
                borderRadius: 999, padding: "5px 11px", fontSize: 12.5, lineHeight: 1.3, cursor: "pointer",
                border: "1px solid " + (on ? "var(--accent-brass, #b9965a)" : "var(--border-subtle, rgba(128,128,128,.3))"),
                background: on ? "color-mix(in srgb, var(--accent-brass, #b9965a) 18%, transparent)" : "var(--surface-sunken)",
                color: on ? "var(--text-primary)" : "var(--text-secondary)", fontWeight: on ? 700 : 400,
              }}>{op}</button>
          );
        })}
      </div>
    );
  }
  function joinReason(chips, text) { var parts = chips.slice(); if (String(text || "").trim()) parts.push(String(text).trim()); return parts.join("、"); }
  window.HelmThesisPresets = { PRESETS: PRESETS, Chips: Chips, joinReason: joinReason };

  function EventRow({ ev, onDelete }) {
    return (
      <div style={{ display: "flex", gap: 10, padding: "8px 0", borderBottom: "1px solid var(--border-subtle, rgba(128,128,128,.15))" }}>
        <div style={{ flexShrink: 0, width: 64 }}>
          <div className="t-caption t-num">{String(ev.date || "").slice(0, 10)}</div>
          <div style={{ fontSize: 12, fontWeight: 700, color: ev.kind === "結案" ? "var(--accent-brass, #b9965a)" : "var(--text-secondary)" }}>{ev.kind}</div>
        </div>
        <div style={{ flex: 1, fontSize: 13, lineHeight: 1.6 }}>
          <div>{ev.text}</div>
          {ev.note && (
            ev.kind === "覆核"
              ? <div style={{ marginTop: 2, fontWeight: 700, color: vColor(ev.note) }}>判定:{ev.note}</div>
              : <div className="t-caption" style={{ marginTop: 2 }}>{ev.kind === "買進" ? "出場條件:" : "結果:"}{ev.note}</div>
          )}
        </div>
        <button type="button" aria-label="刪除這筆" onClick={onDelete}
          style={{ flexShrink: 0, background: "none", border: "none", color: "var(--text-tertiary)", fontSize: 14, padding: 2, cursor: "pointer" }}>×</button>
      </div>
    );
  }

  function MiniForm({ kind, onSubmit, onCancel }) {
    const [text, setText] = React.useState("");
    const [note, setNote] = React.useState(kind === "覆核" ? "不變" : "");
    const [chips, setChips] = React.useState([]);
    const [busy, setBusy] = React.useState(false);
    function content() { return kind === "結案" ? joinReason(chips, text) : text.trim(); }
    return (
      <div style={{ marginTop: 8, padding: 10, borderRadius: 10, background: "var(--surface-sunken)" }}>
        {kind === "覆核" && (
          <div className="fire-seg" role="tablist" style={{ marginBottom: 8 }}>
            {VERDICTS.map(function (v) {
              return <button key={v} type="button" role="tab" aria-selected={note === v} className={"fire-seg__btn" + (note === v ? " is-on" : "")} onClick={function () { setNote(v); }}>{v}</button>;
            })}
          </div>
        )}
        {kind === "結案" && (
          <React.Fragment>
            <div className="t-caption" style={{ marginBottom: 4 }}>為什麼賣?(常見原因,可多選)</div>
            <Chips options={PRESETS.sell} value={chips} onChange={setChips} />
          </React.Fragment>
        )}
        <Field label={kind === "覆核" ? "證據與心得(這季看到什麼?)" : "其他原因/復盤心得(選填)"}>
          <Input placeholder={kind === "覆核" ? "例:法說毛利續守 55%、產能滿載" : "用自己的話寫也完全可以"} value={text} onChange={function (e) { setText(e.target.value); }} />
        </Field>
        {kind === "結案" && (
          <Field label="結果(選填)">
            <Input placeholder="例:+18% 出場 / −12% 停損" value={note} onChange={function (e) { setNote(e.target.value); }} />
          </Field>
        )}
        <div style={{ display: "flex", gap: 8, marginTop: 8 }}>
          <Button size="sm" variant="primary" loading={busy} onClick={function () { var c = content(); if (!c || busy) return; setBusy(true); onSubmit(c, note); }}>{kind === "覆核" ? "記錄覆核" : "結案"}</Button>
          <Button size="sm" variant="ghost" onClick={onCancel}>取消</Button>
        </div>
      </div>
    );
  }

  function ThesisScreen({ onClose, onOpenStock }) {
    const HD = window.HelmData || {};
    const [events, setEvents] = React.useState(null);   // null=載入中
    const [form, setForm] = React.useState(null);       // {code, kind} 開啟中的迷你表單
    const [adding, setAdding] = React.useState(false);
    const [nCode, setNCode] = React.useState(""); const [nName, setNName] = React.useState("");
    const [nText, setNText] = React.useState(""); const [nExit, setNExit] = React.useState("");
    const [nBuyChips, setNBuyChips] = React.useState([]); const [nExitChips, setNExitChips] = React.useState([]);
    const [busy, setBusy] = React.useState(false);

    function load() { if (HD.listThesis) HD.listThesis().then(function (rows) { setEvents(rows || []); }); }
    React.useEffect(load, []);

    // 依代號分組,組內按日期排;有「結案」者沉底
    const groups = React.useMemo(function () {
      const m = {};
      (events || []).forEach(function (ev) { (m[ev.code] = m[ev.code] || []).push(ev); });
      return Object.keys(m).map(function (code) {
        const list = m[code].slice().sort(function (a, b) { return String(a.date).localeCompare(String(b.date)); });
        const closed = list.some(function (e) { return e.kind === "結案"; });
        const last = list[list.length - 1];
        return { code: code, name: (list.find(function (e) { return e.name; }) || {}).name || "", market: last.market || inferMarket(code), list: list, closed: closed, lastDate: last.date };
      }).sort(function (a, b) { return (a.closed === b.closed) ? String(b.lastDate).localeCompare(String(a.lastDate)) : (a.closed ? 1 : -1); });
    }, [events]);

    // 提醒:超過 ~100 天沒覆核的持有中論點(一季一次的紀律)
    function staleDays(g) {
      const lastRel = g.list.filter(function (e) { return e.kind !== "結案"; }).pop();
      if (!lastRel) return 0;
      return Math.round((Date.now() - new Date(String(lastRel.date).replace(/\//g, "-")).getTime()) / 86400000);
    }

    function submitEvent(g, kind, text, note) {
      HD.addThesis({ code: g.code, name: g.name, market: g.market, kind: kind, text: text, note: note }).then(function (res) {
        setForm(null);
        if (res && res.ok) load(); else window.alert("儲存失敗(網路或後端沒回應),請再試一次。");
      });
    }
    function addNew() {
      var buyTxt = joinReason(nBuyChips, nText), exitTxt = joinReason(nExitChips, nExit);
      if (busy || !nCode.trim() || !buyTxt) return;
      setBusy(true);
      HD.addThesis({ code: nCode.trim().toUpperCase(), name: nName.trim(), market: inferMarket(nCode), kind: "買進", text: buyTxt, note: exitTxt })
        .then(function (res) {
          setBusy(false);
          if (res && res.ok) { setAdding(false); setNCode(""); setNName(""); setNText(""); setNExit(""); setNBuyChips([]); setNExitChips([]); load(); }
          else window.alert("儲存失敗(網路或後端沒回應),請再試一次。");
        });
    }
    function delEvent(ev) {
      if (!window.confirm("刪除這筆紀錄?(填錯才刪;正常流程請用覆核/結案留下軌跡)")) return;
      HD.deleteThesis(ev._row).then(load);
    }

    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">
            <div className="fpage__body">

              <section className="fpage__card">
                <div className="fpage__card-head"><span className="t-overline">為什麼要寫下來</span></div>
                <div className="fire-desc">
                  <p>買進當下寫兩件事:<b>為什麼買</b>、<b>什麼情況我會認錯出場</b>。之後每季覆核一次,逐條標「強化/不變/減弱」——鐵則:<b>找反面證據要跟找正面證據一樣認真</b>。這是對治「事後說服自己續抱」最有效的紀律。</p>
                </div>
                {!adding ? (
                  <Button variant="primary" size="sm" onClick={function () { setAdding(true); }}>＋ 建立論點</Button>
                ) : (
                  <div style={{ marginTop: 4 }}>
                    <div className="fpage__fields">
                      <Field label="代號" hint="台股數字(2330)、美股英文(AAPL);市場自動判斷">
                        <Input placeholder="例:2330" value={nCode} onChange={function (e) { setNCode(e.target.value); }} />
                      </Field>
                      <Field label="名稱(選填)"><Input placeholder="例:台積電" value={nName} onChange={function (e) { setNName(e.target.value); }} /></Field>
                      <div className="t-caption" style={{ margin: "6px 0 2px" }}>為什麼買?(常見理由,可多選;不知道術語點這裡就好)</div>
                      <Chips options={PRESETS.buy} value={nBuyChips} onChange={setNBuyChips} />
                      <Field label="其他理由(選填)" hint="用自己的話寫也完全可以;重點是「可被驗證」,別寫「感覺會漲」">
                        <Input placeholder="例:AI 需求撐三年產能" value={nText} onChange={function (e) { setNText(e.target.value); }} />
                      </Field>
                      <div className="t-caption" style={{ margin: "10px 0 2px" }}>什麼情況代表我錯了?(出場條件,可多選)</div>
                      <Chips options={PRESETS.exit} value={nExitChips} onChange={setNExitChips} />
                      <Field label="其他條件(選填)" hint="趁現在冷靜寫——套牢時的你不會想寫這條">
                        <Input placeholder="例:毛利連兩季 <50% 就重評" value={nExit} onChange={function (e) { setNExit(e.target.value); }} />
                      </Field>
                    </div>
                    <div style={{ display: "flex", gap: 8, marginTop: 8 }}>
                      <Button size="sm" variant="primary" loading={busy} onClick={addNew}>寫下論點</Button>
                      <Button size="sm" variant="ghost" onClick={function () { setAdding(false); }}>取消</Button>
                    </div>
                  </div>
                )}
              </section>

              {events == null && <p className="t-caption" style={{ padding: "0 4px" }}>載入中…</p>}
              {events != null && groups.length === 0 && (
                <EmptyState icon="ph-notebook" title="還沒有任何論點" body="從上面「＋建立論點」開始;新增持股時填的論點也會自動出現在這裡。" />
              )}

              {groups.map(function (g) {
                const sd = staleDays(g);
                return (
                  <section key={g.code} className="fpage__card" style={g.closed ? { opacity: 0.72 } : null}>
                    <div className="fpage__card-head">
                      <span className="t-overline">
                        <button type="button" onClick={function () { if (onOpenStock) onOpenStock(g.code, g.market); }}
                          style={{ background: "none", border: "none", padding: 0, font: "inherit", color: "inherit", cursor: "pointer", textDecoration: "underline", textUnderlineOffset: 3 }}>
                          {g.name || g.code}<span className="t-num" style={{ marginLeft: 6, color: "var(--text-tertiary)" }}>{g.code}</span>
                        </button>
                      </span>
                      <span className="fpage__card-hint">{g.closed ? "已結案" : "追蹤中"}</span>
                    </div>
                    {!g.closed && sd > 100 && (
                      <p className="t-caption" style={{ color: "var(--status-error)", marginBottom: 6 }}>⏰ 已 {sd} 天沒覆核——一季一次,去看看最新一季它還站不站得住。</p>
                    )}
                    <div>
                      {g.list.map(function (ev) { return <EventRow key={ev._row} ev={ev} onDelete={function () { delEvent(ev); }} />; })}
                    </div>
                    {!g.closed && (
                      form && form.code === g.code
                        ? <MiniForm kind={form.kind} onSubmit={function (text, note) { submitEvent(g, form.kind, text, note); }} onCancel={function () { setForm(null); }} />
                        : (
                          <div style={{ display: "flex", gap: 8, marginTop: 10 }}>
                            <Button size="sm" variant="secondary" onClick={function () { setForm({ code: g.code, kind: "覆核" }); }}>＋ 覆核</Button>
                            <Button size="sm" variant="ghost" onClick={function () { setForm({ code: g.code, kind: "結案" }); }}>結案</Button>
                          </div>
                        )
                    )}
                  </section>
                );
              })}

              <p className="t-caption" style={{ padding: "0 4px" }}>教材與紀律工具、非投資建議;方法論改編自 Apache-2.0 開源專案。</p>
            </div>
          </div>
        </div>
      </div>
    );
  }

  window.ThesisScreen = ThesisScreen;
})();
