// contract-doc.jsx — Hợp đồng (bản in / xuất Word) sinh từ 1 hợp đồng, theo mẫu sửa được ở Cài đặt HĐ.
// Mẫu hệ thống dựng theo HỢP ĐỒNG MUA BÁN chuẩn của S.W.O (Bên A = Bên MUA, Bên B = Bên BÁN).
// Tái dùng helper chứng từ chung (payment-request.jsx): docCompany / docFontStack / docVars /
// renderDocText / docHeaderMotto / docHeaderNote / docFooter / printDocument / docTienChu.
// Bảng hàng hoá & lịch thanh toán được chèn qua MARKER {BANG_HANG_HOA} / {LICH_THANH_TOAN} trong Điều khoản
// → các Điều vẫn sửa được tự do, bảng tự điền từ dữ liệu hợp đồng.

const DEFAULT_CONTRACT_DOC_TITLE = 'HỢP ĐỒNG MUA BÁN';
const DEFAULT_CONTRACT_DOC_INTRO =
  'Căn cứ Bộ luật Dân sự số 91/2015/QH13 ngày 24/11/2015;\n' +
  'Căn cứ Luật Thương mại số 36/2005/QH11 ngày 14/6/2005;\n' +
  'Căn cứ vào năng lực kinh doanh và nhu cầu của hai Bên.\n' +
  'Hôm nay, {NGAY}, hai Bên gồm:';
const DEFAULT_CONTRACT_DOC_TERMS =
  'ĐIỀU 1: ĐỐI TƯỢNG CỦA HỢP ĐỒNG\n' +
  'Bên A đồng ý mua của Bên B các hàng hoá/dịch vụ theo bảng dưới đây:\n' +
  '{BANG_HANG_HOA}\n\n' +
  'ĐIỀU 2: THỜI GIAN & ĐỊA ĐIỂM GIAO HÀNG\n' +
  '2.1 Thời gian giao hàng: theo thoả thuận giữa hai Bên, sau khi Bên A hoàn tất thanh toán đợt 1 nêu tại Điều 3.\n' +
  '2.2 Địa điểm giao hàng: theo địa chỉ do Bên A cung cấp.\n' +
  '2.3 Chứng từ giao hàng: Bên B cung cấp cho Bên A các giấy tờ liên quan đến hàng hoá (CO/CQ hoặc giấy tờ bản quyền nếu có), Biên bản bàn giao và Hoá đơn giá trị gia tăng.\n\n' +
  'ĐIỀU 3: THỜI HẠN & PHƯƠNG THỨC THANH TOÁN\n' +
  'Bên A thanh toán cho Bên B theo lịch thanh toán dưới đây, bằng chuyển khoản vào tài khoản của Bên B: {NGANHANG} — {STK}.\n' +
  '{LICH_THANH_TOAN}\n\n' +
  'ĐIỀU 4: CHUYỂN RỦI RO & QUYỀN SỞ HỮU HÀNG HOÁ\n' +
  '4.1 Rủi ro về mất mát, hư hỏng hàng hoá được chuyển cho Bên A khi hàng hoá được giao cho Bên A hoặc người được Bên A uỷ quyền tại địa điểm giao nhận.\n' +
  '4.2 Quyền sở hữu hàng hoá được chuyển từ Bên B sang Bên A khi Bên A hoàn thành toàn bộ nghĩa vụ thanh toán cho Bên B.\n\n' +
  'ĐIỀU 5: TRÁCH NHIỆM CỦA HAI BÊN\n' +
  '5.1 Bên B: giao hàng đúng số lượng, chất lượng, thời gian và địa điểm; cung cấp đầy đủ hồ sơ, chứng từ (hoá đơn GTGT, biên bản bàn giao, bảo hành); bảo hành theo chính sách của hãng/thiết bị.\n' +
  '5.2 Bên B bảo đảm hàng hoá hợp pháp, không bị tranh chấp bởi bên thứ ba và việc chuyển giao hàng hoá là hợp pháp.\n' +
  '5.3 Bên A: nhận hàng đúng thời hạn và phối hợp hợp lý để Bên B giao hàng; thanh toán đầy đủ, đúng hạn theo Điều 3; sử dụng và bảo quản hàng hoá đúng quy định.\n\n' +
  'ĐIỀU 6: ĐIỀU KIỆN BẢO HÀNH\n' +
  '6.1 Được bảo hành: lỗi kỹ thuật của nhà sản xuất; hàng hoá còn tem niêm phong và phiếu bảo hành; thiết bị còn trong thời hạn hiệu lực bản quyền/license (nếu có).\n' +
  '6.2 Không được bảo hành: lỗi do người sử dụng sai quy cách (rơi vỡ, vô nước…); sử dụng sai hướng dẫn; hư hỏng do côn trùng, thiên tai, sét đánh; hết hiệu lực bản quyền/license.\n\n' +
  'ĐIỀU 7: GIẢI QUYẾT TRANH CHẤP\n' +
  '7.1 Khi phát sinh tranh chấp, hai Bên ưu tiên tự thương lượng, hoà giải. Nếu không đạt được, vụ việc sẽ được đưa ra Toà án có thẩm quyền giải quyết theo quy định pháp luật.\n' +
  '7.2 Trong quá trình giải quyết tranh chấp, hai Bên vẫn tiếp tục thực hiện hợp đồng, trừ khi có thoả thuận tạm ngừng hoặc chấm dứt.\n\n' +
  'ĐIỀU 8: ĐIỀU KHOẢN THI HÀNH\n' +
  '8.1 Hai Bên cam kết thi hành đúng và đầy đủ các điều khoản đã ký.\n' +
  '8.2 Bên vi phạm gây thiệt hại cho Bên kia thì ngoài việc bị phạt vi phạm còn phải bồi thường toàn bộ thiệt hại.\n' +
  '8.3 Hợp đồng có hiệu lực kể từ ngày ký đến khi hai Bên hoàn tất trách nhiệm và tự thanh lý. Hợp đồng được lập thành 02 (hai) bản có giá trị pháp lý như nhau, mỗi Bên giữ 01 (một) bản.';
