// Helm — 現金流(收入 / 支出 / 投入 三段)。
// 觀念:支出=花掉就沒了;投入=把錢搬成資產(淨值沒減)。貸款月付由後端自動帶入支出。
(function () {
  const NS = window.HelmDesignSystem_9613a7;
  const { Card, AmountDisplay, Button, Input } = NS;

  function fmt(n) { return Math.round(n || 0).toLocaleString("en-US"); }
  function num(v) { return parseFloat(String(v).replace(/,/g, "")) || 0; }
  function monthsToYM(m) {
    const d = new Date(); const t = d.getFullYear() * 12 + d.getMonth() + (m || 0);
    return Math.floor(t / 12) + "/" + ("0" + (t % 12 + 1)).slice(-2);
  }
  function shortDate(s) { const m = String(s || "").match(/(\d{4})[\/\-](\d{1,2})[\/\-](\d{1,2})/); return m ? (Number(m[2]) + "/" + Number(m[3])) : ""; }
  const PH = { "收入": "例:薪水", "支出": "例:信用卡帳單 / 孝親費", "投入": "例:定期定額 0050" };
  const SIGN = { "收入": "+", "支出": "−", "投入": "→" };
  const TONE = { "收入": "pos", "支出": "neg", "投入": "inv" };

  // 分類:只有收入/支出分組(投入本來就乾淨)。編輯時可點選;沒選的用名稱關鍵字自動猜,馬上就有結構、不用回頭逐筆貼標。
  const CF_CATS = {
    "支出": ["居住", "飲食", "交通", "孝親", "保險", "訂閱通訊", "醫療", "教育", "娛樂", "其他"],
    "收入": ["薪資", "獎金", "副業", "投資收益", "租金", "其他"],
  };
  const CAT_COLORS = ["var(--c-alloc-1)", "var(--c-alloc-2)", "var(--c-alloc-3)", "var(--c-alloc-4)", "var(--c-alloc-5)", "var(--c-alloc-6)"];
  function guessCat(name, kind) {
    const n = String(name || "");
    if (kind === "支出") {
      if (/房租|房貸|租金|水電|電費|台電|瓦斯|管理費|物業|水費/.test(n)) return "居住";
      if (/孝親|父母|奉養|爸|媽/.test(n)) return "孝親";
      if (/保險|保費|壽險|醫療險|車險|意外險|實支|長照/.test(n)) return "保險";
      if (/餐|飲食|吃|伙食|食材|外食|便當|咖啡|早午晚/.test(n)) return "飲食";
      if (/油錢|加油|停車|捷運|高鐵|交通|火車|公車|計程|車貸|機車|ETC/i.test(n)) return "交通";
      if (/訂閱|netflix|spotify|youtube|手機|電話|網路|通訊|月租|disney|icloud|chatgpt|claude/i.test(n)) return "訂閱通訊";
      if (/醫|健保|看診|藥|診所|牙/.test(n)) return "醫療";
      if (/學費|補習|教育|課程|才藝|書/.test(n)) return "教育";
      if (/娛樂|遊戲|電影|旅遊|健身|追劇/.test(n)) return "娛樂";
      return "其他";
    }
    if (kind === "收入") {
      if (/薪|月薪|工資|本薪|底薪/.test(n)) return "薪資";
      if (/獎金|年終|分紅|三節|績效/.test(n)) return "獎金";
      if (/副業|外快|接案|兼職|稿費|外包/.test(n)) return "副業";
      if (/股息|利息|配息|股利|投資|債息/.test(n)) return "投資收益";
      if (/租金|出租|包租/.test(n)) return "租金";
      return "其他";
    }
    return "";
  }
  function catOf(r, kind) { return (r.category && String(r.category).trim()) || guessCat(r.name, kind); }
  // 把某段的列依分類分組(支出順帶把貸款自動列併成「貸款」組);回 {cats:[{cat,rows,sum,color,auto}], segments}
  function cfBreakdown(rows, kind, loans) {
    const map = {};
    (rows || []).forEach((r) => {
      const c = catOf(r, kind);
      (map[c] = map[c] || { cat: c, rows: [], sum: 0, auto: false }).rows.push(r);
      map[c].sum += Number(r.monthly) || 0;
    });
    let cats = Object.keys(map).map((k) => map[k]);
    if (loans && loans.length) {
      const ls = loans.reduce((s, l) => s + (Number(l.monthly) || 0), 0);
      if (ls > 0) cats.push({ cat: "貸款", rows: loans, sum: ls, auto: true });
    }
    cats.sort((a, b) => b.sum - a.sum);
    cats.forEach((g, i) => { g.color = CAT_COLORS[i % CAT_COLORS.length]; });
    return { cats: cats, segments: cats.map((g) => ({ label: g.cat, value: g.sum, color: g.color })) };
  }

  // 使用者自訂的分類清單(存跨裝置偏好 helm-cf-cats;沒設過用內建預設)
  function loadCats() {
    try {
      const raw = window.HelmPrefs && window.HelmPrefs.get("helm-cf-cats");
      if (raw) { const p = JSON.parse(raw); return { "支出": (p["支出"] && p["支出"].length) ? p["支出"] : CF_CATS["支出"].slice(), "收入": (p["收入"] && p["收入"].length) ? p["收入"] : CF_CATS["收入"].slice() }; }
    } catch (e) {}
    return { "支出": CF_CATS["支出"].slice(), "收入": CF_CATS["收入"].slice() };
  }

  // 分類管理面板:改名(輸入框失焦即套用)、刪除(🗑,旁邊數字=使用筆數)、新增。改名/刪除會連動後端重整項目。
  function CatManager(props) {
    const kind = props.kind, list = props.list;
    const [drafts, setDrafts] = React.useState(function () { return list.slice(); });
    const [adding, setAdding] = React.useState("");
    const [busy, setBusy] = React.useState(false);
    React.useEffect(function () { setDrafts(list.slice()); }, [list.join("|")]);
    const items = (window.HELM && window.HELM.cashflow) ? (kind === "收入" ? window.HELM.cashflow.income : window.HELM.cashflow.expense) : [];
    function usedCount(name) { return items.filter(function (x) { return String(x.category || "").trim() === name; }).length; }
    function run(pr) { setBusy(true); Promise.resolve(pr).then(function () { setBusy(false); }, function () { setBusy(false); }); }
    function commitRename(i) {
      const nm = String(drafts[i] || "").trim(), old = list[i];
      if (!nm || nm === old || list.indexOf(nm) >= 0) { setDrafts(list.slice()); return; }   // 空/沒改/重名 → 還原
      run(props.onRename(kind, old, nm));
    }
    function add() { const nm = adding.trim(); if (!nm || list.indexOf(nm) >= 0) return; run(props.onAdd(kind, nm)); setAdding(""); }
    return (
      <div className="cf-catmgr">
        {drafts.map(function (c, i) {
          const used = usedCount(list[i]);
          return (
            <div key={i} className="cf-catmgr__row">
              <input className="cf-catmgr__inp" value={c} disabled={busy}
                onChange={function (e) { const v = e.target.value; setDrafts(function (d) { const x = d.slice(); x[i] = v; return x; }); }}
                onBlur={function () { commitRename(i); }}
                onKeyDown={function (e) { if (e.key === "Enter") { commitRename(i); e.target.blur(); } }} />
              <button type="button" className="cf-catmgr__del" disabled={busy} onClick={function () { run(props.onDelete(kind, list[i])); }}>
                <i className="ph ph-trash" aria-hidden="true" />{used ? <span className="cf-catmgr__used">{used}</span> : null}
              </button>
            </div>
          );
        })}
        <div className="cf-catmgr__row">
          <input className="cf-catmgr__inp" placeholder="新分類名稱" value={adding} disabled={busy}
            onChange={function (e) { setAdding(e.target.value); }}
            onKeyDown={function (e) { if (e.key === "Enter") add(); }} />
          <button type="button" className="cf-catmgr__addbtn" disabled={busy || !adding.trim()} onClick={add}>
            <i className="ph ph-plus" aria-hidden="true" />新增
          </button>
        </div>
        <p className="cf-catmgr__note">點名稱可改名(自動套到該分類的項目);🗑 刪除後該分類的項目會自動重新歸類(數字=目前使用筆數)。</p>
      </div>
    );
  }

  // 一筆可編輯的列
  function Row(p, r, grouped) {
    return (
      <button key={r.id} type="button" className={"cf-row" + (grouped ? " cf-row--grp" : "")} onClick={() => p.onEdit(r)}>
        <span className="cf-row__l">
          <span className="cf-row__name">{r.name || "(未命名)"}</span>
          {(r.note || r.updatedAt)
            ? <span className="cf-row__sub">{[r.note, r.updatedAt ? "更新 " + shortDate(r.updatedAt) : null].filter(Boolean).join(" · ")}</span>
            : null}
        </span>
        <span className={"cf-row__amt t-num cf-amt--" + TONE[p.kind]}>{SIGN[p.kind]} {fmt(r.monthly)}</span>
      </button>
    );
  }
  // 一筆自動帶入的貸款列(唯讀)
  function AutoRow(r, grouped) {
    return (
      <div key={r.id} className={"cf-row cf-row--static" + (grouped ? " cf-row--grp" : "")}>
        <span className="cf-row__l">
          <span className="cf-row__name">{r.name}<span className="cf-row__auto">自動</span></span>
          {r.monthsLeft != null ? <span className="cf-row__sub">還 {r.monthsLeft} 期 · {monthsToYM(r.monthsLeft)} 還清</span> : null}
        </span>
        <span className="cf-row__amt t-num cf-amt--neg">− {fmt(r.monthly)}</span>
      </div>
    );
  }

  function Section(p) {
    const [open, setOpen] = React.useState({});   // 哪些分類展開中(預設全收合 → 一眼看分類小計,點開才看明細)
    const toggle = (c) => setOpen((o) => Object.assign({}, o, { [c]: !o[c] }));
    const [managing, setManaging] = React.useState(false);   // 分類管理面板
    const active = p.form && p.form.kind === p.kind;
    const grouped = !!CF_CATS[p.kind];
    const bd = grouped ? cfBreakdown(p.rows, p.kind, p.autoRows) : null;
    const showChart = grouped && bd.segments.length >= 2 && p.subtotal > 0 && window.DonutChart;
    const empty = p.rows.length === 0 && (!p.autoRows || p.autoRows.length === 0);
    return (
      <Card className="cf-sec">
        <div className="cf-sec__head">
          <span className="t-overline">{p.title}</span>
          <span className={"cf-sec__sum t-num cf-amt--" + TONE[p.kind]}>{SIGN[p.kind]} {fmt(p.subtotal)}</span>
        </div>
        {p.hint ? <div className="cf-sec__hint">{p.hint}</div> : null}

        {grouped && !active ? (
          <button type="button" className={"cf-managelink" + (managing ? " cf-managelink--on" : "")} onClick={() => setManaging((m) => !m)}>
            <i className={"ph " + (managing ? "ph-check" : "ph-tag")} aria-hidden="true" />{managing ? "完成管理" : "管理分類"}
          </button>
        ) : null}

        {managing ? (
          <CatManager kind={p.kind} list={p.catList || []} onAdd={p.onAddCat} onRename={p.onRenameCat} onDelete={p.onDeleteCat} />
        ) : (
        <React.Fragment>
        {showChart && (
          <div className="cf-chart">
            <window.DonutChart segments={bd.segments} centerLabel={p.title + "分類"} centerValue={"NT$ " + fmt(p.subtotal)} height={172} />
          </div>
        )}

        <div className="cf-list">
          {grouped ? (
            // 依分類分組:每組一個小標(色點對應上面甜甜圈)+ 小計,底下才是各筆
            bd.cats.map((g) => {
              const isOpen = !!open[g.cat];
              return (
                <div key={g.cat} className="cf-grp-wrap">
                  <button type="button" className={"cf-grp" + (isOpen ? " cf-grp--open" : "")} onClick={() => toggle(g.cat)}>
                    <i className={"ph cf-grp__caret " + (isOpen ? "ph-caret-down" : "ph-caret-right")} aria-hidden="true" />
                    <span className="cf-grp__dot" style={{ background: g.color }} />
                    <span className="cf-grp__name">{g.cat}{g.auto ? <span className="cf-row__auto">自動</span> : null}</span>
                    <span className="cf-grp__n">{g.rows.length} 筆</span>
                    <span className={"cf-grp__sum t-num cf-amt--" + TONE[p.kind]}>{SIGN[p.kind]} {fmt(g.sum)}</span>
                  </button>
                  {isOpen ? g.rows.map((r) => (g.auto ? AutoRow(r, true) : Row(p, r, true))) : null}
                </div>
              );
            })
          ) : (
            <React.Fragment>
              {(p.autoRows || []).map((r) => AutoRow(r, false))}
              {p.rows.map((r) => Row(p, r, false))}
            </React.Fragment>
          )}
          {empty && !active ? <div className="cf-empty">尚無項目</div> : null}
        </div>

        {active ? (
          <div className="cf-editor">
            {grouped && (
              <div className="cf-cats">
                {(p.catList || CF_CATS[p.kind]).map((c) => (
                  <button key={c} type="button" className={"cf-cat-chip" + (p.form.category === c ? " cf-cat-chip--on" : "")}
                    onClick={() => p.onField("category", c)}>{c}</button>
                ))}
              </div>
            )}
            <Input placeholder={PH[p.kind]} value={p.form.name} onChange={(e) => p.onField("name", e.target.value)} />
            <Input amount affix="NT$" inputMode="decimal" placeholder="每月金額" value={p.form.monthly}
              onChange={(e) => p.onField("monthly", e.target.value)} />
            <div className="cf-editor__btns">
              {p.form.mode === "edit"
                ? <Button variant="danger" onClick={p.onDelete} loading={p.busy}>刪除</Button>
                : <span className="cf-editor__spacer" />}
              <div className="cf-editor__right">
                <Button variant="secondary" onClick={p.onCancel} disabled={p.busy}>取消</Button>
                <Button variant="primary" onClick={p.onSave} loading={p.busy}>儲存</Button>
              </div>
            </div>
          </div>
        ) : (
          <button type="button" className="cf-add" onClick={() => p.onAdd(p.kind)}>
            <i className="ph ph-plus" aria-hidden="true" />新增{p.title}
          </button>
        )}
        </React.Fragment>
        )}
      </Card>
    );
  }

  function Cashflow({ onChanged }) {
    const H = window.HELM;
    const cf = H && H.cashflow;
    const monthly = (H && H.monthly) || [];
    const [form, setForm] = React.useState(null);   // {mode,kind,_row,name,monthly}
    const [busy, setBusy] = React.useState(false);
    const [mForm, setMForm] = React.useState(null); // 月結封存 {ym,daili,note}
    const [mBusy, setMBusy] = React.useState(false);
    const [cats, setCats] = React.useState(loadCats);   // 可自訂的分類清單(跨裝置同步)
    const [, setTick] = React.useState(0);   // 分類改名/刪除後就地重繪(讀已更新的 window.HELM),不走全 App refresh → 管理面板不會被收掉

    if (!cf) {
      return (
        <div className="screen">
          <Card><div className="cf-notice">
            <b>現金流需要更新後端</b><br />
            重新部署後端到 version 8 後,重開 App 就會出現囉。
          </div></Card>
        </div>
      );
    }

    const onAdd = (kind) => setForm({ mode: "add", kind: kind, _row: null, name: "", monthly: "", category: "" });
    // 編輯時把「目前分類(沒設過就用猜的)」先選起來 → 一存就把合理預設鎖成正式分類,項目逐漸都有真分類
    const onEdit = (kind, r) => setForm({ mode: "edit", kind: kind, _row: r._row, name: r.name, monthly: String(r.monthly || ""), category: r.category || guessCat(r.name, kind) });
    const onField = (k, v) => setForm((f) => Object.assign({}, f, { [k]: v }));
    const cancel = () => setForm(null);

    // 分類管理:清單存偏好(跨裝置);改名/刪除再連動後端把用到的項目一起改
    function persistCats(next) { setCats(next); try { window.HelmPrefs && window.HelmPrefs.set("helm-cf-cats", JSON.stringify(next)); } catch (e) {} }
    function onAddCat(kind, name) { const next = Object.assign({}, cats); next[kind] = (next[kind] || []).concat([name]); persistCats(next); return Promise.resolve(); }
    function onRenameCat(kind, oldN, newN) { const next = Object.assign({}, cats); next[kind] = (next[kind] || []).map((c) => (c === oldN ? newN : c)); persistCats(next); return window.HelmData.recategorizeCf(kind, oldN, newN).then(() => setTick((t) => t + 1)); }
    function onDeleteCat(kind, name) { const next = Object.assign({}, cats); next[kind] = (next[kind] || []).filter((c) => c !== name); persistCats(next); return window.HelmData.recategorizeCf(kind, name, "").then(() => setTick((t) => t + 1)); }

    function save() {
      if (!form.name.trim() || !(num(form.monthly) > 0)) return;
      setBusy(true);
      const fields = { kind: form.kind, name: form.name.trim(), monthly: num(form.monthly), category: form.category || "" };
      const req = form.mode === "edit"
        ? window.HelmData.updateCf(Object.assign({ _row: form._row }, fields))
        : window.HelmData.addCf(fields);
      req.then(() => { setBusy(false); setForm(null); onChanged && onChanged(); });
    }
    function del() {
      setBusy(true);
      window.HelmData.deleteCf(form._row).then(() => { setBusy(false); setForm(null); onChanged && onChanged(); });
    }
    function curYM() { const d = new Date(); return d.getFullYear() + "-" + ("0" + (d.getMonth() + 1)).slice(-2); }
    function closeThisMonth() {
      setMBusy(true);
      window.HelmData.closeMonth({ ym: mForm.ym, daili: num(mForm.daili), note: mForm.note })
        .then(() => { setMBusy(false); setMForm(null); onChanged && onChanged(); });
    }

    const sp = cf.savingPower, fb = cf.freeBalance;
    const loansBySoon = (cf.loans || []).slice().sort((a, b) => (a.monthsLeft || 0) - (b.monthsLeft || 0));

    return (
      <div className="screen">
        <Card variant="lg" className="cf-hero">
          <div className="t-overline">每月現金流</div>
          <div className="cf-hero__rows">
            <div className="cf-hero__row"><span>收入</span><span className="t-num cf-amt--pos">+ {fmt(cf.incomeSum)}</span></div>
            <div className="cf-hero__row"><span>支出</span><span className="t-num cf-amt--neg">− {fmt(cf.expenseSum)}</span></div>
            <div className="cf-hero__line" />
            <div className="cf-hero__row cf-hero__row--big">
              <span>儲蓄力</span>
              <span className={"t-num " + (sp >= 0 ? "cf-amt--pos" : "cf-amt--neg")}>{sp >= 0 ? "+" : "−"} {fmt(Math.abs(sp))}</span>
            </div>
            <div className="cf-hero__row"><span>定期投入</span><span className="t-num cf-amt--inv">→ {fmt(cf.investSum)}</span></div>
            <div className="cf-hero__line" />
            <div className="cf-hero__row cf-hero__row--big">
              <span>自由結餘</span>
              <span className={"t-num " + (fb >= 0 ? "cf-amt--pos" : "cf-amt--neg")}>{fb >= 0 ? "+" : "−"} {fmt(Math.abs(fb))}</span>
            </div>
          </div>
          <div className="cf-hero__note">
            {fb < 0
              ? "⚠ 自由結餘是負的:你每月定期投入的比「存得下的」還多,差額得從既有現金或額度補。可考慮調低定期投入,或這是有意識的積極投資。"
              : "投入後每月還有這些錢可自由運用 👍"}
          </div>
        </Card>

        <Section title="收入" kind="收入" rows={cf.income} subtotal={cf.incomeSum}
          catList={cats["收入"]} onAddCat={onAddCat} onRenameCat={onRenameCat} onDeleteCat={onDeleteCat}
          form={form} busy={busy} onAdd={onAdd} onEdit={(r) => onEdit("收入", r)}
          onField={onField} onSave={save} onDelete={del} onCancel={cancel} />

        <Section title="支出" kind="支出" rows={cf.expense} autoRows={cf.loans} subtotal={cf.expenseSum}
          hint="貸款月付已自動帶入(標「自動」),不用重複新增。其他固定開銷、孝親費、信用卡帳單填這裡。"
          catList={cats["支出"]} onAddCat={onAddCat} onRenameCat={onRenameCat} onDeleteCat={onDeleteCat}
          form={form} busy={busy} onAdd={onAdd} onEdit={(r) => onEdit("支出", r)}
          onField={onField} onSave={save} onDelete={del} onCancel={cancel} />

        <Section title="投入" kind="投入" rows={cf.invest} subtotal={cf.investSum}
          hint="定期定額 ETF、定期換美金…這是把錢變成資產、不是花掉,所以單獨算。"
          form={form} busy={busy} onAdd={onAdd} onEdit={(r) => onEdit("投入", r)}
          onField={onField} onSave={save} onDelete={del} onCancel={cancel} />

        {loansBySoon.length > 0 && (
          <Card className="cf-sec">
            <div className="cf-sec__head"><span className="t-overline">還清里程碑</span></div>
            <div className="cf-list">
              {loansBySoon.map((l) => (
                <div key={l.id} className="cf-row cf-row--static">
                  <span className="cf-row__l">
                    <span className="cf-row__name">{l.name}</span>
                    <span className="cf-row__sub">還清後每月 +{fmt(l.monthly)} 現金流</span>
                  </span>
                  <span className="cf-mile t-num">{monthsToYM(l.monthsLeft)}</span>
                </div>
              ))}
            </div>
          </Card>
        )}

        <Card className="cf-sec">
          <div className="cf-sec__head"><span className="t-overline">月結 · 每月封存</span></div>
          <div className="cf-sec__hint">每月底更新好「信用卡帳單」後按封存,留一筆當月快照——累積後總覽會長出趨勢圖。</div>
          <div className="cf-list">
            {monthly.slice().reverse().map((m) => (
              <div key={m.id} className="cf-row cf-row--static">
                <span className="cf-row__l">
                  <span className="cf-row__name">{m.ym}</span>
                  <span className="cf-row__sub">真實支出 {fmt(m.realExpense)} · 儲蓄 {fmt(m.saving)}{m.daili ? " · 代墊 " + fmt(m.daili) : ""}</span>
                </span>
                <span className="cf-row__amt t-num">淨值 {fmt(m.netWorth)}</span>
              </div>
            ))}
            {monthly.length === 0 && !mForm ? <div className="cf-empty">還沒有月結紀錄</div> : null}
          </div>
          {mForm ? (
            <div className="cf-editor">
              <Input placeholder="年月(例 2026-06)" value={mForm.ym}
                onChange={(e) => setMForm((f) => Object.assign({}, f, { ym: e.target.value }))} />
              <Input amount affix="NT$" inputMode="decimal" placeholder="這個月公司代墊多少"
                value={mForm.daili} onChange={(e) => setMForm((f) => Object.assign({}, f, { daili: e.target.value }))} />
              <div className="goal__hint">會自動抓你現在的淨值/收入/支出/卡費當快照;代墊填上面這格(沒有就留 0)</div>
              <div className="cf-editor__btns">
                <span className="cf-editor__spacer" />
                <div className="cf-editor__right">
                  <Button variant="secondary" onClick={() => setMForm(null)} disabled={mBusy}>取消</Button>
                  <Button variant="primary" onClick={closeThisMonth} loading={mBusy}>封存</Button>
                </div>
              </div>
            </div>
          ) : (
            <button type="button" className="cf-add" onClick={() => setMForm({ ym: curYM(), daili: "", note: "" })}>
              <i className="ph ph-floppy-disk" aria-hidden="true" />封存這個月
            </button>
          )}
        </Card>
      </div>
    );
  }

  window.Cashflow = Cashflow;
})();
