// Helm — 報稅/節稅試算(台灣綜所稅)。115 年度(2026 所得,2027/5 申報)參數,以財政部公告為準。
// 處理:標準vs列舉(含健保費全額)、儲蓄投資特扣+房貸利息減項、基本生活費差額、長照排富、
//       夫妻薪資分開計稅(取較省)、股利合併8.5%抵減 vs 分開28%(取較省)。純前端,經 agent 查證。
// 欄位記憶:沒動過→用明細/預設;改過→記住(localStorage helm-tax-*)。
(function () {
  const NS = window.HelmDesignSystem_9613a7;
  const { Field, Input } = NS;
  function fmt(n) { return Math.round(n || 0).toLocaleString("en-US"); }
  function wan(n) { return (Math.round((n || 0) / 1e3) / 10).toLocaleString("en-US"); }
  function num(v) { return parseFloat(String(v).replace(/,/g, "")) || 0; }
  function int(v) { return Math.max(0, Math.round(num(v))); }
  function lsGet(k) { try { return localStorage.getItem(k); } catch (e) { return null; } }
  function lsSet(k, v) { try { localStorage.setItem(k, v); } catch (e) {} }
  function lsDel(k) { try { localStorage.removeItem(k); } catch (e) {} }

  // ── 115 年度(2026)參數 ──
  const Y = {
    label: "115 年度(2026 所得)",
    exempt: 101000,
    stdSingle: 136000, stdCouple: 272000,
    salaryMax: 227000,
    mortgageMax: 300000,
    insMax: 24000,
    savingsMax: 270000,
    preschool1: 150000, preschoolN: 225000,
    longCare: 180000,
    edu: 25000,
    basicLiving: 213000,   // 基本生活費/人(114 年值;115 尚未公告,暫用)
    divCreditRate: 0.085, divCreditCap: 80000, divSepRate: 0.28,
    brackets: [[610000, 0.05, 0], [1380000, 0.12, 42700], [2770000, 0.20, 153100], [5190000, 0.30, 430100], [Infinity, 0.40, 949100]],
  };
  function bracketOf(net) { for (let i = 0; i < Y.brackets.length; i++) { if (net <= Y.brackets[i][0]) return Y.brackets[i]; } return Y.brackets[Y.brackets.length - 1]; }
  function taxOf(net) { const b = bracketOf(net); return Math.max(0, net * b[1] - b[2]); }

  const K = { salary: "helm-tax-salary", spouse: "helm-tax-spouse", spouseSalary: "helm-tax-spousesalary", deps: "helm-tax-deps", mort: "helm-tax-mort", ins: "helm-tax-ins", nhi: "helm-tax-nhi", intr: "helm-tax-intr", div: "helm-tax-div", pre: "helm-tax-pre", edu: "helm-tax-edu", ltc: "helm-tax-ltc" };

  function TaxScreen({ onClose }) {
    const H = window.HELM || {};
    const cf = H.cashflow || {};
    const dftSalary = String(Math.round((cf.incomeSum || 0) * 12));
    const mortItems = (H.liabilities || []).filter(function (l) { return /房/.test(l.cat || "") || /房/.test(l.name || ""); });
    const dftMort = String(Math.round(mortItems.reduce(function (s, l) { return s + (l.twd || 0) * (l.loanRate || 0) / 100; }, 0)));

    const [salary, setSalary] = React.useState(function () { return lsGet(K.salary) || dftSalary; });
    const [spouse, setSpouse] = React.useState(function () { return lsGet(K.spouse) || "yes"; });
    const [spouseSalary, setSpouseSalary] = React.useState(function () { return lsGet(K.spouseSalary) || "0"; });
    const [deps, setDeps] = React.useState(function () { return lsGet(K.deps) || "0"; });
    const [mort, setMort] = React.useState(function () { return lsGet(K.mort) || dftMort; });
    const [ins, setIns] = React.useState(function () { return lsGet(K.ins) || "0"; });
    const [nhi, setNhi] = React.useState(function () { return lsGet(K.nhi) || "0"; });
    const [intr, setIntr] = React.useState(function () { return lsGet(K.intr) || "0"; });
    const [div, setDiv] = React.useState(function () { return lsGet(K.div) || "0"; });
    const [pre, setPre] = React.useState(function () { return lsGet(K.pre) || "0"; });
    const [edu, setEdu] = React.useState(function () { return lsGet(K.edu) || "0"; });
    const [ltc, setLtc] = React.useState(function () { return lsGet(K.ltc) || "0"; });

    function persist(setter, key) { return function (e) { const v = e.target.value; setter(v); lsSet(key, v); }; }
    function pickSpouse(s) { setSpouse(s); lsSet(K.spouse, s); }
    function resetAll() {
      Object.keys(K).forEach(function (k) { lsDel(K[k]); });
      setSalary(dftSalary); setSpouse("yes"); setSpouseSalary("0"); setDeps("0"); setMort(dftMort);
      setIns("0"); setNhi("0"); setIntr("0"); setDiv("0"); setPre("0"); setEdu("0"); setLtc("0");
    }

    const hasSpouse = spouse === "yes";
    const S = num(salary), SS = hasSpouse ? num(spouseSalary) : 0, DEP = int(deps);
    const MORT = num(mort), INS = num(ins), NHI = num(nhi), INT = num(intr), DIV = num(div);
    const PRE = int(pre), EDU = int(edu), LTC = int(ltc);

    const people = 1 + (hasSpouse ? 1 : 0) + DEP;
    const exemptAll = people * Y.exempt;
    const savingsDed = Math.min(INT, Y.savingsMax);                        // 儲蓄投資特別扣除
    const mortDed = Math.min(Math.max(0, MORT - savingsDed), Y.mortgageMax); // 房貸利息(先減儲蓄投資)
    const insDed = Math.min(INS, Y.insMax * people);
    const itemized = mortDed + insDed + NHI;                              // 列舉(健保費全額)
    const std = hasSpouse ? Y.stdCouple : Y.stdSingle;
    const usedItemized = itemized > std;
    const generalDed = Math.max(itemized, std);
    const preDed = PRE >= 1 ? Y.preschool1 + Math.max(0, PRE - 1) * Y.preschoolN : 0;
    const eduDed = EDU * Y.edu;

    // 長照排富:用合併粗估邊際稅率,≥20% 不適用
    const roughNet = Math.max(0, S + SS - exemptAll - generalDed - (Math.min(Y.salaryMax, S) + Math.min(Y.salaryMax, SS)) - savingsDed - preDed - eduDed);
    const ltcEligible = bracketOf(roughNet)[1] < 0.20;
    const ltcDed = ltcEligible ? LTC * Y.longCare : 0;
    const ltcExcluded = LTC > 0 && !ltcEligible;

    // 基本生活費差額(比較基礎排除「薪資所得特別扣除」)
    const blfBase = exemptAll + generalDed + savingsDed + preDed + eduDed + ltcDed;
    const blfDiff = Math.max(0, Y.basicLiving * people - blfBase);
    const otherDed = savingsDed + preDed + eduDed + ltcDed + blfDiff;     // 不含薪資特扣的其餘減除

    // 薪資稅:合併 vs 夫妻薪資分開,取較省
    const salDedComb = Math.min(Y.salaryMax, S) + (hasSpouse ? Math.min(Y.salaryMax, SS) : 0);
    const netComb = Math.max(0, S + SS - exemptAll - generalDed - salDedComb - otherDed);
    const taxComb = taxOf(netComb);
    let taxSep = Infinity, netHi = netComb;
    if (hasSpouse && SS > 0) {
      const hi = Math.max(S, SS), lo = Math.min(S, SS);
      const netLo = Math.max(0, lo - Y.exempt - Math.min(Y.salaryMax, lo));               // 分開者:自己薪資 − 1 份免稅 − 自己薪資特扣
      netHi = Math.max(0, hi - (exemptAll - Y.exempt) - generalDed - Math.min(Y.salaryMax, hi) - otherDed);
      taxSep = taxOf(netLo) + taxOf(netHi);
    }
    const useSep = taxSep < taxComb;
    const salaryTax = Math.min(taxComb, taxSep);
    const mRate = bracketOf(useSep ? netHi : netComb)[1];

    // 股利:合併(按邊際稅率,抵減 8.5% 上限 8 萬)vs 分開 28%,取較省
    let divTax = 0, divMethod = "";
    if (DIV > 0) {
      const divMerged = DIV * mRate - Math.min(DIV * Y.divCreditRate, Y.divCreditCap);
      const divSep = DIV * Y.divSepRate;
      divTax = Math.min(divMerged, divSep);
      divMethod = divMerged <= divSep ? "合併計稅(抵減 8.5%)" : "分開計稅 28%";
    }
    const totalTax = Math.max(0, salaryTax + divTax);
    const grossIncome = S + SS + DIV;
    const effRate = grossIncome > 0 ? totalTax / grossIncome * 100 : 0;
    const methodLabel = (useSep ? "夫妻薪資分開" : "合併") + (DIV > 0 ? " · 股利" + (divMethod.indexOf("28") >= 0 ? "28%" : "合併") : "");
    const gapToStd = std - itemized;

    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><span className="fpage__card-hint">{Y.label}</span></div>
                <div className="fx-now"><span className="fx-now__unit">應納稅額約</span><span className="fx-now__rate t-num">{fmt(totalTax)}</span></div>
                <div className="goal__nums"><span className="t-num">有效稅率 ≈ {effRate.toFixed(1)}%</span><span className="goal__pct t-num">{methodLabel}</span></div>

                <div className="tax-break">
                  <div className="tax-row"><span>薪資所得合計</span><span className="t-num">{fmt(S + SS)}</span></div>
                  <div className="tax-row"><span>− 免稅額({people} 人)</span><span className="t-num">{fmt(exemptAll)}</span></div>
                  <div className="tax-row"><span>− {usedItemized ? "列舉扣除" : "標準扣除"}</span><span className="t-num">{fmt(generalDed)}</span></div>
                  <div className="tax-row"><span>− 薪資特別扣除</span><span className="t-num">{fmt(salDedComb)}</span></div>
                  {(savingsDed + preDed + eduDed + ltcDed) > 0 && <div className="tax-row"><span>− 其他特別扣除(儲蓄/幼兒/教育/長照)</span><span className="t-num">{fmt(savingsDed + preDed + eduDed + ltcDed)}</span></div>}
                  {blfDiff > 0 && <div className="tax-row"><span>− 基本生活費差額</span><span className="t-num">{fmt(blfDiff)}</span></div>}
                  <div className="tax-row tax-row--sum"><span>= 綜合所得淨額(合併)</span><span className="t-num">{fmt(netComb)}</span></div>
                  <div className="tax-row"><span>薪資應納稅額{useSep ? "(已用分開計稅)" : ""}</span><span className="t-num">{fmt(salaryTax)}</span></div>
                  {DIV > 0 && <div className="tax-row"><span>+ 股利稅({divMethod.indexOf("28") >= 0 ? "28%" : "合併"})</span><span className="t-num">{fmt(divTax)}</span></div>}
                  <div className="tax-row tax-row--sum"><span>= 應納稅額</span><span className="t-num">{fmt(totalTax)}</span></div>
                </div>

                {/* 重點建議 */}
                <div className="fire-desc">
                  {usedItemized
                    ? <p>💡 <b>報稅選「列舉」</b>:你的列舉 {wan(itemized)} 萬(房貸利息 {wan(mortDed)} + 保險 {wan(insDed)} + 健保 {wan(NHI)} 萬)> {hasSpouse ? "夫妻" : "單身"}標準 {wan(std)} 萬。</p>
                    : <p>💡 <b>用「標準扣除」划算</b>:列舉 {wan(itemized)} 萬還沒過標準 {wan(std)} 萬,差 {wan(gapToStd)} 萬。把<b>健保費、自費醫藥、捐贈</b>加進來有機會超過、改省更多。</p>}
                  {useSep && <p>💡 <b>夫妻用「薪資分開計稅」</b>較省,比合併少繳約 <b>{fmt(taxComb - salaryTax)}</b> 元(國稅局申報軟體會自動幫你選)。</p>}
                  {DIV > 0 && <p>💡 你的股利建議用 <b>{divMethod}</b>。</p>}
                  {blfDiff > 0 && <p>💡 你有「基本生活費差額」{wan(blfDiff)} 萬可再減(多眷口家庭常有)。</p>}
                  {ltcExcluded && <p>⚠️ 你的稅率 ≥ 20%,<b>長照特別扣除不適用</b>(排富),已不計入。</p>}
                </div>
              </section>

              <section className="fpage__card">
                <div className="fpage__card-head"><span className="t-overline">所得與家庭(改過會記住)</span></div>
                <div className="fpage__fields">
                  <Field label="你的年薪資所得" hint="扣繳憑單薪資總額(預設帶現金流收入×12,請改實際)">
                    <Input amount affix="NT$" inputMode="decimal" value={fmt(S)} onChange={persist(setSalary, K.salary)} />
                  </Field>
                  <Field label="申報身份">
                    <div className="fire-seg" role="tablist">
                      <button type="button" role="tab" aria-selected={!hasSpouse} className={"fire-seg__btn" + (!hasSpouse ? " is-on" : "")} onClick={function () { pickSpouse("no"); }}>單身</button>
                      <button type="button" role="tab" aria-selected={hasSpouse} className={"fire-seg__btn" + (hasSpouse ? " is-on" : "")} onClick={function () { pickSpouse("yes"); }}>有配偶</button>
                    </div>
                  </Field>
                  {hasSpouse && (
                    <Field label="配偶年薪資所得" hint="填了會自動比『合併 vs 薪資分開』取較省;沒收入填 0">
                      <Input amount affix="NT$" inputMode="decimal" value={fmt(SS)} onChange={persist(setSpouseSalary, K.spouseSalary)} />
                    </Field>
                  )}
                  <Field label="受扶養親屬人數" hint="父母、子女等符合扶養者(本人與配偶不算)">
                    <Input inputMode="numeric" value={deps} onChange={persist(setDeps, K.deps)} />
                  </Field>
                  <Field label="全戶股利所得/年" hint="台股/ETF 配息、RSU 配股等;會自動比『合併抵減 vs 28% 分開』">
                    <Input amount affix="NT$" inputMode="decimal" value={fmt(DIV)} onChange={persist(setDiv, K.div)} />
                  </Field>
                </div>
              </section>

              <section className="fpage__card">
                <div className="fpage__card-head"><span className="t-overline">扣除額(改過會記住)</span></div>
                <div className="fpage__fields">
                  <Field label="自用住宅房貸利息/年" hint={"列舉上限 30 萬,須先減儲蓄投資扣除。預設=房貸餘額×利率" + (num(dftMort) > 0 ? "(約 " + wan(num(dftMort)) + " 萬)" : "") + ",實際以銀行繳息證明為準"}>
                    <Input amount affix="NT$" inputMode="decimal" value={fmt(MORT)} onChange={persist(setMort, K.mort)} />
                  </Field>
                  <Field label="全民健保費/年(含補充保費)" hint="列舉可全額、不受 2.4 萬限制(全家自付額)">
                    <Input amount affix="NT$" inputMode="decimal" value={fmt(NHI)} onChange={persist(setNhi, K.nhi)} />
                  </Field>
                  <Field label="人身保險費/年" hint="壽險/醫療等,每人上限 2.4 萬">
                    <Input amount affix="NT$" inputMode="decimal" value={fmt(INS)} onChange={persist(setIns, K.ins)} />
                  </Field>
                  <Field label="銀行/存款利息收入/年" hint="儲蓄投資特別扣除(上限 27 萬),也會從房貸利息列舉中先扣掉">
                    <Input amount affix="NT$" inputMode="decimal" value={fmt(INT)} onChange={persist(setIntr, K.intr)} />
                  </Field>
                  <Field label="幼兒學前(6 歲以下)人數" hint="首名 15 萬、第 2 名起每名 22.5 萬">
                    <Input inputMode="numeric" value={pre} onChange={persist(setPre, K.pre)} />
                  </Field>
                  <Field label="大專院校子女人數" hint="每名 2.5 萬教育學費">
                    <Input inputMode="numeric" value={edu} onChange={persist(setEdu, K.edu)} />
                  </Field>
                  <Field label="長照符合人數" hint="每人 18 萬(稅率 ≥ 20% 不適用,工具會自動排除)">
                    <Input inputMode="numeric" value={ltc} onChange={persist(setLtc, K.ltc)} />
                  </Field>
                </div>
                <button type="button" className="fire-reset" onClick={resetAll}><i className="ph ph-arrow-counter-clockwise" aria-hidden="true" /> 全部重設為自動帶入的值</button>
              </section>

              <p className="fx-disclaim">依 <b>{Y.label}</b> 估算,金額以財政部公告為準(115 年度「基本生活費」尚未公告,暫用 114 年 21.3 萬/人)。已含:標準/列舉比較、儲蓄投資、基本生活費差額、夫妻薪資分開、股利合併/分開擇優、長照排富。<b>未含</b>:其他列舉(自費醫藥、捐贈、災損——可自行加進健保那類欄位試)、租金特別扣除(與房貸利息擇一)、海外所得與最低稅負(基本所得額)、各類所得分開計稅。當方向參考,正式以財政部報稅系統試算為準。</p>
            </div>
          </div>
        </div>
      </div>
    );
  }

  window.TaxScreen = TaxScreen;
})();