const DEFAULT_CONTRACT_DOC_SIGN_A = 'BÊN A';
const DEFAULT_CONTRACT_DOC_SIGN_B = 'BÊN B';

function contractDocTemplate(S, c){
  S = S || {};
  // Lời mở đầu / điều khoản soạn RIÊNG cho từng HĐ (c.docOverrides) ghi đè mẫu CHUNG; vắng → dùng mẫu chung.
  const ovr = (c && c.docOverrides) || {};
  return {
    title:      (S.contractDocTitle || '').trim() || DEFAULT_CONTRACT_DOC_TITLE,
    subtitle:   (S.contractDocSubtitle != null ? S.contractDocSubtitle : ''),   // phụ đề dưới tiêu đề (tuỳ chọn)
    intro:      (ovr.intro != null ? ovr.intro : (S.contractDocIntro != null ? S.contractDocIntro : DEFAULT_CONTRACT_DOC_INTRO)),
    terms:      (ovr.terms != null ? ovr.terms : (S.contractDocTerms != null ? S.contractDocTerms : DEFAULT_CONTRACT_DOC_TERMS)),
    signA:      (S.contractDocSignA || '').trim() || DEFAULT_CONTRACT_DOC_SIGN_A,
    signB:      (S.contractDocSignB || '').trim() || DEFAULT_CONTRACT_DOC_SIGN_B,
    showMotto:  docFlag(S.contractDocShowMotto, true),
    mottoTitle: (S.contractDocMottoTitle || '').trim() || DEFAULT_DOC_MOTTO_TITLE,
    mottoSub:   (S.contractDocMottoSub != null ? S.contractDocMottoSub : DEFAULT_DOC_MOTTO_SUB),
    mottoBelow: docFlag(S.contractDocMottoBelow, true),         // mặc định: Quốc hiệu căn giữa TRÊN tiêu đề (đúng mẫu)
    partiesStacked: docFlag(S.contractDocPartiesStacked, true), // mặc định: Bên A/B xếp trên–dưới (đúng mẫu)
    headerNote: (S.contractDocHeaderNote != null ? S.contractDocHeaderNote : ''),
    footer:     (S.contractDocFooter != null ? S.contractDocFooter : DEFAULT_DOC_FOOTER),
  };
}

