/* global React, I, UI, SSSData */
const { useState: useStateU, useMemo: useMemoU } = React;
const uiU = window.UI;

// Map doc type → list key on SSSData and id field
const TYPE_TO_LIST = {
  invoice: { list: "Invoices", id: "no", party: "customer" },
  "tax-invoice": { list: "TaxInvoices", id: "no", party: "customer" },
  "billing-note": { list: "BillingNotes", id: "no", party: "customer" },
  "purchase-order": { list: "PurchaseOrders", id: "no", party: "vendor" },
  "payment-voucher": { list: "PaymentVouchers", id: "no", party: "vendor" },
  quotation: { list: "Quotations", id: "no", party: "customer" }
};

// =============== เปลี่ยนสถานะเอกสาร (บันทึกถาวร) ===============
const DOC_STATUS_CHOICES = {
  invoice: ["ค้างชำระ", "ชำระบางส่วน", "ชำระแล้ว", "เกินกำหนด"],
  "tax-invoice": ["เต็มรูป", "อย่างย่อ"],
  quotation: ["ร่าง", "ส่งแล้ว", "รออนุมัติ", "อนุมัติแล้ว", "แปลงเป็นใบสั่ง", "ปฏิเสธ"],
  "billing-note": ["ส่งแล้ว", "ลูกค้านัดรับ", "เก็บเงินแล้ว"],
  "purchase-order": ["รออนุมัติ", "อนุมัติแล้ว", "รับสินค้าแล้ว"],
  "payment-voucher": ["รอจ่าย", "รออนุมัติจ่าย", "อนุมัติแล้ว", "ออกเช็คแล้ว", "จ่ายแล้ว"]
};
const DS_KEY = "sss-doc-status";
function dsLoad() { try { return JSON.parse(localStorage.getItem(DS_KEY) || "{}"); } catch { return {}; } }
window.DocStatusStore = {
  set(docType, no, status) {
    const m = dsLoad();
    m[docType] = m[docType] || {};
    m[docType][no] = status;
    try { localStorage.setItem(DS_KEY, JSON.stringify(m)); } catch {}
    const info = TYPE_TO_LIST[docType];
    if (info) {
      const row = (window.SSSData[info.list] || []).find(r => r[info.id] === no);
      if (row) { row.status = status; if (docType === "tax-invoice") row.type = status; }
    }
    window.dispatchEvent(new Event("sss-doc-status-changed"));
  },
  apply() {
    const m = dsLoad();
    Object.entries(m).forEach(([dt, map]) => {
      const info = TYPE_TO_LIST[dt];
      if (!info) return;
      (window.SSSData[info.list] || []).forEach(r => { if (map[r[info.id]]) r.status = map[r[info.id]]; });
    });
  }
};
window.DocStatusStore.apply();

// =============== สถานะที่ 2 (ขั้นถัดไป) — เช่น แปลงเป็นใบส่งสินค้าแล้ว / ออกใบกำกับภาษีแล้ว ===============
const DS2_KEY = "sss-doc-status2";
function ds2Load() { try { return JSON.parse(localStorage.getItem(DS2_KEY) || "{}"); } catch { return {}; } }
window.DocStatus2Store = {
  get(docType, no) { const m = ds2Load(); return (m[docType] || {})[no] || null; },
  set(docType, no, status2) {
    const m = ds2Load();
    m[docType] = m[docType] || {};
    if (status2) m[docType][no] = status2; else delete m[docType][no];
    try { localStorage.setItem(DS2_KEY, JSON.stringify(m)); } catch {}
    window.dispatchEvent(new Event("sss-doc-status-changed"));
  }
};

