// iotab.jsx — 委刊單(InsertionOrder) 分頁，依真實範本 · 可雙方編輯 · 匯出可編輯 .doc

function qItems(c) {return c.quote.items.map((k) => {const p = window.PRICE_LIST.find((x) => x.key === k) || {};return { item: p.item, price: p.price || 0 };});}

// ── 委刊單金額與付款計畫（單一計算來源，收款頁共用）──
function ioTotals(c) {
  const io = c.io || {};
  const items = io.items && io.items.length ? io.items : c.value ? [{ name: c.product, fee: c.value }] : [];
  const sub = items.reduce((s, it) => s + (Number(it.fee) || 0), 0);
  const tax = items.reduce((s, it) => s + Math.round((Number(it.fee) || 0) * 0.05), 0);
  const total = sub + tax;
  let depPct = io.depPct == null ? 50 : Number(io.depPct);
  let balPct = io.balPct == null ? 50 : Number(io.balPct);
  const dep = Math.round(total * depPct / 100);
  const bal = total - dep;
  return { sub, tax, total, depPct, balPct, dep, bal };
}
// 依委刊單比例產生付款項目（可能只有一筆）
function payPlan(c) {
  const t = ioTotals(c);
  const plan = [];
  if (t.depPct > 0) plan.push({ key: 'dep', label: '訂金', pct: t.depPct, amount: t.dep });
  if (t.balPct > 0) plan.push({ key: 'bal', label: '尾款', pct: t.balPct, amount: t.bal });
  if (plan.length === 0) plan.push({ key: 'bal', label: '全額', pct: 100, amount: t.total });
  if (plan.length === 1) plan[0] = { ...plan[0], label: '全額結清' };
  return { ...t, plan };
}
function paySummary(c) {
  const { plan } = payPlan(c);
  const pay = c.pay || { dep: { paid: false }, bal: { paid: false } };
  const paid = plan.filter((p) => pay[p.key] && pay[p.key].paid).length;
  if (paid === 0) return { label: '未收款', tone: 'risk-mid', settled: false };
  if (paid === plan.length) return { label: '已結清', tone: 'risk-low', settled: true };
  return { label: '已收部分', tone: 'risk-mid', settled: false };
}
// 案件是否完成（尾款發票提醒依據）
function isCompleted(c) {
  return c.pay && c.pay.bal && c.pay.bal.paid || ['售後', '結案'].includes(c.progress) || c.stage === 'finance';
}
// 每個付款段對應一張發票；訂金於「已簽署」提醒、尾款/全額於「案件完成」提醒
function invoiceSegments(c) {
  const { plan } = payPlan(c);
  const signed = !!(c.io && c.io.signed);
  const done = isCompleted(c);
  const invs = c.invoices || {};
  return plan.map((p) => {
    const due = p.key === 'dep' ? signed : done;
    return { key: p.key, label: p.label, amount: p.amount, invoiced: !!invs[p.key], invoice: invs[p.key] || null, due };
  });
}

function IoLine({ k, v, edit, onChange, ph }) {
  return <div className="ioline">
    <div className="iok">{k}</div>
    {edit ? <input className="miniinp" value={v} placeholder={ph} onChange={(e) => onChange(e.target.value)} /> :
    <div className="iov">{v}</div>}
  </div>;
}

function BankBlock({ title, bank, onChange, accent }) {
  const set = (patch) => onChange({ ...bank, ...patch });
  return (
    <div className={'iobox' + (accent ? ' accent' : '')}>
      <div className="ioh">{title}</div>
      <div className="bankgrid">
        <label>戶名<input className="miniinp" value={bank.holder} onChange={(e) => set({ holder: e.target.value })} placeholder="戶名" /></label>
        <label>銀行<input className="miniinp" value={bank.bank} onChange={(e) => set({ bank: e.target.value })} placeholder="銀行" /></label>
        <label>銀行代號<input className="miniinp" value={bank.code} onChange={(e) => set({ code: e.target.value })} placeholder="000" /></label>
        <label>銀行帳號<input className="miniinp" value={bank.acct} onChange={(e) => set({ acct: e.target.value })} placeholder="帳號" /></label>
      </div>
    </div>);

}