/* c: hợp đồng · party: bên đối tác (KH/NCC) · rep: người đại diện đối tác · branding · S: app_settings */
function contractDocHTML(c, party, rep, branding, S){
  S = S || {};
  const co = docCompany(branding);
  const tpl = contractDocTemplate(S, c);
  const ovr = (c && c.docOverrides) || {};
  // Mẫu v2 (2 cột): header 2 vùng + điều khoản dạng mục + rich. Per-HĐ override (ovr.intro/terms) vẫn THẮNG.
  const V = docTpl(S, 'contract', { title:tpl.title, subtitle:tpl.subtitle, intro:tpl.intro, terms:tpl.terms, signA:tpl.signA, signB:tpl.signB, footer:(S.contractDocFooter != null ? S.contractDocFooter : DEFAULT_DOC_FOOTER), stackedKey:'contractDocPartiesStacked' });
  const logoSz = (V.header || {}).logoSize;
  const buy = (window.contractDir && contractDir(c) === 'buy');
  // Bên A = Bên MUA; Bên B = Bên BÁN. Bán → A là khách hàng, B là công ty (có TK). Mua → A là công ty, B là NCC.
  // Người đại diện: BÊN MÌNH (công ty) lấy từ Cài đặt (S.contractRep*); BÊN ĐỐI TÁC lấy từ Liên hệ (rep) + uỷ quyền riêng HĐ (ovr.partyAuth).
  const pAuth = ovr.partyAuth || null;
  const company = { name:co.name, mst:co.mst, addr:co.addr, phone:co.phone, email:co.email, bank:co.bank, stk:co.stk,
    rep:(S.contractRepName || ''), title:(S.contractRepTitle || ''),
    auth:docFlag(S.contractRepAuth, false), authNo:(S.contractRepAuthNo || ''), authDate:(S.contractRepAuthDate || '') };
  const other   = { name:party.name, mst:party.mst, addr:party.address, phone:party.phone, email:party.email, bank:party.bank, stk:party.stk,
    rep:(rep.name || ''), title:(rep.title || ''),
    auth:!!pAuth, authNo:(pAuth && pAuth.no) || '', authDate:(pAuth && pAuth.date) || '' };
  const A = buy ? company : other;   // Bên mua
  const B = buy ? other : company;   // Bên bán
  const docNo = c.contractNo || c.code;
  const dateLine = docDateVN(c.signDate || TODAY);
  const tot = contractTotals(c);
  const vars = docVars({ co, party, docNo, date:dateLine, contract:c });
  const esc = docEsc;
  // rich (HTML từ RichEditor) → giữ markup + thay biến; plain (mẫu cũ có \n) → escape + <br>.
  const renderRP = (src) => /<[a-z][\s\S]*>/i.test(src || '') ? renderRichVars(src, vars, co, logoSz) : docTextToHtml(src, vars);
  const num = (n) => vnd(n).replace('₫', '').trim();
  const itemRows = (c.items || []).map((it, i) => {
    const line = (it.qty || 0) * (it.price || 0);
    // "Hiển thị chi tiết" (bật ở form HĐ, giống báo giá) → dòng mô tả nhỏ dưới tên hàng.
    const det = (it.showDetail && (it.detail || '').trim()) ? `<div style="font-size:.85em;color:#54657F;white-space:pre-line;margin-top:3px">${esc(it.detail)}</div>` : '';
    return `<tr><td style="text-align:center">${i + 1}</td><td>${esc(it.name)}${det}</td><td style="text-align:center">${esc(it.unit)}</td>`
      + `<td class="num">${it.qty}</td><td class="num">${num(it.price)}</td><td class="num">${it.vat || 0}%</td><td class="num">${num(line)}</td></tr>`;
  }).join('');
  const schedRows = (c.schedule || []).map(s =>
    `<tr><td style="text-align:center">${s.no}</td><td>${esc(s.condition || '')}</td><td style="text-align:center">${fmtDate(s.dueDate)}</td><td class="num">${num(s.amount)}</td></tr>`).join('');

  // Bảng hàng hoá (+ tổng + bằng chữ) và bảng lịch thanh toán — chèn vào Điều khoản qua marker.
  const itemsTable = `<table class="ic-items">
    <thead><tr><th style="width:34px">STT</th><th>Hạng mục</th><th style="width:64px">ĐVT</th><th class="num" style="width:48px">SL</th><th class="num" style="width:96px">Đơn giá</th><th class="num" style="width:48px">VAT</th><th class="num" style="width:110px">Thành tiền</th></tr></thead>
    <tbody>${itemRows || '<tr><td colspan="7" style="text-align:center;color:#98A2B3">—</td></tr>'}</tbody>
    <tfoot>
      <tr><td colspan="6" class="num">Cộng tiền hàng</td><td class="num">${num(tot.sub)}</td></tr>
      <tr><td colspan="6" class="num">Thuế VAT</td><td class="num">${num(tot.vat)}</td></tr>
      <tr><td colspan="6" class="num">TỔNG CỘNG (VNĐ)</td><td class="num" style="color:#1466E0">${num(tot.total)}</td></tr>
    </tfoot>
  </table>
  <div class="words">Bằng chữ: ${docTienChu(tot.total)}.</div>`;
  const schedTable = schedRows ? `<table class="ic-sched">
    <thead><tr><th style="width:44px">Đợt</th><th>Điều kiện / nội dung</th><th style="width:110px">Ngày đến hạn</th><th class="num" style="width:130px">Số tiền (VNĐ)</th></tr></thead>
    <tbody>${schedRows}</tbody>
  </table>` : '<div class="muted-line">(Lịch thanh toán theo thoả thuận / báo giá đính kèm.)</div>';

  // Nguồn lời mở đầu / điều khoản: per-HĐ override THẮNG (nếu có), else mẫu v2.
  const introSrc = (ovr.intro != null) ? ovr.intro : V.intro;
  const termsSrc = (ovr.terms != null) ? ovr.terms : V.terms;
  const resolveTables = (h) => String(h).replace(/\{BANG_HANG_HOA\}/g, itemsTable).replace(/\{LICH_THANH_TOAN\}/g, schedTable);
  // v2: mảng {title, content} → mỗi mục 1 .clause (tiêu đề đậm + nội dung rich, chèn bảng qua mã).
  // legacy: chuỗi có marker → tách bảng như cũ (giữ tương thích HĐ có điều khoản riêng dạng cũ).
  const termsHtml = Array.isArray(termsSrc)
    ? termsSrc.map(tm => `<div class="clause">${(tm.title || '').trim() ? `<div class="cl-title">${esc(tm.title)}</div>` : ''}<div class="cl-body">${resolveTables(renderRP(tm.content || ''))}</div></div>`).join('')
    : String(termsSrc || '').split(/(\{BANG_HANG_HOA\}|\{LICH_THANH_TOAN\})/).map(seg => {
        if (seg === '{BANG_HANG_HOA}') return itemsTable;
        if (seg === '{LICH_THANH_TOAN}') return schedTable;
        const body = seg.replace(/^\n+|\n+$/g, '');
        if (!body.trim()) return '';
        return `<div class="clause"><div class="cl-body">${renderRP(body)}</div></div>`;
      }).join('');

  const guqNote = (d) => d.auth ? ` (theo Giấy uỷ quyền số ${esc(d.authNo || '—')}${d.authDate ? ' ngày ' + fmtDate(d.authDate) : ''})` : '';
  const partyBlock = (lbl, d) =>
    `<div class="pb"><div class="pl">${lbl}</div>
      <div class="pr"><b>${esc(d.name) || '—'}</b></div>
      ${d.addr ? `<div class="pr">Địa chỉ: ${esc(d.addr)}</div>` : ''}
      ${d.mst ? `<div class="pr">MST: ${esc(d.mst)}</div>` : ''}
      ${(d.phone || d.email) ? `<div class="pr">${d.phone ? 'ĐT: ' + esc(d.phone) : ''}${(d.phone && d.email) ? ' · ' : ''}${d.email ? esc(d.email) : ''}</div>` : ''}
      ${(d.bank || d.stk) ? `<div class="pr">Số TK: ${esc(d.stk || '')}${(d.bank && d.stk) ? ' — ' : ''}${esc(d.bank || '')}</div>` : ''}
      ${d.rep ? `<div class="pr">Đại diện: <b>${esc(d.rep)}</b>${d.title ? ' — ' + esc(d.title) : ''}${guqNote(d)}</div>` : ''}</div>`;

  return `<!DOCTYPE html><html lang="vi"><head><meta charset="utf-8"><title>${esc(docNo)}</title>
<style>
@page{size:A4;margin:16mm}
${DOC_PAGENUM_CSS}
${DOC_HEAD2_CSS}
*{box-sizing:border-box}
html{background:#fff;color-scheme:light}
body{font-family:${docFontStack(co)};color:#0A1730;background:#fff;font-size:13px;line-height:1.55;margin:0;color-scheme:light}
.doc{max-width:720px;margin:0 auto;padding:8px}
.head{display:flex;justify-content:space-between;align-items:flex-start;border-bottom:2px solid #1466E0;padding-bottom:10px;margin-bottom:6px}
.co{display:flex;gap:10px;align-items:center}
.mark{width:40px;height:40px;border-radius:11px;background:linear-gradient(135deg,#12C5C0,#1466E0);color:#fff;display:flex;flex-direction:column;align-items:center;justify-content:center;font-weight:800;font-size:13px;letter-spacing:.5px}
.mark i{width:60%;height:2px;background:rgba(255,255,255,.9);border-radius:1px;margin-top:2px;display:block}
.mark-img{width:46px;height:46px;object-fit:contain;border-radius:8px}
/* Cỡ chữ NỀN = .doc (docDocStyle, docFontSize pt) — body text KHÔNG đặt px, phân cấp bằng em → KHÔNG nhảy font.
   Riêng KHỐI ĐẦU TRANG (letterhead công ty + Quốc hiệu) giữ px nhỏ CỐ ĐỊNH (không scale theo cỡ nền) để khỏi tràn dòng. */
.co .n{font-weight:700;font-size:14px}
.co .m{font-size:11px;color:#54657F}
.natl{text-align:center;font-size:11px;color:#54657F}
.natl b{color:#0A1730}
.natl.below{margin:8px 0 2px;font-size:12px}
h1{text-align:center;font-size:1.55em;letter-spacing:.5px;margin:18px 0 2px;color:#0A1730}
.docsub{text-align:center;font-size:.85em;color:#54657F;margin:-2px 0 4px}
.docno{text-align:center;font-size:.85em;color:#54657F;margin-bottom:14px}
.intro{margin:10px 0}
.parties{display:flex;gap:14px;margin:10px 0}
.parties.stacked{flex-direction:column}
.pb{flex:1;border:1px solid #D0D5DD;border-radius:8px;padding:10px 12px}
.pb .pl{font-weight:700;color:#1466E0;margin-bottom:4px}
.pb .pr{margin:1px 0}
.lead{margin:12px 0 6px}
.clause{margin:10px 0}
.cl-title{font-weight:700;margin:12px 0 3px;color:#0A1730}
.cl-body{margin:0}
table{width:100%;border-collapse:collapse;margin:8px 0;white-space:normal}
th,td{border:1px solid #D0D5DD;padding:7px 9px;text-align:left;vertical-align:top}
th{background:#EAF1FE;font-weight:700}
td.num,th.num{text-align:right;font-variant-numeric:tabular-nums}
tfoot td{font-weight:700;background:#F6F9FD}
.words{font-style:italic;margin:6px 0}
.muted-line{font-style:italic;color:#54657F;margin:6px 0}
.sign{display:flex;justify-content:space-between;margin-top:30px;text-align:center}
.sign>div{width:45%}
.sign .role{font-weight:700}
.sign .note{font-size:.8em;color:#54657F;font-style:italic}
.sign .space{height:74px}
.foot{margin-top:24px;border-top:1px solid #E3E6EC;padding-top:8px;font-size:.8em;color:#98A2B3;text-align:center;white-space:normal}
${DOC_HDRNOTE_CSS}
@media print{.no-print{display:none!important}.doc{max-width:none;margin:0;padding:0}}
</style></head>
<body><div class="doc" style="${docTplStyle(co, V)}">
  ${docHeader2(co, S, V.header, vars)}

  <h1>${esc(V.title || tpl.title)}</h1>
  ${(V.subtitle || '').trim() ? `<div class="docsub">${esc(V.subtitle)}</div>` : ''}
  <div class="docno">Số: ${esc(docNo)} &nbsp;·&nbsp; ${dateLine}</div>

  <div class="intro">${renderRP(introSrc)}</div>

  <div class="parties${V.partiesStacked ? ' stacked' : ''}">
    ${partyBlock('BÊN A (Bên mua)', A)}
    ${partyBlock('BÊN B (Bên bán)', B)}
  </div>

  <div class="lead">Sau khi bàn bạc và thống nhất, hai Bên cùng nhau ký hợp đồng này theo các điều khoản và điều kiện sau đây:</div>

  ${termsHtml}

  <div class="sign">
    <div><div class="role">${esc(V.signA || tpl.signA)}</div><div class="note">(Ký tên, đóng dấu)</div><div class="space"></div>${A.rep ? `<div><b>${esc(A.rep)}</b></div>` : ''}</div>
    <div><div class="role">${esc(V.signB || tpl.signB)}</div><div class="note">(Ký tên, đóng dấu)</div><div class="space"></div>${B.rep ? `<div><b>${esc(B.rep)}</b></div>` : ''}</div>
  </div>

  <div class="foot">${renderRP(V.footer)}</div>
</div></body></html>`;
}