// แปลงเลขเอกสารในข้อความ (DN/INV/TX/RC/PV/PO/QO/BN) ให้กดเปิดเอกสารต้นทางได้
const DOC_LINK_ROUTE = { DN: "delivery-notes", INV: "invoices", TX: "tax-invoices", RC: "receipts", PV: "payment-vouchers", PO: "purchase-orders", QO: "quotations", BN: "billing-notes" };
window.docLinkify = function (text, navigate) {
  if (!text) return text;
  const parts = String(text).split(/((?:DN|INV|TX|RC|PV|PO|QO|BN)-[0-9]{4}-[0-9]+)/g);
  return parts.map((p, i) => {
    const m = /^((?:DN|INV|TX|RC|PV|PO|QO|BN))-[0-9]{4}-[0-9]+$/.exec(p);
    if (m && DOC_LINK_ROUTE[m[1]]) return React.createElement("button", { key: i, className: "mono", style: { border: 0, background: "transparent", color: "var(--info)", cursor: "pointer", fontWeight: 700, padding: 0, fontSize: "inherit" }, title: "เปิดเอกสาร " + p, onClick: () => navigate && navigate(DOC_LINK_ROUTE[m[1]] + "/" + p) }, p + " ↗");
    return React.createElement(React.Fragment, { key: i }, p);
  });
};

// Generate plausible line items from a row's total amount
function fakeLinesFor(docType, row) {
  const D = window.SSSData;
  // Try to find matching customer/vendor
  const cfg = window.DOC_TYPES[docType];
  const partyList = cfg.party === "customer" ? D.Customers : D.Vendors;
  const partyName = row.customer || row.vendor || row.payee;
  const party = partyList.find(p => p.name === partyName) || partyList[0];

  const totalIncVat = row.amount;
  const total = cfg.showVAT ? totalIncVat / 1.07 : totalIncVat;

  // Lines depending on doc type and party
  let lines = [];
  if (docType === "purchase-order") {
    // Raw materials based on vendor category
    if (party.category && party.category.includes("สแตนเลส")) {
      lines = [
        { id: 1, sku: "SS304-SH-1.0", name: "แผ่นสแตนเลส 304 หนา 1.0 มม. 4x8 ฟุต", qty: Math.floor(total / 2850 * 0.6), unit: "แผ่น", price: 2850 },
        { id: 2, sku: "SS304-SH-1.5", name: "แผ่นสแตนเลส 304 หนา 1.5 มม. 4x8 ฟุต", qty: Math.floor(total / 4180 * 0.4), unit: "แผ่น", price: 4180 }
      ];
    } else if (party.category && party.category.includes("เหล็ก")) {
      lines = [
        { id: 1, sku: "STL-PL-3", name: "แผ่นเหล็กดำ หนา 3 มม. 4x8 ฟุต", qty: Math.floor(total / 1240 * 0.7), unit: "แผ่น", price: 1240 },
        { id: 2, sku: "STL-HB-50", name: "เหล็กกล่อง 50x50 หนา 2.3 มม. ยาว 6 ม.", qty: Math.floor(total / 540 * 0.3), unit: "เส้น", price: 540 }
      ];
    } else {
      lines = [{ id: 1, sku: "", name: party.category || "วัตถุดิบ/อุปกรณ์", qty: 1, unit: "lot", price: total }];
    }
  } else if (docType === "payment-voucher") {
    lines = [{ id: 1, sku: "", name: `จ่ายตามอ้างอิง: ${row.ref || "—"}`, qty: 1, unit: "ครั้ง", price: totalIncVat }];
  } else if (docType === "tax-invoice") {
    lines = [
      { id: 1, sku: "SS316-SH-2.0", name: "แผ่นสแตนเลส 316L หนา 2.0 มม. 4x8 ฟุต", qty: Math.floor(total / 11200 * 0.6), unit: "แผ่น", price: 11200 },
      { id: 2, sku: "SVC-CNC-LASER", name: "ค่าบริการตัด CNC Fiber Laser", qty: Math.floor(total * 0.2 / 850), unit: "ชม.", price: 850 },
      { id: 3, sku: "SVC-WELD-TIG", name: "ค่าบริการเชื่อม TIG", qty: Math.floor(total * 0.2 / 650), unit: "ชม.", price: 650 }
    ];
  } else if (docType === "invoice") {
    lines = [
      { id: 1, sku: "—", name: `งานตามใบเสนอราคา ${(row.no || "").replace("INV", "QO")}`, qty: 1, unit: "งาน", price: total }
    ];
  } else if (docType === "billing-note") {
    // List the underlying invoices
    lines = (row.invoices || []).map((inv, i) => ({
      id: i + 1, sku: "", name: `ใบแจ้งหนี้ ${inv}`, qty: 1, unit: "ใบ", price: row.amount / (row.invoices?.length || 1)
    }));
    if (lines.length === 0) lines = [{ id: 1, sku: "", name: "ค่าสินค้าและบริการ", qty: 1, unit: "lot", price: total }];
  } else {
    lines = [{ id: 1, sku: "", name: "ค่าสินค้าและบริการ", qty: 1, unit: "lot", price: total }];
  }

  return { lines: lines.filter(l => l.qty > 0), party };
}