/* 簽訂前·事前確認信（確認合作項目金額 · 詢問甲方必填資料）*/
function genIOInquiry(c, t) {
  const S = window.STUDIO || {};
  const io = c.io || {};
  const money = (n) => 'NT$ ' + window.fmtNum(n);
  const items = (io.items || []).filter((it) => it.name);
  const itemLines = items.length ?
  items.map((it) => {const fee = Number(it.fee) || 0;const tax = Math.round(fee * 0.05);return `・${it.name}　廣告費 ${window.fmtNum(fee)}（含稅 ${window.fmtNum(fee + tax)}）`;}).join('\n') :
  '（項目待確認）';
  // 甲方（廠商）開立發票與聯絡所需必填欄位
  const need = [
  ['發票抬頭', io.invoiceTitle],
  ['統一編號', io.taxId],
  ['聯絡地址（發票寄送）', io.addr],
  ['聯絡電話', io.tel],
  ['E-mail', io.email]];

  const needLines = need.map(([k, v]) => `・${k}：${v && String(v).trim() && !/^（/.test(v) ? v + '　（如需修正請告知）' : '________________'}`).join('\n');
  return {
    subject: `委刊簽訂前確認― ${c.vendor} × ${S.creator || '國美'}（${c.product}）`,
    body: `${c.contact} 您好，\n\n我是多多，負責國美的合作洽談。在正式簽訂廣告委刊單前，想與您確認合作項目金額，並麻煩提供開立委刊單所需的資料：\n\n【一、合作項目與金額（未稅×含稅）】\n${itemLines}\n總計（含稅）：${money(t.total)}\n\n【二、請提供以下資料（委刊、開立發票所需）】\n${needLines}\n\n以上項目金額若無誤，並麻煩補齊上述資料回覆給我，我們就會進一步產出委刊單請雙方簽署。若需調整合作項目或金額，也請直接告知。\n\n感謝您的協助，期待合作順利！\n\nBest regards,\n多多\n${S.name || '果米工作室'}　官方 LINE：@942njuhl` };
}