function ContractDocModal({ contract, versionLabel, onClose }){
  const p = usePortal();
  const { t, lang } = useLang();
  const toast = useToast();
  const party = (window.contractDir && contractDir(contract) === 'buy')
    ? ((window.VendorStore && VendorStore.byCode(contract.customer)) || {})
    : ((window.CustomerStore && CustomerStore.byCode(contract.customer)) || {});
  const rep = contract.rep && window.ContactStore ? (ContactStore.byCode(contract.rep) || {}) : {};
  const html = contractDocHTML(contract, party, rep, p.branding, p.appSettings);
  const docNo = contract.contractNo || contract.code;
  const doPrint = () => { if (!printDocument(html)) toast(lang === 'vi' ? 'Trình duyệt chặn cửa sổ in — hãy cho phép pop-up' : 'Pop-up blocked — allow pop-ups', 'error'); };
  return (
    <Modal title={(lang === 'vi' ? 'Hợp đồng · ' : 'Contract · ') + docNo + (versionLabel ? ' · ' + versionLabel : '')} width={860} onClose={onClose}
      footer={<><div className="grow flex g8 items-center subtle" style={{ fontSize:'var(--fs-sm)' }}><i className="bi bi-eye"></i>{lang === 'vi' ? 'Mẫu sửa ở Cài đặt → tab Hợp đồng' : 'Edit template in Settings → Contract tab'}</div>
        <button className="btn" onClick={onClose}>{t('c.close')}</button>
        <button className="btn btn-primary" onClick={doPrint}><i className="bi bi-filetype-pdf"></i>{lang === 'vi' ? 'In / Lưu PDF' : 'Print / PDF'}</button></>}>
      <iframe title="preview" srcDoc={html} style={{ width:'100%', height:'60vh', border:'1px solid var(--border)', borderRadius:'var(--r-md)', background:'#fff' }}></iframe>
    </Modal>
  );
}

Object.assign(window, {
  contractDocHTML, contractDocTemplate, ContractDocModal,
  DEFAULT_CONTRACT_DOC_TITLE, DEFAULT_CONTRACT_DOC_INTRO, DEFAULT_CONTRACT_DOC_TERMS,
  DEFAULT_CONTRACT_DOC_SIGN_A, DEFAULT_CONTRACT_DOC_SIGN_B,
});