// ============ Universal doc detail view ============
function UniversalDocDetail({ docType, docId, navigate }) {
  const D = window.SSSData;
  const info = TYPE_TO_LIST[docType];
  const list = D[info.list] || [];
  const row = list.find(r => r[info.id] === docId) || list[0];
  const cfg = window.DOC_TYPES[docType];
  const { lines, party } = useMemoU(() => fakeLinesFor(docType, row), [docType, row]);
  const [, forceU] = useStateU(0);
  const [payModal, setPayModal] = useStateU(false);

  const subtotal = lines.reduce((s, l) => s + l.qty * l.price, 0);
  const discount = 0;
  const afterDisc = subtotal - discount;
  const vatPct = cfg.showVAT ? 7 : 0;
  const vat = cfg.showVAT ? afterDisc * 0.07 : 0;
  const grand = afterDisc + vat;

  const { Btn, Badge, Card, PageHead, Workflow, fmt0, fmtM } = uiU;

  // Workflow steps per doc type
  const workflows = {
    invoice: ["สร้าง", "ส่งให้ลูกค้า", "รอชำระ", "ชำระแล้ว"],
    "tax-invoice": ["สร้าง", "ออกเอกสาร", "ส่งให้ลูกค้า", "นำส่งใน ภ.พ.30"],
    "billing-note": ["สร้าง", "นัดวันเก็บ", "ลูกค้าเซ็นรับ", "เก็บเงินแล้ว"],
    "purchase-order": ["ร่าง", "รออนุมัติ", "ส่งให้ vendor", "รับสินค้าแล้ว"],
    "payment-voucher": ["บันทึก", "อนุมัติ", "ออกเช็ค/โอน", "จ่ายแล้ว"]
  };
  const currentStep = {
    invoice: row.status === "ชำระแล้ว" ? 3 : row.status === "ชำระบางส่วน" ? 2 : row.status === "เกินกำหนด" ? 2 : 2,
    "tax-invoice": 2,
    "billing-note": row.status === "เก็บเงินแล้ว" ? 3 : row.status === "ลูกค้านัดรับ" ? 1 : 2,
    "purchase-order": row.status === "รับสินค้าแล้ว" ? 3 : row.status === "อนุมัติแล้ว" ? 2 : 1,
    "payment-voucher": row.status === "จ่ายแล้ว" ? 3 : 2
  }[docType] || 1;

  // แปลงใบส่งสินค้า/ใบแจ้งหนี้ → ใบเสร็จรับเงิน (+ ใบกำกับภาษี)
  const convertInvoice = async (withTax) => {
    const rcNo = "RC-2569-0157", txNo = "TX-2569-0205";
    const ok = await window.confirmDialog({
      title: withTax ? "แปลงเป็นใบเสร็จรับเงิน + ใบกำกับภาษี" : "แปลงเป็นใบเสร็จรับเงินอย่างเดียว",
      message: `บันทึกรับชำระเงินจาก <b>${row.customer}</b> ตาม <b class="mono">${row[info.id]}</b> ยอด <b>฿${fmt0(row.amount)}</b>`,
      bullets: withTax ? [
        `ออกใบเสร็จรับเงินเลข ${rcNo}`,
        `ออกใบกำกับภาษีเต็มรูปเลข ${txNo} (VAT 7%)`,
        "เปลี่ยนสถานะใบแจ้งหนี้เป็น 'ชำระแล้ว'",
        "บันทึกเข้าสมุดรายวันรับเงิน (CR) อัตโนมัติ"
      ] : [
        `ออกใบเสร็จรับเงินเลข ${rcNo} — ไม่ออกใบกำกับภาษี`,
        "เปลี่ยนสถานะใบแจ้งหนี้เป็น 'ชำระแล้ว'",
        "บันทึกเข้าสมุดรายวันรับเงิน (CR) อัตโนมัติ"
      ],
      confirmText: withTax ? "ออกใบเสร็จ + ใบกำกับภาษี" : "ออกใบเสร็จอย่างเดียว"
    });
    if (!ok) return;
    window.logActivity && window.logActivity("แปลงเอกสาร", `${row[info.id]} → ${rcNo}${withTax ? " + " + txNo : ""}`, "create");
    window.DocStatusStore.set("invoice", row[info.id], "ชำระแล้ว");
    window.DocStatus2Store.set("invoice", row[info.id], withTax ? `ออกใบเสร็จ + ใบกำกับภาษีแล้ว (${txNo})` : "ออกใบเสร็จแล้ว (ไม่ออกใบกำกับภาษี)");
    forceU(n => n + 1);
    window.toast && window.toast(withTax ? `ออกใบเสร็จ ${rcNo} และใบกำกับภาษี ${txNo} จาก ${row[info.id]} แล้ว` : `ออกใบเสร็จ ${rcNo} จาก ${row[info.id]} แล้ว`);
    setTimeout(() => navigate("receipts/RC-2569-0156"), 600);
  };

  return (
    <>
      <PageHead
        title={<span style={{display: "flex", alignItems: "center", gap: 12}}>
          <Btn kind="ghost" size="sm" onClick={() => navigate(docType === "invoice" ? "invoices" : docType === "tax-invoice" ? "tax-invoices" : docType === "billing-note" ? "billing-notes" : docType === "purchase-order" ? "purchase-orders" : "payment-vouchers")}>
            <I.chevronLeft size={14} className="icon"/>กลับ
          </Btn>
          {cfg.title} <span className="mono" style={{fontSize: 16, color: "var(--ink-3)", fontWeight: 500}}>{row[info.id]}</span>
        </span>}
        sub={`${cfg.partyLabel}: ${row.customer || row.vendor || row.payee} · ${row.date}`}
        right={<>
          <Btn icon={I.edit} kind="ghost" onClick={() => window.openNewDoc && window.openNewDoc(docType, { editing: true, docNo: row[info.id], partyName: row.customer || row.vendor || row.payee, lines: lines.map(l => ({ sku: l.sku, name: l.name, qty: l.qty, unit: l.unit, price: l.price })) })}>แก้ไขเอกสาร</Btn>
          <Btn icon={I.msg} kind="ghost" onClick={() => window.toast && window.toast(`ส่ง ${cfg.title} ${row[info.id]} ทางอีเมลให้ ${row.customer || row.vendor || row.payee} แล้ว`)}>ส่งทางอีเมล</Btn>
          <Btn icon={I.print} kind="ghost" onClick={() => window.printDocPaperWithOptions()}>พิมพ์</Btn>
          <Btn icon={I.download} kind={(docType === "invoice" || docType === "payment-voucher") ? "ghost" : "primary"} onClick={() => window.printDocPaperWithOptions()}>ดาวน์โหลด PDF</Btn>
          {docType === "payment-voucher" && row.status !== "จ่ายแล้ว" && (
            <Btn icon={I.money} kind="primary" onClick={() => setPayModal(true)}>กดจ่าย → เลือกบัญชีบริษัท</Btn>
          )}
          {docType === "invoice" && <>
            <Btn icon={I.receipt} kind="ghost" onClick={() => convertInvoice(false)}>ใบเสร็จอย่างเดียว</Btn>
            <Btn icon={I.arrowRight} kind="primary" onClick={() => convertInvoice(true)}>แปลงเป็นใบเสร็จ + ใบกำกับภาษี</Btn>
          </>}
        </>}
      />

      <div className="grid" style={{gridTemplateColumns: "1fr 320px", gap: 14, alignItems: "flex-start"}}>
        <div>
          {/* Workflow */}
          <Card padded={false} className="mb-lg" flush>
            <div style={{padding: "14px 16px"}}>
              <Workflow steps={workflows[docType] || ["สร้าง", "ออก", "ส่ง", "ปิดงาน"]} current={currentStep}/>
            </div>
          </Card>

          {/* Doc paper */}
          <window.NewDocPrintablePaper
            cfg={cfg}
            docType={docType}
            docNo={row[info.id]}
            date={row.date}
            dueDate={row.due || row.dueDate || row.expected || "—"}
            validity={row.validity || "—"}
            expected={row.expected || "—"}
            method={row.method || "โอน · KBank"}
            party={party}
            lines={lines}
            subtotal={subtotal}
            discount={discount}
            vat={vat}
            vatPct={vatPct}
            grand={grand}
            notes={cfg.note}
          />
        </div>

        {/* Side panel */}
        <div style={{display: "flex", flexDirection: "column", gap: 14}}>
          <Card title="สถานะ" right={<Badge>{row.status || "ออกแล้ว"}</Badge>}>
            {(() => { const s2 = window.DocStatus2Store && window.DocStatus2Store.get(docType, row[info.id]); return s2 ? (
              <div style={{display: "flex", alignItems: "center", gap: 8, padding: "7px 10px", marginBottom: 10, background: "var(--success-bg, var(--surface-2))", border: "1px solid var(--success)", borderRadius: 8, fontSize: 12.5}}>
                <I.check size={14} stroke="var(--success)"/>
                <span style={{flex: 1}}><b style={{color: "var(--success)"}}>สถานะที่ 2:</b> {window.docLinkify ? window.docLinkify(s2, navigate) : s2}</span>
                <button className="icon-btn" title="ลบสถานะที่ 2" onClick={() => { window.DocStatus2Store.set(docType, row[info.id], null); forceU(n => n + 1); }}><I.close size={11}/></button>
              </div>
            ) : null; })()}
            <div style={{display: "flex", flexDirection: "column", gap: 8, fontSize: 13}}>
              {DOC_STATUS_CHOICES[docType] && (
                <div className="field" style={{marginBottom: 2}}>
                  <label style={{fontSize: 11, color: "var(--ink-3)", display: "block", marginBottom: 4}}>เปลี่ยนสถานะ</label>
                  <select className="input" style={{height: 32}} value={row.status || ""}
                    onChange={e => {
                      const s = e.target.value;
                      window.DocStatusStore.set(docType, row[info.id], s);
                      forceU(n => n + 1);
                      window.logActivity && window.logActivity("เปลี่ยนสถานะ", `${row[info.id]} → ${s}`, "update");
                      window.toast && window.toast(`เปลี่ยนสถานะ ${row[info.id]} เป็น "${s}" แล้ว — บันทึกถาวร`);
                    }}>
                    {!DOC_STATUS_CHOICES[docType].includes(row.status) && row.status && <option value={row.status}>{row.status}</option>}
                    {DOC_STATUS_CHOICES[docType].map(s => <option key={s} value={s}>{s}</option>)}
                  </select>
                </div>
              )}
              <div style={{display: "flex", justifyContent: "space-between"}}><span className="muted">เลขที่</span><span className="mono">{row[info.id]}</span></div>
              <div style={{display: "flex", justifyContent: "space-between"}}><span className="muted">วันที่</span><span>{row.date}</span></div>
              {row.due && <div style={{display: "flex", justifyContent: "space-between"}}><span className="muted">ครบกำหนด</span><span>{row.due}</span></div>}
              {row.dueDate && <div style={{display: "flex", justifyContent: "space-between"}}><span className="muted">ครบกำหนด</span><span>{row.dueDate}</span></div>}
              {row.expected && <div style={{display: "flex", justifyContent: "space-between"}}><span className="muted">นัดรับ</span><span>{row.expected}</span></div>}
              {row.paid !== undefined && <div style={{display: "flex", justifyContent: "space-between"}}><span className="muted">ชำระแล้ว</span><span className="amount">฿{fmt0(row.paid)}</span></div>}
              {row.method && <div style={{display: "flex", justifyContent: "space-between"}}><span className="muted">วิธีจ่าย</span><span>{row.method}</span></div>}
            </div>
          </Card>

          <Card title={cfg.partyLabel} right={<Btn size="sm" kind="ghost" onClick={() => navigate(cfg.party === "customer" ? "customers" : "vendors")}>เปิดโปรไฟล์</Btn>}>
            <div style={{fontSize: 13, lineHeight: 1.6}}>
              <div style={{fontWeight: 500, marginBottom: 4}}>{party.name}</div>
              <div className="muted">เลขผู้เสียภาษี <span className="mono">{party.taxId}</span></div>
              <div className="muted">{party.contact}</div>
              <div className="mono muted">{party.phone}</div>
              {party.credit !== undefined && <div className="muted">เครดิต {party.credit} วัน</div>}
              {party.terms && <div className="muted">เงื่อนไข: {party.terms}</div>}
            </div>
          </Card>

          {(docType === "billing-note" && row.invoices) && (
            <Card title="ใบแจ้งหนี้ที่รวม">
              <div style={{display: "flex", flexDirection: "column", gap: 6}}>
                {row.invoices.map(inv => <Badge key={inv}>{inv}</Badge>)}
              </div>
            </Card>
          )}

          {docType === "payment-voucher" && (
            <Card title="อ้างอิง">
              <div className="mono" style={{fontSize: 12, lineHeight: 1.6}}>{row.ref}</div>
            </Card>
          )}

          {docType === "payment-voucher" && <SlipUpload voucherNo={row.no}/>}

          <Card title="ประวัติ">
            <div style={{display: "flex", flexDirection: "column", gap: 8, fontSize: 12.5, color: "var(--ink-3)"}}>
              <div><b style={{color: "var(--ink-1)"}}>ปิยะ ศ.</b> สร้างเอกสาร · {row.date}</div>
              <div><b style={{color: "var(--ink-1)"}}>วันเพ็ญ ส.</b> ตรวจสอบ · {row.date}</div>
              {(row.status === "ชำระแล้ว" || row.status === "จ่ายแล้ว" || row.status === "เก็บเงินแล้ว") && (
                <div><b style={{color: "var(--ink-1)"}}>ระบบ</b> ปิดบัญชี · auto</div>
              )}
            </div>
          </Card>

          <Card title="ไฟล์แนบ" right={<Btn size="sm" kind="ghost" icon={I.plus} onClick={() => window.toast && window.toast("ลากไฟล์มาวางเพื่อแนบกับเอกสาร")}>เพิ่ม</Btn>}>
            <div style={{display: "flex", flexDirection: "column", gap: 6, fontSize: 12, color: "var(--ink-3)"}}>
              <div style={{display: "flex", alignItems: "center", gap: 6}}><I.paperclip size={12}/> {row[info.id]}.pdf</div>
              {docType === "payment-voucher" && <div style={{display: "flex", alignItems: "center", gap: 6}}><I.paperclip size={12}/> bank-slip.jpg</div>}
            </div>
          </Card>
        </div>
      </div>

      {payModal && <PayFromCompanyModal row={row} onClose={() => setPayModal(false)} navigate={navigate}/>}
    </>
  );
}

