// acceptance.jsx — Biên bản bàn giao & nghiệm thu (printable) từ 1 hợp đồng, theo mẫu sửa được ở Cài đặt HĐ.
// Tái dùng helper chứng từ: docCompany / docFontStack / printDocument (payment-request.jsx).

const DEFAULT_ACCEPT_TITLE = 'BIÊN BẢN NGHIỆM THU & BÀN GIAO';
const DEFAULT_ACCEPT_SUBTITLE = 'ACCEPTANCE & HANDOVER MINUTES';
const DEFAULT_ACCEPT_BODY =
  'Căn cứ hợp đồng đã ký giữa hai Bên, hôm nay hai Bên cùng tiến hành nghiệm thu và bàn giao các hạng mục nêu trên.\n' +
  'Sau khi kiểm tra thực tế, hai Bên thống nhất: các hạng mục đã được bàn giao đầy đủ, đúng yêu cầu kỹ thuật và đạt chất lượng nghiệm thu.\n' +
  'Bên nhận đồng ý nghiệm thu và đưa vào sử dụng. Biên bản được lập thành 02 bản, mỗi Bên giữ 01 bản có giá trị pháp lý như nhau.';

// Lấy mẫu từ app_settings (đã lưu) + fallback mặc định.
function acceptanceTemplate(S){
  S = S || {};
  return {
    title: (S.acceptTitle || '').trim() || DEFAULT_ACCEPT_TITLE,
    subtitle: (S.acceptSubtitle != null ? S.acceptSubtitle : DEFAULT_ACCEPT_SUBTITLE),
    body: (S.acceptBody != null ? S.acceptBody : DEFAULT_ACCEPT_BODY),
    // Header / footer (sửa được + biến) — dùng helper chung ở payment-request.jsx
    showMotto:  docFlag(S.acceptShowMotto, true),
    mottoTitle: (S.acceptMottoTitle || '').trim() || DEFAULT_DOC_MOTTO_TITLE,
    mottoSub:   (S.acceptMottoSub != null ? S.acceptMottoSub : DEFAULT_DOC_MOTTO_SUB),
    headerNote: (S.acceptHeaderNote != null ? S.acceptHeaderNote : ''),
    footer:     (S.acceptFooter != null ? S.acceptFooter : DEFAULT_DOC_FOOTER),
  };
}