function InsertionOrderTab({ c, onUpdate, onNext, onMove, toast }) {
  const S = window.STUDIO;
  const io = c.io;
  const set = (patch) => onUpdate({ io: { ...io, ...patch } });

  const items = io.items || [];
  const setItem = (i, patch) => set({ items: items.map((it, k) => k === i ? { ...it, ...patch } : it) });
  const addItem = () => set({ items: [...items, { name: '', fee: 0 }] });
  const delItem = (i) => set({ items: items.filter((_, k) => k !== i) });
  const pullFromQuote = () => {set({ items: window.ioItemsFromQuote(c) });toast('已從報價步驟帶入項目');};

  const sub = items.reduce((s, it) => s + (Number(it.fee) || 0), 0);
  const tax = items.reduce((s, it) => s + Math.round((Number(it.fee) || 0) * 0.05), 0);
  const total = sub + tax;
  const depPct = Number(io.depPct) || 0,balPct = Number(io.balPct) || 0;
  const dep = Math.round(total * depPct / 100),bal = total - dep;

  const sign = () => {
    set({ signed: true, signB: '果米工作室 · 多多' });
    if (onMove && c.stage === 'contract') onMove('schedule');
    toast('委刊單已簽署 · 案件移至「排程」');
    if (window.isGoogleConnected?.()) {
      window.createDriveFolder(`${c.id} ${c.vendor}`)
        .then(f => { set({ driveFolderUrl: `https://drive.google.com/drive/folders/${f.id}` }); toast('✓ 雲端硬碟資料夾已建立'); })
        .catch(e => toast('Drive 資料夾建立失敗：' + e.message));
    }
  };

  const [showAsk, setShowAsk] = React.useState(false);
  const inquiry = genIOInquiry(c, { total, dep, bal, depPct, balPct });
  const copyAsk = () => {window.copyText(inquiry.subject + '\n\n' + inquiry.body, toast, '已複製事前確認信到剪貼簿');};

  return (
    <div className="tabwrap">
      <div className="tabbody" style={{ background: 'var(--paper-2)' }}>
        <div className="editnote">✎ 此頁所有欄位（金額、付款、條款、帳號）皆可雙方協商修改；右下可匯出可編輯文件。</div>
        {!io.signed && <div className="askbar">
          <div className="askbar-h" onClick={() => setShowAsk((v) => !v)}>
            <span style={{ fontSize: 14 }}>✉</span>
            <div style={{ flex: 1 }}>
              <div style={{ fontWeight: 700, fontSize: 12.5 }}>簽訂前·事前確認信</div>
              <div className="faint" style={{ fontSize: 10.5 }}>簽委刊單前，先與廠商確認金額、付款方式、條款與匯款帳號</div>
            </div>
            <span className="linkbtn">{showAsk ? '收合 ⌃' : '展開·取得信件 ⌄'}</span>
          </div>
          {showAsk && <div className="askbody">
            <div className="mailhead" style={{ borderRadius: '8px 8px 0 0' }}>
              <span className="faint mono" style={{ fontSize: 10 }}>主旨</span>
              <span className="ell" style={{ fontSize: 12, fontWeight: 600 }}>{inquiry.subject}</span>
              <button className="btn" style={{ marginLeft: 'auto', height: 28, fontSize: 11.5 }} onClick={copyAsk}>⧉ 複製信件</button>
            </div>
            <textarea className="emailedit" style={{ minHeight: 300, borderRadius: '0 0 8px 8px' }} value={inquiry.body} readOnly />
          </div>}
        </div>}
        <div className="iodoc">
          <div className="ioband">
            <div>
              <div className="serif" style={{ fontSize: 20, fontWeight: 900, letterSpacing: 1 }}>廣告委刊單</div>
              <div className="faint mono" style={{ fontSize: 10.5, marginTop: 3 }}>INSERTION ORDER</div>
              <div style={{ fontSize: 12, marginTop: 7 }}>案件名稱：<b>{S.creator} ✕ {c.vendor}</b></div>
            </div>
            <div style={{ textAlign: 'right' }}>
              <div className="mono" style={{ fontSize: 11 }}>編號 {io.number}</div>
              <div style={{ marginTop: 5, display: 'flex', gap: 6, alignItems: 'center', justifyContent: 'flex-end' }}>
                <span className="faint" style={{ fontSize: 10 }}>申請日期</span>
                <input className="miniinp" style={{ width: 140 }} type="date" value={io.date} onChange={(e) => set({ date: e.target.value })} />
              </div>
              <div style={{ marginTop: 7 }}>{io.signed ?
                <span className="pill risk-low" style={{ height: 20 }}><span className="dot"></span>已簽署</span> :
                <span className="pill risk-mid" style={{ height: 20 }}><span className="dot"></span>待簽署</span>}</div>
            </div>
          </div>

          {/* 甲乙方 */}
          <div className="iotwo">
            <div className="iobox">
              <div className="ioh">委刊方（甲方）</div>
              <IoLine k="公司名稱" v={c.vendor} />
              <IoLine k="發票抬頭" edit v={io.invoiceTitle} ph="同公司名稱" onChange={(v) => set({ invoiceTitle: v })} />
              <IoLine k="統一編號" edit v={io.taxId} ph="00000000" onChange={(v) => set({ taxId: v })} />
              <IoLine k="聯絡地址" edit v={io.addr} ph="（請填寫）" onChange={(v) => set({ addr: v })} />
              <IoLine k="聯絡人" v={`${c.contact} · ${c.contactRole}`} />
              <IoLine k="聯絡電話" edit v={io.tel} ph="（請填寫）" onChange={(v) => set({ tel: v })} />
              <IoLine k="E-mail" edit v={io.email} ph="（請填寫）" onChange={(v) => set({ email: v })} />
            </div>
            <div className="iobox accent">
              <div className="ioh">受託方（乙方）</div>
              <IoLine k="公司名稱" v={S.name} />
              <IoLine k="發票抬頭" v={S.invoiceTitle} />
              <IoLine k="統一編號" v={S.taxId} />
              <IoLine k="聯絡地址" v={S.addr} />
              <IoLine k="聯絡人" v={S.contact} />
              <IoLine k="聯絡電話" v={S.tel} />
              <IoLine k="E-mail" v={S.email} />
            </div>
          </div>

          {/* 合作內容（可編輯明細）*/}
          <div className="iosect">合作內容
            <span className="secttools">
              <button className="linkbtn" onClick={pullFromQuote}>↺ 從報價帶入</button>
              <button className="linkbtn" onClick={addItem}>＋ 新增項目</button>
            </span>
          </div>
          <div className="iotable">
            <div className="iorow head"><span style={{ flex: 1 }}>項目</span><span style={{ width: 120, textAlign: 'right' }}>廣告費</span><span style={{ width: 84, textAlign: 'right' }}>稅金 5%</span><span style={{ width: 104, textAlign: 'right' }}>小計</span><span style={{ width: 26 }}></span></div>
            {items.length === 0 && <div className="iorow"><span className="faint">尚無項目，點「新增項目」或「從報價帶入」</span></div>}
            {items.map((it, i) => {const t = Math.round((Number(it.fee) || 0) * 0.05);return (
                <div key={i} className="iorow">
                <input className="cellinp" style={{ flex: 1 }} value={it.name} placeholder="合作項目內容" onChange={(e) => setItem(i, { name: e.target.value })} />
                <input className="cellinp mono" style={{ width: 120, textAlign: 'right' }} type="number" value={it.fee} onChange={(e) => setItem(i, { fee: e.target.value })} />
                <span className="mono" style={{ width: 84, textAlign: 'right', color: 'var(--ink-3)' }}>{window.fmtNum(t)}</span>
                <span className="mono" style={{ width: 104, textAlign: 'right' }}>{window.fmtNum((Number(it.fee) || 0) + t)}</span>
                <button className="rowdel" style={{ width: 26 }} onClick={() => delItem(i)} title="刪除">✕</button>
              </div>);
            })}
            <div className="iorow total"><span style={{ flex: 1 }}>總計</span><span className="mono" style={{ width: 120, textAlign: 'right' }}>{window.fmtNum(sub)}</span><span className="mono" style={{ width: 84, textAlign: 'right' }}>{window.fmtNum(tax)}</span><span className="mono" style={{ width: 104, textAlign: 'right' }}>NT$ {window.fmtNum(total)}</span><span style={{ width: 26 }}></span></div>
          </div>

          {/* 付款方式（可編輯）*/}
          <div className="iosect">付款方式
            <span className="secttools">
              {[[50, 50], [30, 70], [40, 60], [0, 100]].map(([d, b]) =>
              <button key={d + '-' + b} className={'ratiochip' + (depPct === d && balPct === b ? ' on' : '')}
              onClick={() => set({ depPct: d, balPct: b, payBal: d === 0 ? '簽約並收到發票後 30 日內一次結清' : io.payBal })}>
                  {d === 0 ? '全額結清' : d + '/' + b}
                </button>
              )}
            </span>
          </div>
          <div className="paygrid">
            {depPct > 0 && <div className="payrow">
              <div className="paypct"><span>訂金</span><input className="miniinp" style={{ width: 54 }} type="number" value={io.depPct} onChange={(e) => set({ depPct: +e.target.value })} /><span>%</span></div>
              <input className="miniinp" style={{ flex: 1 }} value={io.payDep} onChange={(e) => set({ payDep: e.target.value })} placeholder="付款時點與條件" />
              <span className="mono paymoney">NT$ {window.fmtNum(dep)}</span>
            </div>}
            <div className="payrow">
              <div className="paypct"><span>{depPct > 0 ? '尾款' : '全額'}</span><input className="miniinp" style={{ width: 54 }} type="number" value={io.balPct} onChange={(e) => set({ balPct: +e.target.value })} /><span>%</span></div>
              <input className="miniinp" style={{ flex: 1 }} value={io.payBal} onChange={(e) => set({ payBal: e.target.value })} placeholder="付款時點與條件" />
              <span className="mono paymoney">NT$ {window.fmtNum(depPct > 0 ? bal : total)}</span>
            </div>
            {depPct + balPct !== 100 && <div className="faint" style={{ fontSize: 10.5, color: 'var(--rose-ink)' }}>＊訂金＋尾款目前為 {depPct + balPct}%，建議調整為 100%。</div>}
          </div>

          {/* 條款（可編輯）*/}
          <div className="iosect">注意事項與服務條款
            <span className="secttools">
              <button className="linkbtn" onClick={() => set({ clauses: [...io.clauses, { h: '新增條款', body: '' }] })}>＋ 新增條款</button>
              <button className="linkbtn" onClick={() => {set({ clauses: window.IO_CLAUSES.map((cl) => ({ h: cl.h, body: cl.body.replace('NT$ 　', 'NT$ ＿＿ ') })) });toast('已還原為範本條款');}}>↺ 還原範本</button>
            </span>
          </div>
          <div className="clauses">
            {io.clauses.map((cl, i) =>
            <div key={i} className="clause edit">
                <div className="clausehd">
                  <input className="cellinp" style={{ fontWeight: 700, flex: 1 }} value={cl.h} onChange={(e) => set({ clauses: io.clauses.map((x, k) => k === i ? { ...x, h: e.target.value } : x) })} />
                  <button className="rowdel" onClick={() => set({ clauses: io.clauses.filter((_, k) => k !== i) })} title="刪除條款">✕</button>
                </div>
                <textarea className="clauseta" rows={3} value={cl.body} onChange={(e) => set({ clauses: io.clauses.map((x, k) => k === i ? { ...x, body: e.target.value } : x) })} />
              </div>
            )}
          </div>

          {/* 帳號資料 */}
          <div className="iosect">匯款帳號資料</div>
          <div className="iotwo">
            <BankBlock title="甲方匯款帳號" bank={io.bankA} onChange={(b) => set({ bankA: b })} />
            <BankBlock title="乙方收款帳號" bank={io.bankB} onChange={(b) => set({ bankB: b })} accent />
          </div>
          <div className="faint" style={{ fontSize: 10, marginTop: 7, lineHeight: 1.5 }}>＊甲方應以「甲方匯款帳號」將款項匯至乙方帳戶；若未使用該帳號匯款，乙方有權退回並要求重新匯款，所生費用由甲方承擔。</div>

          {/* 簽章 */}
          <div className="signrow">
            <div className="signbox">
              <div className="faint" style={{ fontSize: 10, marginBottom: 6 }}>甲方簽章（已同意並詳閱上述內容）</div>
              <input className="signinp" value={io.signA} placeholder="甲方簽署" onChange={(e) => set({ signA: e.target.value })} />
            </div>
            <div className="signbox">
              <div className="faint" style={{ fontSize: 10, marginBottom: 6 }}>乙方簽章</div>
              <input className="signinp" value={io.signB} placeholder="乙方簽署" onChange={(e) => set({ signB: e.target.value })} />
            </div>
          </div>
          {io.driveFolderUrl && (
            <div className="sagebox" style={{marginTop:16}}>
              <span style={{color:'var(--sage-ink)',fontSize:16}}>📁</span>
              <div>
                <div style={{fontSize:12,fontWeight:600,color:'var(--sage-ink)'}}>雲端硬碟資料夾已建立</div>
                <a href={io.driveFolderUrl} target="_blank" rel="noreferrer" style={{fontSize:11,color:'var(--sage-ink)',wordBreak:'break-all'}}>{io.driveFolderUrl}</a>
              </div>
            </div>
          )}
        </div>
      </div>
      <div className="tabfoot">
        <button className="btn" onClick={() => {exportIODoc(c, { sub, tax, total, dep, bal });toast('已匯出 .doc · 上傳 Google 雲端硬碟即可用 Google 文件編輯');}}>↧ 匯出可編輯文件（.doc）</button>
        <button className="btn" onClick={() => {exportIOPdf(c, { sub, tax, total, dep, bal }, toast);}}>↧ 輸出 PDF</button>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginLeft: 14 }}>
          <span className="faint" style={{ fontSize: 11 }}>懲罰性違約金 NT$</span>
          <input className="miniinp" style={{ width: 90 }} type="number" value={io.penalty} placeholder="如 50000" onChange={(e) => set({ penalty: e.target.value })} />
        </div>
        {!io.signed ?
        <button className="btn primary" style={{ marginLeft: 'auto' }} onClick={() => {sign();onNext();}}>標記已簽署 · 進入溝通表 →</button> :
        <button className="btn primary" style={{ marginLeft: 'auto' }} onClick={onNext}>下一步：填寫溝通表 →</button>}
      </div>
    </div>);

}