// =============== กดจ่ายใบสำคัญจ่าย → เลือกบัญชีบริษัท ===============
function PayFromCompanyModal({ row, onClose, navigate }) {
  const { Btn, fmt0 } = window.UI;
  const [accountId, setAccountId] = useStateU("SCB");
  const balances = window.CompanyCashStore ? window.CompanyCashStore.balances() : [];
  const confirmPay = () => {
    if (!window.CompanyCashStore) { window.toast && window.toast("ระบบบัญชีบริษัทยังไม่พร้อม"); return; }
    const acc = balances.find(a => a.id === accountId);
    window.CompanyCashStore.addPayment({
      voucherNo: row.no, payee: row.payee,
      desc: `ตามใบสำคัญจ่าย ${row.no} · อ้างอิง ${row.ref || "—"}`,
      accountId, amount: row.amount
    });
    window.DocStatusStore && window.DocStatusStore.set("payment-voucher", row.no, "รออนุมัติจ่าย");
    window.logActivity && window.logActivity("กดจ่ายใบสำคัญจ่าย", `${row.no} → จ่ายผ่าน${acc ? acc.short : accountId}`, "expense");
    window.toast && window.toast(`สร้างรายการจ่าย ${row.no} ขึ้นที่บัญชี${acc ? acc.short : ""}แล้ว — ไปอนุมัติจ่าย + แนบสลิปต่อ`);
    onClose();
    setTimeout(() => navigate("company-cash"), 500);
  };
  return (
    <>
      <div className="scrim" style={{zIndex: 80}} onClick={onClose}></div>
      <div style={{position: "fixed", left: "50%", top: "50%", transform: "translate(-50%, -50%)", zIndex: 81, background: "var(--surface)", border: "1px solid var(--line)", borderRadius: 12, padding: 18, width: 480, maxWidth: "94vw", maxHeight: "92vh", overflowY: "auto", boxShadow: "var(--shadow-lg)"}}>
        <div style={{fontSize: 14.5, fontWeight: 700, marginBottom: 4}}>กดจ่าย — เลือกบัญชีที่จะจ่าย</div>
        <div style={{fontSize: 12.5, color: "var(--ink-3)", marginBottom: 12}}>{row.no} · {row.payee} · <b className="amount" style={{color: "var(--ink-1)"}}>฿{fmt0(row.amount)}</b></div>
        {window.CCAccountPicker
          ? <window.CCAccountPicker value={accountId} onChange={setAccountId} balances={balances}/>
          : <div className="muted" style={{fontSize: 12}}>ไม่พบข้อมูลบัญชี</div>}
        <div style={{marginTop: 10, padding: "8px 12px", background: "var(--surface-2)", borderRadius: 8, fontSize: 11.5, color: "var(--ink-3)", lineHeight: 1.7}}>
          รายการจะขึ้นที่บัญชีที่เลือก สถานะ "รออนุมัติจ่าย" — จากนั้นไปกด <b style={{color: "var(--ink-1)"}}>อนุมัติจ่าย + แนบสลิป/หลักฐาน</b> ระบบจึงจะบันทึกลงระบบบัญชี
        </div>
        <div style={{display: "flex", gap: 8, justifyContent: "flex-end", marginTop: 14}}>
          <Btn kind="ghost" onClick={onClose}>ยกเลิก</Btn>
          <Btn kind="primary" icon={I.check} onClick={confirmPay}>สร้างรายการจ่าย</Btn>
        </div>
      </div>
    </>
  );
}

