// Helm — 交易紀錄:每筆買賣的歷史台帳(券商只給平均成本、沒有歷史)。
//   定期定額/衛星股都記:日期/股數/單價/總金額(可含手續費)→ 依代號分組時間軸 + 自算平均成本(移動加權,
//   同台灣券商口徑)+ 跟明細持股股數對帳。刪紀錄不反向改持股——紀錄是事實,持股以明細為準。
(function () {
  const NS = window.HelmDesignSystem_9613a7;
  const { Field, Input, Button } = NS;

  // 平均成本法(移動加權):買進加池、賣出按池均價出(單位成本不變);賣超過已記=歷史沒補完,掛旗
  function calcPool(rows) {
    var qty = 0, cost = 0, warn = false;
    rows.forEach(function (r) {
      if (r.act === "買") { cost += r.total; qty += r.qty; }
      else {
        var q = r.qty;
        if (q > qty + 1e-9) { warn = true; q = qty; }
        var avg = qty > 1e-9 ? cost / qty : 0;
        cost -= avg * q; qty -= q;
        if (qty < 1e-9) { qty = 0; cost = 0; }
      }
    });
    return { qty: Math.round(qty * 10000) / 10000, cost: cost, avg: qty > 1e-9 ? cost / qty : null, warn: warn };
  }
  function inferMarket(code) { return /^\d{4,6}[A-Z]?$/.test(String(code).trim().toUpperCase()) ? "tw" : "us"; }
  function fmtN(x, d) { return x == null ? "—" : Number(x).toLocaleString("en-US", { maximumFractionDigits: d == null ? 2 : d }); }

  function TxnScreen({ onClose, onOpenStock }) {
    const HD = window.HelmData || {};
    const DEMO = !!HD.DEMO;
    const [list, setList] = React.useState(null);   // null=載入中
    const [busyRow, setBusyRow] = React.useState(0);
    const [formOpen, setFormOpen] = React.useState(false);
    const [act, setAct] = React.useState("買");
    const [code, setCode] = React.useState("");
    const [name, setName] = React.useState("");
    const [qty, setQty] = React.useState("");
    const [price, setPrice] = React.useState("");
    const [total, setTotal] = React.useState("");
    const [date, setDate] = React.useState(new Date().toISOString().slice(0, 10));
    const [note, setNote] = React.useState("");
    const [posting, setPosting] = React.useState(false);
    const [msg, setMsg] = React.useState("");

    function load() {
      if (!HD.listTxn) { setList([]); return; }
      HD.listTxn().then(function (d) { setList(d || []); }).catch(function () { setList([]); });
    }
    React.useEffect(function () { load(); }, []);

    var qtyN = parseFloat(String(qty).replace(/,/g, "")) || 0;
    var priceN = parseFloat(String(price).replace(/,/g, "")) || 0;
    var totalN = parseFloat(String(total).replace(/,/g, "")) || 0;
    var codeU = String(code).trim().toUpperCase();
    var market = inferMarket(codeU);

    function submit() {
      if (!codeU || qtyN <= 0 || priceN < 0 || (priceN === 0 && totalN <= 0)) { setMsg("代號、股數、單價要填(總金額可選填)"); return; }
      setPosting(true); setMsg("");
      HD.addTxn({ date: date.replace(/-/g, "/"), code: codeU, name: name.trim(), market: market, act: act, qty: qtyN, price: priceN, total: total === "" ? "" : totalN, note: note.trim() })
        .then(function (r) {
          setPosting(false);
          if (r && (r.ok || (r.data && r.data.ok))) {
            setMsg("✓ 已記一筆"); setQty(""); setTotal(""); setNote("");
            load();
          } else setMsg("⚠️ 沒存成功,再試一次");
        }).catch(function () { setPosting(false); setMsg("⚠️ 網路問題,沒存成功"); });
    }

    function del(row) {
      if (!HD.deleteTxn) return;
      setBusyRow(row);
      HD.deleteTxn(row).then(function () { setBusyRow(0); load(); }).catch(function () { setBusyRow(0); });
    }

    // 依 代號+市場 分組;組內依日期升冪算池、顯示時降冪(最新在上)
    var groups = null;
    if (list) {
      var map = {};
      list.forEach(function (t) {
        var k = t.market + ":" + t.code;
        (map[k] = map[k] || []).push(t);
      });
      groups = Object.keys(map).map(function (k) {
        var rows = map[k].slice().sort(function (a, b) { return a.date === b.date ? a._row - b._row : (a.date < b.date ? -1 : 1); });
        var pool = calcPool(rows);
        var nm = ""; for (var i = rows.length - 1; i >= 0; i--) { if (rows[i].name) { nm = rows[i].name; break; } }
        // 對帳:明細持股欄的股數(同代號;台股 ticker 可能帶 .TW)
        var held = null;
        var assets = (window.HELM && window.HELM.assets) || [];
        for (var j = 0; j < assets.length; j++) {
          var tk = String(assets[j].ticker || "").toUpperCase().replace(/\.TW$/, "");
          if (tk && tk === rows[0].code) { held = assets[j].shares || 0; break; }
        }
        return { key: k, code: rows[0].code, market: rows[0].market, name: nm, rows: rows, pool: pool, held: held };
      }).sort(function (a, b) { return (b.rows[b.rows.length - 1].date || "").localeCompare(a.rows[a.rows.length - 1].date || ""); });
    }

    var ccyOf = function (mk) { return mk === "us" ? "美元" : "元"; };

    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">
              <p className="stk-note" style={{ marginTop: 0 }}>每筆買賣的歷史台帳——券商只給你「平均成本」,這裡留下<b>每一筆買在什麼位階</b>。在明細點持股 → 按「買進/賣出」記一筆,股數自動更新、這裡自動進帳;舊的歷史可以在下面照券商 App 補登。{DEMO && <b>(展示版:示範資料,操作不落地。)</b>}</p>
              <button type="button" className="stk-prof__refresh" onClick={function () { setFormOpen(!formOpen); }}>
                {formOpen ? "收起補登表單 ▴" : "補登一筆(照券商紀錄抄)▾"}
              </button>
              {formOpen && (
                <div style={{ marginTop: 10 }}>
                  <div className="stk-ai__btns" style={{ marginBottom: 8 }}>
                    <button type="button" className={act === "買" ? "stk-ai__go" : "stk-ai__cancel"} onClick={function () { setAct("買"); }}>買進</button>
                    <button type="button" className={act === "賣" ? "stk-ai__go" : "stk-ai__cancel"} onClick={function () { setAct("賣"); }}>賣出</button>
                  </div>
                  <Field label="股票代號"><Input placeholder="例:0050、TSLA" value={code} onChange={function (e) { setCode(e.target.value); }} /></Field>
                  <Field label="名稱(選填)"><Input placeholder="例:元大台灣50" value={name} onChange={function (e) { setName(e.target.value); }} /></Field>
                  <Field label="日期"><Input type="date" value={date} onChange={function (e) { setDate(e.target.value); }} /></Field>
                  <Field label="股數"><Input inputMode="decimal" placeholder={market === "us" ? "美股可含小數(碎股)" : "例:1000(零股照填)"} value={qty} onChange={function (e) { setQty(e.target.value); }} /></Field>
                  <Field label={"單價(" + ccyOf(market) + ")"}><Input inputMode="decimal" placeholder="成交價" value={price} onChange={function (e) { setPrice(e.target.value); }} /></Field>
                  <Field label={"總金額(選填," + ccyOf(market) + ")"} hint="填券商實際扣款金額(含手續費)對帳最準;不填就用 股數×單價">
                    <Input inputMode="decimal" placeholder={qtyN > 0 && priceN > 0 ? "不填=" + fmtN(qtyN * priceN) : ""} value={total} onChange={function (e) { setTotal(e.target.value); }} />
                  </Field>
                  <Field label="附註(選填)"><Input placeholder="例:定期定額、加碼" value={note} onChange={function (e) { setNote(e.target.value); }} /></Field>
                  <Button variant="primary" size="sm" onClick={submit} disabled={posting}>{posting ? "存檔中…" : "記這一筆"}</Button>
                  {msg && <p className="stk-ai__warn" style={{ marginTop: 8 }}>{msg}</p>}
                </div>
              )}
            </section>

            {list == null ? (
              <div className="fx-now"><span className="fx-now__unit">載入中</span><span className="fx-now__rate">…</span></div>
            ) : groups.length === 0 ? (
              <section className="fpage__card"><div className="fire-desc"><p>還沒有任何紀錄。兩個入口:①<b>明細 → 點持股 → 記一筆買賣</b>(順手記,股數自動更新);②上面的<b>補登</b>(把過去定期定額的歷史照券商 App 抄進來)。</p></div></section>
            ) : (
              groups.map(function (g) {
                var p = g.pool;
                var mismatch = g.held != null && Math.abs((g.held || 0) - p.qty) > 1e-6;
                return (
                  <section key={g.key} className="fpage__card">
                    <div className="fpage__card-head">
                      <button type="button" onClick={function () { if (onOpenStock) onOpenStock(g.code, g.market); }}
                        style={{ background: "none", border: "none", padding: 0, cursor: "pointer", color: "inherit", font: "inherit", textAlign: "left" }}>
                        <span className="t-overline">{g.name || g.code}<span className="t-num" style={{ marginLeft: 6, color: "var(--text-tertiary)" }}>{g.code}{g.market === "us" ? " · 美股" : ""}</span></span>
                      </button>
                      <span className="fpage__card-hint">{g.rows.length} 筆</span>
                    </div>
                    <div className="fx-now" style={{ marginBottom: 6 }}>
                      <span className="fx-now__unit">自算平均成本(已記的 {fmtN(p.qty, 4)} 股)</span>
                      <span className="fx-now__rate t-num">{p.avg != null ? fmtN(p.avg) + " " + ccyOf(g.market) : "—"}</span>
                    </div>
                    {p.warn && <p className="stk-ai__warn" style={{ marginBottom: 6 }}>⚠️ 有賣出超過已記買進的紀錄——歷史還沒補完,平均成本僅供參考。</p>}
                    {mismatch && <p className="stk-ai__warn" style={{ marginBottom: 6 }}>對帳:明細持股是 {fmtN(g.held, 4)} 股、這裡只記到 {fmtN(p.qty, 4)} 股——差的那段多半是還沒補登的舊紀錄。</p>}
                    {g.rows.slice().reverse().map(function (t) {
                      return (
                        <div key={t._row} style={{ display: "flex", alignItems: "baseline", gap: 8, padding: "8px 0", borderTop: "1px solid rgba(128,128,128,0.18)" }}>
                          <span style={{ fontSize: 12.5, color: "var(--text-tertiary)", flexShrink: 0 }} className="t-num">{t.date}</span>
                          <span style={{ fontWeight: 700, color: t.act === "買" ? "var(--status-success)" : "var(--value-negative)", flexShrink: 0 }}>{t.act}</span>
                          <span className="t-num" style={{ fontSize: 13.5 }}>{fmtN(t.qty, 4)} 股 @ {fmtN(t.price)}</span>
                          <span className="t-num" style={{ marginLeft: "auto", fontSize: 13, color: "var(--text-secondary)", flexShrink: 0 }}>{g.market === "us" ? "US$" : ""}{fmtN(t.total)}</span>
                          {!DEMO && <button type="button" aria-label="刪除" onClick={function () { del(t._row); }} disabled={busyRow === t._row}
                            style={{ background: "none", border: "none", cursor: "pointer", opacity: 0.4, fontSize: 15, padding: "0 2px", color: "inherit", flexShrink: 0 }}>
                            <i className="ph ph-x" aria-hidden="true" />
                          </button>}
                        </div>
                      );
                    })}
                    {g.rows.some(function (t) { return t.note; }) && (
                      <p className="cc-note" style={{ marginTop: 6 }}>{g.rows.filter(function (t) { return t.note; }).slice(-2).map(function (t) { return t.date + ":" + t.note; }).join(" · ")}</p>
                    )}
                  </section>
                );
              })
            )}

            <section className="fpage__card">
              <div className="fpage__card-head"><span className="t-overline">跟券商對不上?常見原因</span></div>
              <div className="fire-desc">
                <p><b>①手續費口徑</b>:總金額沒填「實際扣款」時,這裡用 股數×單價,少了手續費(台股 0.1425%、最低 1 元)與賣出證交稅 0.3%。<b>②股利再投入</b>:配股/股利再買的那些股,券商算進成本、這裡要自己補一筆才會有。<b>③舊紀錄沒補完</b>:上面對帳提示會告訴你差幾股。刻意不硬湊——<b>數字對不上時,知道為什麼對不上,比假裝對上有用</b>。</p>
              </div>
            </section>

            <p className="t-caption" style={{ padding: "0 4px" }}>台帳只記事實、不評價;刪紀錄不會反向修改明細持股。非投資建議。</p>
          </div></div>
        </div>
      </div>
    );
  }

  window.TxnScreen = TxnScreen;
})();