/* ---------- 委刊單 HTML 內文（共用於 .doc / PDF，排版貼近畫面）---------- */
function buildIOHtml(c, totals, forPrint) {
  const S = window.STUDIO;const io = c.io;
  const esc = (s) => String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
  const money = (n) => 'NT$ ' + window.fmtNum(n);
  const line = (k, v) => `<div class="ln"><span class="lk">${esc(k)}</span><span class="lv">${esc(v) || '　'}</span></div>`;
  const itemRows = (io.items || []).map((it) => {const t = Math.round((Number(it.fee) || 0) * 0.05);
    return `<tr><td>${esc(it.name)}</td><td class="r">${window.fmtNum(it.fee)}</td><td class="r dim">${window.fmtNum(t)}</td><td class="r">${window.fmtNum((Number(it.fee) || 0) + t)}</td></tr>`;}).join('');
  const payRows = (io.depPct > 0 ?
  [[`訂金（${esc(io.depPct)}%）`, io.payDep, totals.dep], [`尾款（${esc(io.balPct)}%）`, io.payBal, totals.bal]] :
  [[`全額（100%）`, io.payBal, totals.total]]).
  map(([t, cond, amt]) => `<tr><td style="width:120px"><b>${t}</b></td><td>${esc(cond)}</td><td class="r"><b>${money(amt)}</b></td></tr>`).join('');
  const clauseRows = (io.clauses || []).map((cl) => `<div class="cl"><div class="clh">${esc(cl.h)}</div><div class="clb">${esc(cl.body).replace(/\n/g, '<br/>')}</div></div>`).join('');
  const bank = (b) => `${line('戶名', b.holder)}${line('銀行', b.bank + (b.code ? `（${esc(b.code)}）` : ''))}${line('帳號', b.acct)}`;
  const printCss = forPrint ? '@page{size:A4;margin:14mm;}' : '';
  return `<!DOCTYPE html><html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-html40"><head><meta charset="utf-8"><title>廣告委刊單</title>
<style>${printCss}
*{box-sizing:border-box;}
body{font-family:"Noto Sans TC","新細明體",sans-serif;font-size:10.5pt;color:#222;line-height:1.6;margin:0;background:#fff;}
.band{display:flex;justify-content:space-between;align-items:flex-start;border-bottom:2px solid #333;padding-bottom:12px;margin-bottom:16px;}
.band h1{font-size:21pt;letter-spacing:3px;margin:0;font-weight:900;color:#111;}
.band .en{color:#999; font-size:8pt;letter-spacing:2px;margin-top:2px;}
.band .nm{font-size:10.5pt;margin-top:6px;}
.band .rt{text-align:right;font-size:9.5pt;color:#666;}
.badge{display:inline-block;margin-top:6px;padding:2px 10px;border-radius:20px;font-size:8.5pt;font-weight:700;border:1px solid #999;color:#444;}
.two{display:flex;gap:12px;margin-bottom:6px;}
.box{flex:1;border:1px solid #bbb;border-radius:6px;padding:11px 13px;background:#fff;}
.box .bh{font-weight:700;font-size:9.5pt;color:#333;border-bottom:1px solid #ddd;padding-bottom:5px;margin-bottom:7px;}
.ln{display:flex;font-size:9.5pt;padding:2px 0;}
.lk{width:66px;color:#999;flex:none;} .lv{flex:1;color:#222;}
.sect{font-weight:700;font-size:11pt;color:#111;margin:16px 0 7px;padding-left:9px;border-left:3px solid #333;}
table{border-collapse:collapse;width:100%;font-size:9.5pt;}
th,td{border:1px solid #bbb;padding:6px 9px;background:#fff;} th{background:#eee;color:#444;font-weight:600;text-align:left;}
td.r,th.r{text-align:right;font-variant-numeric:tabular-nums;} td.dim{color:#999;}
tr.tot td{background:#fff;font-weight:700;}
.cl{margin-bottom:8px;} .clh{font-weight:700;font-size:9.5pt;color:#222;} .clb{font-size:9pt;color:#555;margin-top:2px;}
.penal{margin-top:8px;font-size:9.5pt;color:#333;}
.note{font-size:8.5pt;color:#999;margin-top:6px;line-height:1.5;}
.sign{display:flex;gap:12px;margin-top:22px;}
.sbox{flex:1;border:1px solid #bbb;border-radius:6px;padding:12px 14px;min-height:150px;background:#fff;}
.sbox .sl{font-size:8.5pt;color:#999;margin-bottom:8px;}
.sbox .sv{font-size:13pt;color:#111;min-height:100px;}
</style></head><body>
<div class="band">
  <div><h1>廣告委刊單</h1><div class="en">INSERTION ORDER</div><div class="nm">案件名稱：<b>${esc(S.creator)} ✕ ${esc(c.vendor)}</b></div></div>
  <div class="rt">編號 ${esc(io.number)}<br/>申請日期 ${esc(io.date) || '＿＿＿＿'}</div>
</div>
<div class="two">
  <div class="box"><div class="bh">委刊方（甲方）</div>${line('公司名稱', c.vendor)}${line('發票抬頭', io.invoiceTitle)}${line('統一編號', io.taxId)}${line('聯絡地址', io.addr)}${line('聯絡人', c.contact + ' · ' + (c.contactRole || ''))}${line('聯絡電話', io.tel)}${line('E-mail', io.email)}</div>
  <div class="box"><div class="bh">受託方（乙方）</div>${line('公司名稱', S.name)}${line('發票抬頭', S.invoiceTitle)}${line('統一編號', S.taxId)}${line('聯絡地址', S.addr)}${line('聯絡人', S.contact)}${line('聯絡電話', S.tel)}${line('E-mail', S.email)}</div>
</div>
<div class="sect">合作內容</div>
<table><tr><th>項目</th><th class="r">廣告費</th><th class="r">稅金 5%</th><th class="r">小計</th></tr>
${itemRows}
<tr class="tot"><td>總計（含稅）</td><td class="r">${window.fmtNum(totals.sub)}</td><td class="r">${window.fmtNum(totals.tax)}</td><td class="r">${money(totals.total)}</td></tr></table>
<div class="sect">付款方式</div>
<table class="paytb">${payRows}</table>
<div class="sect">注意事項與服務條款</div>
${clauseRows}
${io.penalty ? `<div class="penal">懲罰性違約金：${money(io.penalty)}</div>` : ''}
<div class="sect">匯款帳號資料</div>
<div class="two">
  <div class="box"><div class="bh">甲方匯款帳號</div>${bank(io.bankA)}</div>
  <div class="box"><div class="bh">乙方收款帳號</div>${bank(io.bankB)}</div>
</div>
<div class="note">＊甲方應以「甲方匯款帳號」將款項匯至乙方帳戶；若未使用該帳號匯款，乙方有權退回並要求重新匯款，所生費用由甲方承擔。</div>
<div class="sign">
  <div class="sbox"><div class="sl">甲方簽章（簽署並加蓋公司大小章）</div><div class="sv"></div></div>
  <div class="sbox"><div class="sl">乙方簽章（簽署並加蓋公司大小章）</div><div class="sv"></div></div>
</div>
${forPrint ? '' : '<p class="note">＊本文件可上傳至 Google 雲端硬碟，以 Google 文件開啟後即可線上編輯。'}
</body></html>`;
}