window.UniversalDocDetail = UniversalDocDetail;

// =============== Bank slip uploader (for payment vouchers) ===============
function SlipUpload({ voucherNo }) {
  const { Btn, Card } = window.UI;
  const key = `sss-slip-${voucherNo}`;
  const [slips, setSlips] = useStateU(() => {
    try { return JSON.parse(localStorage.getItem(key) || "[]"); } catch { return []; }
  });
  const [preview, setPreview] = useStateU(null);

  const save = (list) => {
    setSlips(list);
    try { localStorage.setItem(key, JSON.stringify(list)); } catch {}
  };

  const onPick = (e) => {
    const files = [...e.target.files];
    Promise.all(files.map(f => new Promise(res => {
      const reader = new FileReader();
      reader.onload = () => res({
        name: f.name,
        url: reader.result,
        size: f.size,
        type: f.type,
        uploadedAt: new Date().toLocaleString("th-TH", { day: "2-digit", month: "short", year: "2-digit", hour: "2-digit", minute: "2-digit" })
      });
      reader.readAsDataURL(f);
    }))).then(loaded => {
      save([...slips, ...loaded]);
      window.toast && window.toast(`แนบสลิป ${loaded.length} ไฟล์`);
    });
    e.target.value = "";
  };

  const removeSlip = (i) => save(slips.filter((_, j) => j !== i));

  return (
    <>
      <Card title="สลิปการโอนเงิน" sub={`${slips.length} ไฟล์`} right={
        <label className="btn sm" style={{cursor: "pointer"}}>
          <I.upload className="icon" size={13}/>
          แนบสลิป
          <input type="file" accept="image/*,application/pdf" multiple style={{display: "none"}} onChange={onPick}/>
        </label>
      }>
        {slips.length === 0 ? (
          <label style={{cursor: "pointer", display: "block"}}>
            <input type="file" accept="image/*,application/pdf" multiple style={{display: "none"}} onChange={onPick}/>
            <div className="attach-dropzone">
              <I.upload size={20}/>
              <div style={{marginTop: 6, fontSize: 12}}>คลิกหรือลากไฟล์สลิปมาวาง</div>
              <div style={{fontSize: 11, marginTop: 2}}>JPG, PNG หรือ PDF</div>
            </div>
          </label>
        ) : (
          <div style={{display: "flex", flexDirection: "column", gap: 8}}>
            {slips.map((s, i) => {
              const isImg = s.type && s.type.startsWith("image/");
              return (
                <div key={i} style={{display: "flex", gap: 10, padding: 8, border: "1px solid var(--line)", borderRadius: 6, alignItems: "center"}}>
                  {isImg ? (
                    <img src={s.url} alt={s.name} onClick={() => setPreview(s)}
                      style={{width: 56, height: 56, objectFit: "cover", borderRadius: 4, cursor: "pointer", border: "1px solid var(--line)"}}/>
                  ) : (
                    <div style={{width: 56, height: 56, borderRadius: 4, background: "var(--surface-2)", border: "1px solid var(--line)", display: "grid", placeItems: "center", color: "var(--ink-3)", fontSize: 10, fontWeight: 600}}>PDF</div>
                  )}
                  <div style={{flex: 1, minWidth: 0}}>
                    <div style={{fontSize: 12.5, fontWeight: 500, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap"}}>{s.name}</div>
                    <div style={{fontSize: 10.5, color: "var(--ink-3)"}}>{(s.size/1024).toFixed(0)} KB · {s.uploadedAt}</div>
                  </div>
                  <div style={{display: "flex", gap: 4}}>
                    <button className="icon-btn" onClick={() => isImg ? setPreview(s) : window.open(s.url, "_blank")} title="ดู"><I.search size={12}/></button>
                    <button className="icon-btn" onClick={() => removeSlip(i)} title="ลบ"><I.trash size={12}/></button>
                  </div>
                </div>
              );
            })}
            <label style={{cursor: "pointer"}}>
              <input type="file" accept="image/*,application/pdf" multiple style={{display: "none"}} onChange={onPick}/>
              <div style={{padding: "8px 12px", border: "1.5px dashed var(--line-strong)", borderRadius: 6, textAlign: "center", color: "var(--ink-3)", fontSize: 12}}>+ เพิ่มสลิป</div>
            </label>
          </div>
        )}
      </Card>

      {preview && (
        <div className="scrim" style={{display: "flex", alignItems: "center", justifyContent: "center", padding: 24}} onClick={() => setPreview(null)}>
          <div style={{position: "relative", maxWidth: "90vw", maxHeight: "90vh"}}>
            <button className="icon-btn" onClick={() => setPreview(null)} style={{position: "absolute", top: -36, right: 0, background: "white"}}>
              <I.close size={14}/>
            </button>
            <img src={preview.url} alt={preview.name} style={{maxWidth: "90vw", maxHeight: "90vh", borderRadius: 6, boxShadow: "0 20px 60px rgba(0,0,0,0.4)"}}/>
            <div style={{position: "absolute", left: 0, bottom: -28, color: "white", fontSize: 12}}>{preview.name}</div>
          </div>
        </div>
      )}
    </>
  );
}

window.SlipUpload = SlipUpload;