/* Build printable HTML — c: hợp đồng, party: bên đối tác (KH/NCC), rep: người đại diện, branding, S: app_settings */
function acceptanceHTML(c, party, rep, branding, S){
  const co = docCompany(branding);
  const tpl = acceptanceTemplate(S);
  const buy = (window.contractDir && contractDir(c) === 'buy');
  // Bên giao / Bên nhận theo chiều HĐ: bán → công ty giao cho KH; mua → NCC giao cho công ty.
  const giao = buy ? { name:party.name, mst:party.mst, addr:party.address, rep:(rep.name || ''), title:(rep.title || '') }
                   : { name:co.name, mst:co.mst, addr:co.addr, rep:'', title:'' };
  const nhan = buy ? { name:co.name, mst:co.mst, addr:co.addr, rep:'', title:'' }
                   : { name:party.name, mst:party.mst, addr:party.address, rep:(rep.name || ''), title:(rep.title || '') };
  const docNo = 'BBNT-' + c.code;
  const today = new Date(TODAY);
  const dateLine = 'ngày ' + String(today.getDate()).padStart(2, '0') + ' tháng ' + String(today.getMonth() + 1).padStart(2, '0') + ' năm ' + today.getFullYear();
  const esc = (s) => String(s == null ? '' : s).replace(/[&<>]/g, m => ({ '&':'&amp;', '<':'&lt;', '>':'&gt;' }[m]));
  const tot = contractTotals(c);
  const bodyIsHtml = /<[a-z][\s\S]*>/i.test(tpl.body || '');
  // acceptDetail: thông tin chi tiết phần cứng (Part number · Serial · cấu hình…) nhập ở AcceptanceModal — hiện dưới tên hàng.
  const items = (c.items || []).map((it, i) =>
    `<tr><td style="text-align:center">${i + 1}</td><td>${esc(it.name)}${(it.acceptDetail || '').trim() ? `<div style="font-size:.85em;color:#54657F;white-space:pre-line;margin-top:3px">${esc(it.acceptDetail)}</div>` : ''}</td><td style="text-align:center">${esc(it.unit)}</td><td class="num">${it.qty}</td></tr>`).join('');
  const partyBlock = (lbl, d) =>
    `<div class="pb"><div class="pl">${lbl}</div>
      <div class="pr"><b>${esc(d.name) || '—'}</b></div>
      ${d.mst ? `<div class="pr">MST: ${esc(d.mst)}</div>` : ''}
      ${d.addr ? `<div class="pr">Địa chỉ: ${esc(d.addr)}</div>` : ''}
      ${d.rep ? `<div class="pr">Đại diện: ${esc(d.rep)}${d.title ? ' — ' + esc(d.title) : ''}</div>` : ''}</div>`;
  const vars = docVars({ co, party, docNo, date:docDateVN(), contract:c });
  // Khung mẫu v2 (header 2 vùng · config · title · footer); THÂN biên bản giữ riêng (căn cứ · bảng nghiệm thu · nội dung · kết luận).
  const V = docTpl(S, 'accept', { title:tpl.title, subtitle:tpl.subtitle, body:tpl.body, footer:(S.acceptFooter != null ? S.acceptFooter : DEFAULT_DOC_FOOTER) });
  const logoSz = (V.header || {}).logoSize;
  const renderRP = (src) => /<[a-z][\s\S]*>/i.test(src || '') ? renderRichVars(src, vars, co, logoSz) : docTextToHtml(src, vars);
  return `<!DOCTYPE html><html lang="vi"><head><meta charset="utf-8"><title>${docNo}</title>
<style>
@page{size:A4;margin:16mm}
${DOC_PAGENUM_CSS}
${DOC_HEAD2_CSS}
*{box-sizing:border-box}
body{font-family:${docFontStack(co)};color:#0A1730;font-size:13px;line-height:1.55;margin:0}
.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}
h1{text-align:center;font-size:1.5em;letter-spacing:.5px;margin:18px 0 2px;color:#0A1730}
.sub{text-align:center;font-size:.85em;color:#54657F;margin-bottom:6px}
.docno{text-align:center;font-size:.85em;color:#54657F;margin-bottom:16px}
.parties{display:flex;gap:14px;margin:10px 0}
.parties.stacked{flex-direction:column;gap:10px}
.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}
.based{margin:10px 0}
table{width:100%;border-collapse:collapse;margin:10px 0}
th,td{border:1px solid #D0D5DD;padding:7px 9px;text-align:left}
th{background:#EAF1FE;font-weight:700}
td.num,th.num{text-align:right;font-variant-numeric:tabular-nums}
.body{margin:12px 0;white-space:normal}
.concl{border-left:3px solid #12C5C0;background:#F6F9FD;padding:10px 12px;margin:12px 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:70px}
.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="sub">${esc(V.subtitle)}</div>` : ''}
  <div class="docno">Số: ${docNo} &nbsp;·&nbsp; ${dateLine}</div>

  <div class="based">Căn cứ Hợp đồng số <b>${esc(c.contractNo || c.code)}</b> ký ngày ${fmtDate(c.signDate)}; tổng giá trị: <b>${vnd(tot.total)}</b>.</div>

  <div class="parties${V.partiesStacked ? ' stacked' : ''}">
    ${partyBlock('BÊN GIAO (Bên A)', giao)}
    ${partyBlock('BÊN NHẬN (Bên B)', nhan)}
  </div>

  <p style="margin:12px 0 4px"><b>Nội dung bàn giao & nghiệm thu:</b></p>
  <table>
    <thead><tr><th style="width:44px">STT</th><th>Hạng mục</th><th style="width:90px">ĐVT</th><th class="num" style="width:90px">Số lượng</th></tr></thead>
    <tbody>${items || '<tr><td colspan="4" style="text-align:center;color:#98A2B3">—</td></tr>'}</tbody>
  </table>

  <div class="body">${renderRP(V.body || tpl.body)}</div>

  <div class="concl"><b>Kết luận:</b> Hai Bên đồng ý NGHIỆM THU và BÀN GIAO các hạng mục nêu trên. Bên nhận tiếp nhận và đưa vào sử dụng.</div>

  <div class="sign accept-sign">
    <div><div class="role">ĐẠI DIỆN BÊN GIAO</div><div class="note">(Ký, ghi rõ họ tên${giao.rep ? '' : ', đóng dấu'})</div><div class="space"></div><div>${esc(giao.rep || '')}</div></div>
    <div><div class="role">ĐẠI DIỆN BÊN NHẬN</div><div class="note">(Ký, ghi rõ họ tên${nhan.rep ? '' : ', đóng dấu'})</div><div class="space"></div><div>${esc(nhan.rep || '')}</div></div>
  </div>

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