/* ---------- 匯出可編輯 .doc（Google 文件可開啟編輯）---------- */
function exportIODoc(c, totals) {
  const html = buildIOHtml(c, totals, false);
  const blob = new Blob(['\ufeff' + html], { type: 'application/msword' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');a.href = url;a.download = `委刊單_${c.vendor}_${c.io.number}.doc`;
  document.body.appendChild(a);a.click();
  setTimeout(() => {document.body.removeChild(a);URL.revokeObjectURL(url);}, 200);
}

/* ---------- 輸出 PDF（開啟列印視窗，選「儲存為 PDF」）---------- */
function exportIOPdf(c, totals, toast) {
  const win = window.open('', '_blank');
  if (!win || !win.document) {toast && toast('請允許彈出視窗以列印 PDF');return;}
  win.document.write(buildIOHtml(c, totals, true));
  win.document.close();
  setTimeout(() => {win.focus();win.print();}, 350);
  toast && toast('已開啟列印視窗，選「儲存為 PDF」即可');
}

window.InsertionOrderTab = InsertionOrderTab;
window.qItems = qItems;window.exportIODoc = exportIODoc;window.exportIOPdf = exportIOPdf;
window.ioTotals = ioTotals;window.payPlan = payPlan;window.paySummary = paySummary;
window.isCompleted = isCompleted;window.invoiceSegments = invoiceSegments;

// ── 月報表：依實際入帳日期匯總收款，計算 15% 抽成與結餘 ──
const COMMISSION_RATE = 0.15;
function parsePayMonth(dateStr) {// '2026/05/20' -> {y:2026,m:5}
  const m = String(dateStr || '').match(/(\d{4})[\/-](\d{1,2})/);
  return m ? { y: +m[1], m: +m[2] } : null;
}
// 收集所有已入帳款項（含案名、款項別、金額、年月）
function allReceipts(cases) {
  const out = [];
  cases.forEach((c) => {
    if (c.progress === '婉拒' || c.progress === '未成交') return;
    const { plan } = payPlan(c);
    plan.forEach((p) => {
      const pay = (c.pay || {})[p.key];
      if (pay && pay.paid && pay.date) {
        const ym = parsePayMonth(pay.date);
        if (ym) out.push({ id: c.id, vendor: c.vendor, product: c.product, seg: p.label, amount: p.amount, date: pay.date, y: ym.y, m: ym.m });
      }
    });
  });
  return out;
}
// 合併同一案件在同月的多筆收款為一列
function monthlyReport(cases, year, month) {
  const recs = allReceipts(cases).filter((r) => r.y === year && r.m === month);
  const byCase = {};
  recs.forEach((r) => {
    if (!byCase[r.id]) byCase[r.id] = { id: r.id, vendor: r.vendor, product: r.product, amount: 0, segs: [] };
    byCase[r.id].amount += r.amount;byCase[r.id].segs.push(r.seg);
  });
  const rows = Object.values(byCase).map((x) => {
    const commission = Math.round(x.amount * COMMISSION_RATE);
    return { ...x, commission, net: x.amount - commission };
  }).sort((a, b) => b.amount - a.amount);
  const total = rows.reduce((s, r) => s + r.amount, 0);
  const totalCommission = rows.reduce((s, r) => s + r.commission, 0);
  return { rows, total, totalCommission, totalNet: total - totalCommission };
}
// 年報表：按月匯總
function annualReport(cases, year) {
  const recs = allReceipts(cases).filter((r) => r.y === year);
  const months = [];
  for (let m = 1; m <= 12; m++) {
    const mr = recs.filter((r) => r.m === m);
    const amount = mr.reduce((s, r) => s + r.amount, 0);
    const commission = Math.round(amount * COMMISSION_RATE);
    months.push({ m, amount, commission, net: amount - commission, count: new Set(mr.map((r) => r.id)).size });
  }
  const total = months.reduce((s, r) => s + r.amount, 0);
  const totalCommission = months.reduce((s, r) => s + r.commission, 0);
  return { months, total, totalCommission, totalNet: total - totalCommission };
}
// 資料內存在的所有（年,月）選項
function availablePeriods(cases) {
  const set = new Set();const years = new Set();
  allReceipts(cases).forEach((r) => {set.add(r.y + '-' + r.m);years.add(r.y);});
  return { keys: [...set], years: [...years].sort((a, b) => b - a) };
}
Object.assign(window, { COMMISSION_RATE, allReceipts, monthlyReport, annualReport, availablePeriods });