function AcceptanceModal({ contract, 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) || {}) : {};
  // Chi tiết phần cứng theo hạng mục (Part number · Serial…) — sửa tại chỗ, preview cập nhật ngay.
  const [details, setDetails] = React.useState((contract.items || []).map(it => it.acceptDetail || ''));
  const [showDetails, setShowDetails] = React.useState((contract.items || []).some(it => (it.acceptDetail || '').trim()));
  const liveItems = (contract.items || []).map((it, i) => ({ ...it, acceptDetail:(details[i] || '').trim() }));
  const html = acceptanceHTML({ ...contract, items:liveItems }, party, rep, p.branding, p.appSettings);
  const docNo = 'BBNT-' + contract.code;
  const dirty = (contract.items || []).some((it, i) => (it.acceptDetail || '') !== (details[i] || '').trim());
  // Lưu bền vào hạng mục của HĐ — hoặc của BÁO GIÁ (biên bản từ "Chốt không HĐ" dùng adapter dạng HĐ).
  const save = (silent) => {
    if (!dirty) return;
    if (p.contracts.some(c => c.code === contract.code)) {
      p.patchContract(contract.code, { ...contract, items:liveItems });
    } else {
      const q = (p.quotes || []).find(x => x.code === contract.code);
      if (q) p.patchQuote(q.code, { ...q, items:(q.items || []).map((it, i) => ({ ...it, acceptDetail:(details[i] || '').trim() })) });
    }
    if (!silent) toast(lang === 'vi' ? 'Đã lưu chi tiết hạng mục' : 'Item details saved', 'success');
  };
  const doPrint = () => { save(true); 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' ? 'Biên bản nghiệm thu · ' : 'Acceptance · ') + docNo} width={860} onClose={onClose}
      footer={<><div className="grow"></div>
        <button className="btn" onClick={onClose}>{t('c.close')}</button>
        {dirty && <button className="btn" onClick={() => save(false)}><i className="bi bi-save"></i>{lang === 'vi' ? 'Lưu chi tiết' : 'Save details'}</button>}
        <button className="btn btn-primary" onClick={doPrint}><i className="bi bi-filetype-pdf"></i>{lang === 'vi' ? 'In / Lưu PDF' : 'Print / PDF'}</button></>}>
      <div style={{ marginBottom:8 }} className="flex g8 items-center subtle">
        <i className="bi bi-eye"></i>{lang === 'vi' ? 'Xem trước (mẫu sửa ở Cài đặt hợp đồng)' : 'Preview (edit template in Contract Settings)'}
        <button className="btn btn-sm btn-subtle" style={{ marginLeft:'auto' }} onClick={() => setShowDetails(s => !s)}>
          <i className={'bi ' + (showDetails ? 'bi-chevron-up' : 'bi-upc-scan')}></i>{lang === 'vi' ? 'Chi tiết hạng mục (Part / Serial…)' : 'Item details (Part / Serial…)'}
        </button>
      </div>
      {showDetails && (contract.items || []).length > 0 && (
        <div className="card" style={{ marginBottom:10 }}>
          <div className="card-body col g8">
            <div className="subtle" style={{ fontSize:'var(--fs-sm)' }}><i className="bi bi-info-circle" style={{ marginRight:4 }}></i>{lang === 'vi' ? 'Nhập Part number · Serial · cấu hình… cho từng hạng mục — hiện thành dòng nhỏ dưới tên hàng trong biên bản; bấm In sẽ tự lưu.' : 'Enter part numbers, serials, specs per item — shown under the item name; printing auto-saves.'}</div>
            {(contract.items || []).map((it, i) => (
              <div key={i} className="flex g8 items-start">
                <div className="truncate" style={{ flex:'0 0 230px', fontWeight:500, paddingTop:5, fontSize:'var(--fs-md)' }} title={it.name}>{i + 1}. {it.name}</div>
                <textarea className="textarea" rows={2} style={{ flex:1, fontSize:'var(--fs-base)' }}
                  placeholder={lang === 'vi' ? 'VD: P/N: ZB-2200-EU · S/N: SN0123, SN0124…' : 'e.g. P/N: ZB-2200-EU · S/N: SN0123, SN0124…'}
                  value={details[i] || ''} onChange={e => setDetails(s => s.map((v, j) => j === i ? e.target.value : v))} />
              </div>
            ))}
          </div>
        </div>
      )}
      <iframe title="preview" srcDoc={html} style={{ width:'100%', height:showDetails ? '44vh' : '58vh', border:'1px solid var(--border)', borderRadius:'var(--r-md)', background:'#fff' }}></iframe>
    </Modal>
  );
}

Object.assign(window, { acceptanceHTML, acceptanceTemplate, AcceptanceModal, DEFAULT_ACCEPT_TITLE, DEFAULT_ACCEPT_SUBTITLE, DEFAULT_ACCEPT_BODY });
