/* global React, Icon, fmt, fmtMoney, fmtCompact, fmtDate, Progress, StatusPill, useToast, Modal, DeleteConfirmModal, EditContractModal, EditHouseModal, NewContractModal, AddRangeModal, BulkTextModal, PaymentModal, HistoryModal, BulkPaymentModal, exportExcel */
const { useState, useMemo, useEffect } = React;

// =====================================================
// CONTRACTS
// =====================================================
function ContractsScreen({ data, projectId, setProjectId, onOpenHouses, onAddContract, onUpdateContract, onDeleteContract, onAddPayment }) {
  const [selectedId, setSelectedId] = useState(null);
  const [search, setSearch] = useState("");
  const [showNew, setShowNew] = useState(false);
  const [showBulk, setShowBulk] = useState(false);
  const toast = useToast();

  const project = data.projects.find((p) => p.id === projectId);
  const contracts = (data.contracts[projectId] || []).filter((c) =>
    !search || (c.contract_number + c.description).toLowerCase().includes(search.toLowerCase())
  );
  const selected = contracts.find((c) => c.id === selectedId);

  useEffect(() => { setSelectedId(null); }, [projectId]);

  return (
    <div className="page">
      <div className="page-head">
        <div>
          <h1 className="page-title">สัญญา</h1>
          <p className="page-sub">เลือกโครงการเพื่อดูสัญญาภายใน — แต่ละสัญญาประกอบด้วยบ้านหลายหลัง</p>
        </div>
        <div className="page-actions">
          <button className="btn" onClick={() => setShowBulk(true)}><Icon name="layers" size={13} /> เบิกจ่ายกลุ่ม</button>
          <button className="btn primary" disabled={!projectId} onClick={() => setShowNew(true)}><Icon name="plus" size={13} /> เพิ่มสัญญา</button>
        </div>
      </div>

      <div className="card" style={{ marginBottom: 14 }}>
        <div className="card-body" style={{ display: "flex", alignItems: "center", gap: 14 }}>
          <div className="field" style={{ flex: 1, maxWidth: 480 }}>
            <label>โครงการ</label>
            <select className="select" value={projectId || ""} onChange={(e) => setProjectId(e.target.value || null)}>
              <option value="">— เลือกโครงการ —</option>
              {data.projects.map((p) => <option key={p.id} value={p.id}>{p.name} · {p.client}</option>)}
            </select>
          </div>
          {project && (
            <>
              <div className="divider" style={{ width: 1, height: 50, background: "var(--border)", margin: 0 }}></div>
              <div className="hstack" style={{ gap: 24 }}>
                <div>
                  <div className="dim" style={{ fontSize: 11.5 }}>มูลค่ารวม</div>
                  <div className="num" style={{ fontSize: 17, fontWeight: 600 }}>{fmt(project.value_total)} ฿</div>
                </div>
                <div>
                  <div className="dim" style={{ fontSize: 11.5 }}>เบิกแล้ว</div>
                  <div className="num" style={{ fontSize: 17, fontWeight: 600, color: "var(--success)" }}>{fmt(project.paid_total)} ฿</div>
                </div>
                <div>
                  <div className="dim" style={{ fontSize: 11.5 }}>คงเหลือ</div>
                  <div className="num" style={{ fontSize: 17, fontWeight: 600, color: "var(--warn)" }}>{fmt(project.value_total - project.paid_total)} ฿</div>
                </div>
              </div>
            </>
          )}
        </div>
      </div>

      {!projectId ? (
        <div className="card">
          <div className="detail-empty" style={{ padding: 56 }}>
            <div className="ico"><Icon name="folder" size={40} /></div>
            <div style={{ fontWeight: 500, color: "var(--text-2)" }}>กรุณาเลือกโครงการเพื่อดูรายการสัญญา</div>
          </div>
        </div>
      ) : (
        <div className="dual">
          <div className="card card-flush">
            <div className="card-head">
              <h3>รายการสัญญา</h3>
              <span className="sub">{contracts.length} ฉบับ</span>
              <div style={{ flex: 1 }}></div>
              <input className="input" placeholder="ค้นหาเลขที่ / รายละเอียด..." value={search} onChange={(e) => setSearch(e.target.value)} style={{ maxWidth: 260 }} />
            </div>
            <div className="tbl-wrap">
              <table className="tbl">
                <thead>
                  <tr>
                    <th>เลขที่สัญญา</th>
                    <th>รายละเอียด</th>
                    <th>วันที่</th>
                    <th className="r">มูลค่า</th>
                    <th style={{ width: 130 }}>คืบหน้า</th>
                    <th className="c">ไฟล์</th>
                  </tr>
                </thead>
                <tbody>
                  {contracts.map((c) => (
                    <tr key={c.id} className={selectedId === c.id ? "selected" : ""} onClick={() => setSelectedId(c.id)} style={{ cursor: "pointer" }}>
                      <td>
                        <div className="strong mono" style={{ color: "var(--brand-700)" }}>{c.contract_number}</div>
                        <div className="dim" style={{ fontSize: 11 }}>{c.house_count > 0 ? `${c.house_count} หลัง` : "ไม่มีบ้าน"}</div>
                      </td>
                      <td>{c.description}</td>
                      <td className="dim mono">{c.contract_date}</td>
                      <td className="r num">{fmt(c.value_total)}</td>
                      <td><Progress paid={c.paid_total} total={c.value_total} /></td>
                      <td className="c">
                        {c.attachment_name
                          ? <span title={c.attachment_name} style={{ color: "var(--brand)", cursor: "pointer" }} onClick={(e) => { e.stopPropagation(); window.open(c.attachment_url, "_blank"); }}><Icon name="paperclip" size={14} /></span>
                          : <span className="dim">—</span>}
                      </td>
                    </tr>
                  ))}
                  {contracts.length === 0 && (
                    <tr><td colSpan={6} className="c dim" style={{ padding: 40 }}>ยังไม่มีสัญญาในโครงการนี้ — กด "เพิ่มสัญญา"</td></tr>
                  )}
                </tbody>
              </table>
            </div>
          </div>

          <div className="detail-panel">
            {!selected ? (
              <div className="card">
                <div className="detail-empty">
                  <div className="ico"><Icon name="contract" size={36} /></div>
                  <div style={{ fontWeight: 500, color: "var(--text-2)" }}>เลือกสัญญาเพื่อดูรายละเอียด</div>
                </div>
              </div>
            ) : (
              <ContractDetail
                c={selected}
                projectId={projectId}
                onOpenHouses={() => onOpenHouses(selected.id)}
                onUpdate={(fields) => onUpdateContract(selected.id, fields)}
                onDelete={(val, paid, attPath) => onDeleteContract(selected.id, val, paid, attPath)}
                onAfterDelete={() => setSelectedId(null)}
              />
            )}
          </div>
        </div>
      )}

      {showNew && (
        <NewContractModal
          onClose={() => setShowNew(false)}
          onCreate={async (c) => {
            try { await onAddContract(projectId, c); setShowNew(false); toast({ t: "บันทึกสัญญาสำเร็จ", s: c.contract_number }); }
            catch(e) { toast({ t: "บันทึกไม่สำเร็จ", s: e.message }); }
          }}
        />
      )}
      {showBulk && (
        <BulkPaymentModal
          data={data}
          projectId={projectId}
          onClose={() => setShowBulk(false)}
          onSave={async (items, meta) => {
            let count = 0;
            for (const it of items) {
              try {
                await onAddPayment(it.cid, it.id, { date: meta.date, inv: meta.inv, amount: Number(it.amount), notes: "", file: meta.file });
                count++;
              } catch(e) {}
            }
            setShowBulk(false);
            toast({ t: `บันทึกเบิกจ่าย ${count} รายการสำเร็จ`, s: `รวม ฿${fmt(items.reduce((s,i) => s + Number(i.amount), 0))}` });
          }}
        />
      )}
    </div>
  );
}

function ContractDetail({ c, projectId, onOpenHouses, onUpdate, onDelete, onAfterDelete }) {
  const [showDelete, setShowDelete] = useState(false);
  const [showEdit, setShowEdit] = useState(false);
  const [delLoading, setDelLoading] = useState(false);
  const toast = useToast();

  const remain = c.value_total - c.paid_total;
  const pct = (c.paid_total / Math.max(1, c.value_total)) * 100 || 0;

  const handleDelete = async () => {
    setDelLoading(true);
    try {
      await onDelete(c.value_total, c.paid_total, c.attachment_path);
      toast({ t: "ลบสัญญาสำเร็จ", s: c.contract_number });
      setShowDelete(false);
      onAfterDelete();
    } catch(e) {
      toast({ t: "ลบไม่สำเร็จ", s: e.message });
    }
    setDelLoading(false);
  };

  const handlePrintPDF = () => {
    const html = `<!DOCTYPE html><html lang="th"><head><meta charset="UTF-8"><title>สัญญา ${c.contract_number}</title>
      <style>body{font-family:'Sarabun','Noto Sans Thai',sans-serif;padding:32px;color:#111}h1{color:#1D4ED8}table{width:100%;border-collapse:collapse;margin-top:16px}td{padding:10px;border-bottom:1px solid #e2e8f0}.r{text-align:right;font-weight:600}@media print{body{print-color-adjust:exact}}</style>
      </head><body><h1>สัญญาเลขที่ ${c.contract_number}</h1><p style="color:#64748b">${c.description} · วันที่ ${c.contract_date}</p>
      <table>
        <tr><td>มูลค่าสัญญา</td><td class="r">฿${c.value_total.toLocaleString()}</td></tr>
        <tr><td>เบิกจ่ายแล้ว</td><td class="r" style="color:#16a34a">฿${c.paid_total.toLocaleString()}</td></tr>
        <tr><td>คงเหลือ</td><td class="r" style="color:#d97706">฿${remain.toLocaleString()}</td></tr>
        <tr><td>ความคืบหน้า</td><td class="r">${pct.toFixed(1)}%</td></tr>
        <tr><td>จำนวนบ้าน</td><td class="r">${c.house_count} หลัง</td></tr>
      </table></body></html>`;
    const w = window.open("", "_blank");
    w.document.write(html); w.document.close();
    setTimeout(() => w.print(), 400);
  };

  return (
    <>
      <div className="card">
        <div className="card-head" style={{ flexDirection: "column", alignItems: "flex-start", gap: 6 }}>
          <div className="hstack" style={{ width: "100%" }}>
            <span className="pill brand mono">{c.contract_number}</span>
            <div style={{ flex: 1 }}></div>
            <button className="ico-btn" title="แก้ไข" onClick={() => setShowEdit(true)}><Icon name="edit" size={13} /></button>
            <button className="ico-btn danger" title="ลบสัญญา" onClick={() => setShowDelete(true)}><Icon name="trash" size={13} /></button>
          </div>
          <h3>{c.description}</h3>
          <div className="dim" style={{ fontSize: 12 }}>ลงวันที่ {c.contract_date}</div>
        </div>
        <div className="card-body">
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10, marginBottom: 12 }}>
            <div className="stat" style={{ padding: 12 }}>
              <div className="label" style={{ fontSize: 11 }}>มูลค่า</div>
              <div className="value" style={{ fontSize: 17 }}>฿{fmt(c.value_total)}</div>
            </div>
            <div className="stat accent-green" style={{ padding: 12 }}>
              <div className="label" style={{ fontSize: 11 }}>เบิกแล้ว</div>
              <div className="value" style={{ fontSize: 17, color: "var(--success)" }}>฿{fmt(c.paid_total)}</div>
            </div>
          </div>
          <div className="prog" style={{ marginBottom: 14 }}>
            <div className="hstack" style={{ justifyContent: "space-between", marginBottom: 4 }}>
              <span style={{ fontSize: 12, fontWeight: 500 }}>คืบหน้าการเบิก</span>
              <span className="num" style={{ fontWeight: 600 }}>{pct.toFixed(1)}%</span>
            </div>
            <div className="prog-bar" style={{ height: 8 }}><div className="prog-fill" style={{ width: pct + "%" }}></div></div>
            <div className="prog-meta"><span>เบิกแล้ว ฿{fmt(c.paid_total)}</span><span>คงเหลือ ฿{fmt(remain)}</span></div>
          </div>

          <div style={{ borderTop: "1px solid var(--border)", paddingTop: 12, marginBottom: 12 }}>
            <div className="dim" style={{ fontSize: 11, fontWeight: 500, marginBottom: 6 }}>ไฟล์สัญญา</div>
            {c.attachment_name ? (
              <div className="hstack" style={{ background: "var(--brand-50)", border: "1px solid #BFDBFE", borderRadius: 8, padding: "8px 10px" }}>
                <Icon name="file" size={16} className="dim" />
                <span style={{ flex: 1, fontSize: 13, fontWeight: 500 }}>{c.attachment_name}</span>
                <button className="ico-btn" title="ดูไฟล์" onClick={() => window.open(c.attachment_url, "_blank")}><Icon name="eye" size={13} /></button>
                <a href={c.attachment_url} download={c.attachment_name} target="_blank" className="ico-btn" title="ดาวน์โหลด" style={{ display: "inline-flex", alignItems: "center", justifyContent: "center" }}><Icon name="download" size={13} /></a>
              </div>
            ) : (
              <div className="file-drop" style={{ padding: 10, cursor: "not-allowed", opacity: 0.6 }}>
                <div className="ico" style={{ width: 30, height: 30 }}><Icon name="paperclip" size={14} /></div>
                <div style={{ flex: 1 }}>
                  <div className="t" style={{ fontSize: 12 }}>ยังไม่มีไฟล์แนบ</div>
                  <div className="s">แก้ไขสัญญาเพื่อแนบไฟล์</div>
                </div>
              </div>
            )}
          </div>

          <button className="btn primary" style={{ width: "100%", justifyContent: "center" }} onClick={onOpenHouses}>
            จัดการบ้านในสัญญานี้ ({c.house_count}) <Icon name="arrowR" size={13} />
          </button>
          <button className="btn" style={{ width: "100%", justifyContent: "center", marginTop: 6 }} onClick={handlePrintPDF}>
            <Icon name="print" size={13} /> พิมพ์รายงานสัญญา PDF
          </button>
        </div>
      </div>

      {showDelete && (
        <DeleteConfirmModal
          title="ลบสัญญา"
          message={`ลบสัญญา "${c.contract_number} - ${c.description}" และบ้านทั้งหมด ${c.house_count} หลัง — มูลค่า ฿${fmt(c.value_total)} จะถูกลบถาวร`}
          loading={delLoading}
          onClose={() => setShowDelete(false)}
          onConfirm={handleDelete}
        />
      )}
      {showEdit && (
        <EditContractModal
          contract={c}
          onClose={() => setShowEdit(false)}
          onSave={async (fields) => {
            await onUpdate(fields);
            toast({ t: "แก้ไขสัญญาสำเร็จ", s: fields.contract_number });
          }}
        />
      )}
    </>
  );
}

// =====================================================
// HOUSES
// =====================================================
function HousesScreen({ data, contractId, projectId, onBack, onAddHouse, onAddPayment, onUpdateHouse, onDeleteHouse, onDeletePayment, onLoadPayments }) {
  const [selectedId, setSelectedId] = useState(null);
  const [search, setSearch] = useState("");
  const [filter, setFilter] = useState("all");
  const [showAddRange, setShowAddRange] = useState(false);
  const [showBulkText, setShowBulkText] = useState(false);
  const [showPayment, setShowPayment] = useState(null);
  const [showHistory, setShowHistory] = useState(null);
  const toast = useToast();

  const project = data.projects.find((p) => p.id === projectId);
  const contract = (data.contracts[projectId] || []).find((c) => c.id === contractId);
  const houses = (data.houses[contractId] || []);

  // Load payments whenever selected house changes
  useEffect(() => {
    if (selectedId && projectId && contractId) {
      onLoadPayments(selectedId);
    }
  }, [selectedId, projectId, contractId]);

  const filtered = houses
    .filter((h) => {
      if (search && !h.house_code.toLowerCase().includes(search.toLowerCase())) return false;
      const remain = h.price - h.paid_total;
      if (filter === "paid" && remain > 0) return false;
      if (filter === "owing" && remain <= 0) return false;
      if (filter === "untouched" && h.paid_total > 0) return false;
      return true;
    })
    .sort((a, b) => a.house_code.localeCompare(b.house_code, undefined, { numeric: true, sensitivity: "base" }));

  const selected = houses.find((h) => h.id === selectedId);

  const totalPrice = houses.reduce((s, h) => s + h.price, 0);
  const totalPaid = houses.reduce((s, h) => s + h.paid_total, 0);
  const fullyPaid = houses.filter((h) => h.paid_total >= h.price).length;

  const handleExcel = () => {
    const rows = houses.map(h => ({
      "รหัสบ้าน": h.house_code,
      "ราคา (บาท)": h.price,
      "เบิกแล้ว (บาท)": h.paid_total,
      "คงเหลือ (บาท)": h.price - h.paid_total,
      "จำนวนงวด": h.payments,
      "หมายเหตุ": h.notes || "",
    }));
    exportExcel([{ name: "บ้าน", rows }], `บ้าน_${contract?.contract_number || "export"}`);
    toast({ t: "ส่งออก Excel สำเร็จ" });
  };

  return (
    <div className="page">
      <div className="page-head">
        <div>
          <button className="btn ghost sm" onClick={onBack} style={{ marginBottom: 8, padding: "4px 8px" }}>
            <Icon name="chevL" size={13} /> กลับไปรายการสัญญา
          </button>
          <h1 className="page-title">บ้านในสัญญา {contract?.contract_number}</h1>
          <p className="page-sub">{contract?.description} · {project?.name}</p>
        </div>
        <div className="page-actions">
          <button className="btn" onClick={handleExcel}><Icon name="excel" size={13} /> Excel</button>
          <button className="btn" onClick={() => setShowBulkText(true)}><Icon name="upload" size={13} /> เพิ่มแบบ Text</button>
          <button className="btn primary" onClick={() => setShowAddRange(true)}><Icon name="plus" size={13} /> เพิ่มบ้านแบบกลุ่ม</button>
        </div>
      </div>

      <div className="stat-grid" style={{ gridTemplateColumns: "repeat(4,1fr)" }}>
        <div className="stat"><div className="label">บ้านทั้งหมด</div><div className="value">{houses.length}</div><div className="delta dim">{fullyPaid} จ่ายครบแล้ว</div></div>
        <div className="stat accent-green"><div className="label">มูลค่ารวม</div><div className="value">{fmtCompact(totalPrice)}</div><div className="accent"><Icon name="money" size={14} /></div></div>
        <div className="stat"><div className="label">เบิกแล้ว</div><div className="value" style={{ color: "var(--success)" }}>{fmtCompact(totalPaid)}</div></div>
        <div className="stat accent-warn"><div className="label">คงเหลือ</div><div className="value" style={{ color: "var(--warn)" }}>{fmtCompact(totalPrice - totalPaid)}</div><div className="accent"><Icon name="wallet" size={14} /></div></div>
      </div>

      <div className="dual">
        <div className="card card-flush">
          <div className="card-head" style={{ gap: 8 }}>
            <input className="input" placeholder="ค้นหารหัสบ้าน..." value={search} onChange={(e) => setSearch(e.target.value)} style={{ maxWidth: 220 }} />
            <div className="hstack" style={{ gap: 4 }}>
              {[["all","ทั้งหมด"],["owing","ยังค้างจ่าย"],["paid","จ่ายครบ"],["untouched","ยังไม่เบิก"]].map(([k,l]) => (
                <button key={k} className={`btn sm ${filter === k ? "primary" : ""}`} onClick={() => setFilter(k)}>{l}</button>
              ))}
            </div>
            <div style={{ flex: 1 }}></div>
            <span className="dim" style={{ fontSize: 12 }}>{filtered.length} หลัง</span>
          </div>
          <div className="tbl-wrap" style={{ maxHeight: 560, overflow: "auto" }}>
            <table className="tbl">
              <thead>
                <tr>
                  <th>รหัสบ้าน</th>
                  <th className="r">ราคา</th>
                  <th className="r">เบิกแล้ว</th>
                  <th className="r">คงเหลือ</th>
                  <th>หมายเหตุ</th>
                  <th className="c" style={{ width: 80 }}>งวด</th>
                </tr>
              </thead>
              <tbody>
                {filtered.map((h) => {
                  const remain = h.price - h.paid_total;
                  return (
                    <tr key={h.id} className={selectedId === h.id ? "selected" : ""} onClick={() => setSelectedId(h.id)} style={{ cursor: "pointer" }}>
                      <td className="strong mono">{h.house_code}</td>
                      <td className="r num">{fmt(h.price)}</td>
                      <td className="r num" style={{ color: "var(--brand-700)" }}>{fmt(h.paid_total)}</td>
                      <td className="r num" style={{ color: remain > 0 ? "var(--warn)" : "var(--success)", fontWeight: 600 }}>
                        {remain > 0 ? fmt(remain) : <Icon name="check" size={14} />}
                      </td>
                      <td className="dim" style={{ fontSize: 12, maxWidth: 160, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{h.notes || "—"}</td>
                      <td className="c"><span className="pill" style={{ padding: "1px 7px" }}>{h.payments}</span></td>
                    </tr>
                  );
                })}
                {filtered.length === 0 && (
                  <tr><td colSpan={6} className="c dim" style={{ padding: 40 }}>ไม่พบบ้านที่ตรงเงื่อนไข</td></tr>
                )}
              </tbody>
            </table>
          </div>
        </div>

        <div className="detail-panel">
          {!selected ? (
            <div className="card">
              <div className="detail-empty">
                <div className="ico"><Icon name="house" size={36} /></div>
                <div style={{ fontWeight: 500, color: "var(--text-2)" }}>เลือกบ้านเพื่อดูรายละเอียด</div>
                <div style={{ fontSize: 12, marginTop: 4 }}>คลิกแถวเพื่อดูยอด, ประวัติ และเบิกจ่าย</div>
              </div>
            </div>
          ) : (
            <HouseDetail
              h={selected}
              payments={data.payments[selected.id] || []}
              onPay={() => setShowPayment(selected)}
              onHistory={() => setShowHistory(selected)}
              onDelete={(price, paid) => onDeleteHouse(selected.id, price, paid)}
              onUpdate={(fields, oldPrice) => onUpdateHouse(selected.id, fields, oldPrice)}
              onAfterDelete={() => setSelectedId(null)}
            />
          )}
        </div>
      </div>

      {showAddRange && (
        <AddRangeModal
          onClose={() => setShowAddRange(false)}
          onSave={async (payload) => {
            try {
              for (const code of payload.codes) await onAddHouse(projectId, contractId, { house_code: `${payload.form.prefix}${code}`, price: Number(payload.form.price), notes: payload.form.note });
              setShowAddRange(false);
              toast({ t: `เพิ่มบ้านสำเร็จ ${payload.count} หลัง` });
            } catch(e) { toast({ t: "ไม่สำเร็จ", s: e.message }); }
          }}
        />
      )}
      {showBulkText && (
        <BulkTextModal
          onClose={() => setShowBulkText(false)}
          onSave={async (parsed) => {
            try {
              for (const r of parsed) await onAddHouse(projectId, contractId, r);
              setShowBulkText(false);
              toast({ t: `เพิ่มบ้าน ${parsed.length} รายการสำเร็จ` });
            } catch(e) { toast({ t: "ไม่สำเร็จ", s: e.message }); }
          }}
        />
      )}
      {showPayment && (
        <PaymentModal
          house={showPayment}
          onClose={() => setShowPayment(null)}
          onSave={async (form) => {
            try {
              await onAddPayment(projectId, contractId, showPayment.id, form);
              setShowPayment(null);
              toast({ t: "บันทึกเบิกจ่ายสำเร็จ", s: `${fmt(Number(form.amount))} บาท` });
            } catch(e) { toast({ t: "ไม่สำเร็จ", s: e.message }); }
          }}
        />
      )}
      {showHistory && (
        <HistoryModal
          house={showHistory}
          payments={data.payments[showHistory.id] || []}
          onClose={() => setShowHistory(null)}
          onDeletePayment={(payId, amount, receiptPath) => onDeletePayment(showHistory.id, payId, amount, receiptPath)}
          onLoad={() => onLoadPayments(showHistory.id)}
        />
      )}
    </div>
  );
}

function HouseDetail({ h, payments, onPay, onHistory, onDelete, onUpdate, onAfterDelete }) {
  const [showDelete, setShowDelete] = useState(false);
  const [showEdit, setShowEdit] = useState(false);
  const [delLoading, setDelLoading] = useState(false);
  const toast = useToast();

  const remain = h.price - h.paid_total;
  const pct = (h.paid_total / Math.max(1, h.price)) * 100 || 0;
  const done = remain <= 0;

  const handleDelete = async () => {
    setDelLoading(true);
    try {
      await onDelete(h.price, h.paid_total);
      toast({ t: "ลบบ้านสำเร็จ", s: h.house_code });
      setShowDelete(false);
      onAfterDelete();
    } catch(e) {
      toast({ t: "ลบไม่สำเร็จ", s: e.message });
    }
    setDelLoading(false);
  };

  const handlePrint = () => {
    const rows = payments.map(p =>
      `<tr><td>${fmtDate(p.date)}</td><td>${p.inv || "—"}</td><td style="text-align:right;color:#16a34a">฿${p.amount.toLocaleString()}</td><td>${p.notes || "—"}</td></tr>`
    ).join("");
    const html = `<!DOCTYPE html><html lang="th"><head><meta charset="UTF-8"><title>บ้าน ${h.house_code}</title>
      <style>body{font-family:'Sarabun','Noto Sans Thai',sans-serif;padding:32px;color:#111}h1{color:#1D4ED8}table{width:100%;border-collapse:collapse;margin-top:16px}th{background:#1D4ED8;color:#fff;padding:8px;text-align:left}td{padding:8px;border-bottom:1px solid #e2e8f0}@media print{body{print-color-adjust:exact}}</style>
      </head><body><h1>บ้าน ${h.house_code}</h1>
      <p style="color:#64748b">ราคา ฿${h.price.toLocaleString()} · เบิกแล้ว ฿${h.paid_total.toLocaleString()} · คงเหลือ ฿${remain.toLocaleString()}</p>
      ${payments.length ? `<table><thead><tr><th>วันที่</th><th>เลขใบกำกับ</th><th>ยอด</th><th>หมายเหตุ</th></tr></thead><tbody>${rows}</tbody></table>` : "<p>ยังไม่มีรายการเบิก</p>"}
      </body></html>`;
    const w = window.open("", "_blank");
    w.document.write(html); w.document.close();
    setTimeout(() => w.print(), 400);
  };

  return (
    <>
      <div className="card">
        <div className="card-head" style={{ flexDirection: "column", alignItems: "flex-start", gap: 6 }}>
          <div className="hstack" style={{ width: "100%" }}>
            {done ? <span className="pill success"><span className="dot"></span>จ่ายครบแล้ว</span>
              : h.paid_total > 0 ? <span className="pill brand"><span className="dot"></span>เบิกบางส่วน</span>
              : <span className="pill warn"><span className="dot"></span>ยังไม่เบิก</span>}
            <div style={{ flex: 1 }}></div>
            <button className="ico-btn" title="แก้ไข" onClick={() => setShowEdit(true)}><Icon name="edit" size={13} /></button>
            <button className="ico-btn danger" title="ลบบ้านนี้" onClick={() => setShowDelete(true)}><Icon name="trash" size={13} /></button>
          </div>
          <h3 style={{ fontSize: 22, fontFamily: "IBM Plex Mono, monospace", letterSpacing: "0.02em" }}>{h.house_code}</h3>
          {h.notes && <div className="dim" style={{ fontSize: 12 }}>{h.notes}</div>}
        </div>
        <div className="card-body">
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 8, marginBottom: 12 }}>
            <div className="stat" style={{ padding: 10 }}>
              <div className="label" style={{ fontSize: 10.5 }}>ราคา</div>
              <div className="value" style={{ fontSize: 14 }}>฿{fmt(h.price)}</div>
            </div>
            <div className="stat" style={{ padding: 10 }}>
              <div className="label" style={{ fontSize: 10.5 }}>เบิกแล้ว</div>
              <div className="value" style={{ fontSize: 14, color: "var(--success)" }}>฿{fmt(h.paid_total)}</div>
            </div>
            <div className="stat" style={{ padding: 10 }}>
              <div className="label" style={{ fontSize: 10.5 }}>คงเหลือ</div>
              <div className="value" style={{ fontSize: 14, color: remain > 0 ? "var(--warn)" : "var(--success)" }}>฿{fmt(remain)}</div>
            </div>
          </div>

          <div className="prog" style={{ marginBottom: 14 }}>
            <div className="prog-bar" style={{ height: 8 }}><div className={`prog-fill ${done ? "success" : ""}`} style={{ width: pct + "%" }}></div></div>
            <div className="prog-meta"><span className="num" style={{ fontWeight: 600 }}>{pct.toFixed(0)}%</span><span>{h.payments} งวด</span></div>
          </div>

          <div style={{ borderTop: "1px solid var(--border)", paddingTop: 12 }}>
            <div className="hstack" style={{ justifyContent: "space-between", marginBottom: 8 }}>
              <div style={{ fontSize: 12, fontWeight: 500 }}>การเบิกจ่ายล่าสุด</div>
              <button className="btn ghost sm" onClick={onHistory}>ดูทั้งหมด <Icon name="chevR" size={11} /></button>
            </div>
            {payments.length === 0 ? (
              <div className="dim" style={{ fontSize: 12, padding: "12px 0", textAlign: "center" }}>ยังไม่มีรายการเบิก</div>
            ) : (
              <div className="vstack" style={{ gap: 6 }}>
                {payments.slice(0, 3).map((p) => (
                  <div key={p.id} className="hstack" style={{ padding: "6px 0", borderBottom: "1px dashed var(--border)" }}>
                    <div style={{ flex: 1 }}>
                      <div style={{ fontSize: 12.5, fontWeight: 500 }}>{p.notes || "—"}</div>
                      <div className="dim mono" style={{ fontSize: 11 }}>{p.inv || "—"} · {fmtDate(p.date)}</div>
                    </div>
                    <div className="num" style={{ fontWeight: 600, color: "var(--success)" }}>฿{fmt(p.amount)}</div>
                  </div>
                ))}
              </div>
            )}
          </div>

          <button className="btn primary" disabled={done} style={{ width: "100%", justifyContent: "center", marginTop: 14 }} onClick={onPay}>
            <Icon name="plus" size={13} /> {done ? "จ่ายครบแล้ว" : "บันทึกเบิกจ่ายใหม่"}
          </button>
          <div className="hstack" style={{ marginTop: 6, gap: 6 }}>
            <button className="btn sm" style={{ flex: 1, justifyContent: "center" }} onClick={onHistory}><Icon name="history" size={12} /> ประวัติ</button>
            <button className="btn sm" style={{ flex: 1, justifyContent: "center" }} onClick={handlePrint}><Icon name="print" size={12} /> พิมพ์</button>
          </div>
        </div>
      </div>

      {showDelete && (
        <DeleteConfirmModal
          title="ลบบ้าน / ยูนิต"
          message={`ลบบ้าน "${h.house_code}" ราคา ฿${fmt(h.price)} และประวัติเบิกจ่าย ${h.payments} งวด — ข้อมูลจะถูกลบถาวร`}
          loading={delLoading}
          onClose={() => setShowDelete(false)}
          onConfirm={handleDelete}
        />
      )}
      {showEdit && (
        <EditHouseModal
          house={h}
          onClose={() => setShowEdit(false)}
          onSave={async (fields, oldPrice) => {
            await onUpdate(fields, oldPrice);
            toast({ t: "แก้ไขบ้านสำเร็จ", s: fields.house_code });
          }}
        />
      )}
    </>
  );
}

// =====================================================
// REPORTS — detailed PDF/Excel generation
// =====================================================

function buildBaseHTML(title, body) {
  return `<!DOCTYPE html><html lang="th"><head><meta charset="UTF-8"><title>${title}</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:'Sarabun','Noto Sans Thai',sans-serif;font-size:12.5px;color:#111;background:#fff;padding:20px 28px}
h1{font-size:20px;color:#1D4ED8;margin-bottom:2px}
.sub{font-size:11.5px;color:#64748b;margin-bottom:18px}
.stat-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:10px;margin-bottom:18px}
.stat-box{border:1px solid #e2e8f0;border-radius:6px;padding:9px 12px}
.stat-box .lbl{font-size:10.5px;color:#64748b}.stat-box .val{font-size:17px;font-weight:700;margin-top:2px}
table{width:100%;border-collapse:collapse;margin-bottom:12px;font-size:12px}
th{background:#1D4ED8;color:#fff;padding:7px 9px;text-align:left;font-size:11.5px}
td{padding:5px 9px;border-bottom:1px solid #e2e8f0}
.r{text-align:right}.b{font-weight:700}.mono{font-family:monospace;font-size:11.5px}
.project-hd{background:#EFF6FF;border-left:4px solid #1D4ED8;padding:10px 14px;margin:20px 0 6px;border-radius:0 6px 6px 0}
.project-hd .pname{font-size:15px;font-weight:700;color:#1D4ED8;display:block}
.project-hd .pmeta{font-size:11px;color:#64748b;margin-top:3px}
.contract-hd{background:#F0FDF4;border-left:3px solid #16a34a;padding:7px 12px;margin:10px 0 2px;border-radius:0 4px 4px 0}
.contract-hd .cnum{font-size:13px;font-weight:700;color:#15803d;font-family:monospace}
.contract-hd .cdesc{font-size:12.5px;color:#166534;margin-left:8px}
.contract-hd .cmeta{font-size:11px;color:#64748b;margin-top:2px}
.house-row td{font-weight:600;background:#fff}
.pay-row td{background:#F8FAFC;font-size:11.5px;padding:3px 9px}
.pay-inner{display:flex;gap:12px;align-items:center;padding-left:22px;flex-wrap:wrap}
.ngwd{background:#DBEAFE;color:#1e40af;padding:1px 6px;border-radius:3px;font-size:10.5px;font-weight:700;white-space:nowrap;font-family:monospace}
.pay-date{color:#475569;font-family:monospace;font-size:11px}
.pay-inv{color:#64748b;font-family:monospace;font-size:11px}
.pay-amt{color:#16a34a;font-weight:700;font-size:12px;white-space:nowrap}
.pay-note{color:#64748b;font-size:11px}
.no-pay{color:#94a3b8;font-size:11px;padding:3px 9px 3px 30px;font-style:italic;background:#fafafa}
.tfoot-row td{background:#f1f5f9;font-weight:700;border-top:2px solid #cbd5e1}
@media print{
  body{print-color-adjust:exact;-webkit-print-color-adjust:exact;padding:12px 16px}
  button{display:none}
  .no-break{page-break-inside:avoid}
  .project-hd{page-break-before:auto}
}
</style>
<script>window.onload=function(){setTimeout(function(){window.print()},700)}</script>
</head><body>
<h1>${title}</h1>
<div class="sub">สร้างเมื่อ ${new Date().toLocaleDateString("th-TH",{year:"numeric",month:"long",day:"numeric"})} ${new Date().toLocaleTimeString("th-TH",{hour:"2-digit",minute:"2-digit"})} — JS Contract System</div>
${body}
<div style="text-align:center;padding:16px 0;color:#94a3b8;font-size:11px;border-top:1px solid #e2e8f0;margin-top:16px">
  © JS Contract System
</div></body></html>`;
}

function openHTML(html, targetWindow) {
  if (targetWindow && !targetWindow.closed) {
    targetWindow.document.open();
    targetWindow.document.write(html);
    targetWindow.document.close();
  } else {
    const w = window.open("", "_blank");
    if (!w) { alert("กรุณาอนุญาต Pop-up สำหรับเว็บไซต์นี้ แล้วลองใหม่"); return; }
    w.document.write(html);
    w.document.close();
  }
}

function ReportsScreen({ data }) {
  const [generating, setGenerating] = useState(null);
  const toast = useToast();

  const tick = (ms = 80) => new Promise(r => setTimeout(r, ms));

  const generateReport = async (type, name, format) => {
    // Open window IMMEDIATELY (sync, in user-gesture context) so browser won't block popup
    let targetWindow = null;
    if (format !== "xlsx") {
      targetWindow = window.open("", "_blank");
      if (targetWindow) {
        targetWindow.document.write(`<!DOCTYPE html><html lang="th"><head><meta charset="UTF-8"><title>กำลังสร้างรายงาน...</title>
          <style>body{font-family:'Sarabun',sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#f8fafc;color:#64748b;flex-direction:column;gap:16px}
          .spin{width:40px;height:40px;border:3px solid #e2e8f0;border-top-color:#2563eb;border-radius:50%;animation:s 0.8s linear infinite}
          @keyframes s{to{transform:rotate(360deg)}}</style></head>
          <body><div class="spin"></div><div style="font-size:15px">กำลังสร้างรายงาน <b>${name}</b>...</div></body></html>`);
      }
    }

    setGenerating({ type, name, format, step: 0 });
    await tick(100);

    try {
      // Step 1: Load ALL payments from Firebase (server-side data)
      setGenerating(g => ({ ...g, step: 1 }));
      await window.FB.loadAllPayments();
      await tick(150);

      // Use fresh payments from live FB state — not the stale React prop
      const allPayments = window.FB.state.payments || {};

      // Step 2: Process projects + contracts
      setGenerating(g => ({ ...g, step: 2 }));
      await tick(200);
      const projects = data.projects;

      // Step 3: Process houses + build content
      setGenerating(g => ({ ...g, step: 3 }));
      await tick(200);

      let htmlBody = "";
      let excelSheets = [];

      // ── Summary all ──────────────────────────────────────
      if (type === "summary-all") {
        const totalVal  = projects.reduce((s,p) => s+p.value_total, 0);
        const totalPaid = projects.reduce((s,p) => s+p.paid_total, 0);
        const totalC    = projects.reduce((s,p) => s+p.contract_count, 0);
        const totalH    = projects.reduce((s,p) => s+p.house_count, 0);

        htmlBody = `<div class="stat-row">
          <div class="stat-box"><div class="lbl">โครงการ</div><div class="val">${projects.length}</div></div>
          <div class="stat-box"><div class="lbl">มูลค่ารวม (บาท)</div><div class="val">฿${totalVal.toLocaleString()}</div></div>
          <div class="stat-box"><div class="lbl">เบิกแล้ว (บาท)</div><div class="val" style="color:#16a34a">฿${totalPaid.toLocaleString()}</div></div>
          <div class="stat-box"><div class="lbl">คงเหลือ (บาท)</div><div class="val" style="color:#d97706">฿${(totalVal-totalPaid).toLocaleString()}</div></div>
          <div class="stat-box"><div class="lbl">สัญญา</div><div class="val">${totalC}</div></div>
          <div class="stat-box"><div class="lbl">บ้านทั้งหมด</div><div class="val">${totalH}</div></div>
        </div>
        <table><thead><tr>
          <th>โครงการ</th><th>ลูกค้า</th><th>สถานะ</th>
          <th class="r">มูลค่า (บาท)</th><th class="r">เบิกแล้ว (บาท)</th><th class="r">คงเหลือ (บาท)</th>
          <th class="r">%</th><th class="r">สัญญา</th><th class="r">บ้าน</th>
        </tr></thead><tbody>
        ${projects.map(p => {
          const pct = p.value_total > 0 ? ((p.paid_total/p.value_total)*100).toFixed(1) : "0.0";
          const st = p.status==="active"?"กำลังดำเนินการ":p.status==="completed"?"เสร็จสิ้น":"รอเริ่มงาน";
          return `<tr><td class="b">${p.name}</td><td>${p.client||"-"}</td><td>${st}</td>
            <td class="r">${p.value_total.toLocaleString()}</td>
            <td class="r" style="color:#16a34a">${p.paid_total.toLocaleString()}</td>
            <td class="r" style="color:#d97706">${(p.value_total-p.paid_total).toLocaleString()}</td>
            <td class="r">${pct}%</td><td class="r">${p.contract_count}</td><td class="r">${p.house_count}</td></tr>`;
        }).join("")}
        </tbody></table>`;

        excelSheets = [{ name: "โครงการ", rows: projects.map(p => ({
          "โครงการ": p.name, "ลูกค้า": p.client||"",
          "สถานะ": p.status==="active"?"กำลังดำเนินการ":p.status==="completed"?"เสร็จสิ้น":"รอเริ่มงาน",
          "มูลค่า (บาท)": p.value_total, "เบิกแล้ว (บาท)": p.paid_total,
          "คงเหลือ (บาท)": p.value_total-p.paid_total,
          "% คืบหน้า": p.value_total>0?((p.paid_total/p.value_total)*100).toFixed(1)+"%" : "0%",
          "สัญญา": p.contract_count, "บ้าน": p.house_count,
        })) }];

      // ── Detailed by project (โครงการ→สัญญา→บ้าน→งวด) ───────
      } else if (type === "by-project") {
        const rowsC = [], rowsH = [], rowsPay = [];

        for (const p of projects) {
          const contracts = data.contracts[p.id] || [];
          const pPct = p.value_total>0 ? ((p.paid_total/p.value_total)*100).toFixed(1) : "0.0";

          let contractsHTML = "";
          for (const c of contracts) {
            const houses = (data.houses[c.id] || [])
              .slice()
              .sort((a,b) => a.house_code.localeCompare(b.house_code, undefined, { numeric: true, sensitivity: "base" }));
            const cPct = c.value_total>0 ? ((c.paid_total/c.value_total)*100).toFixed(1) : "0.0";
            let totalCngwd = 0;

            let houseRows = "";
            for (const h of houses) {
              const pays = (allPayments[h.id] || [])
                .slice()
                .sort((a,b) => a.date > b.date ? 1 : -1);
              totalCngwd += pays.length;
              const remain = h.price - h.paid_total;

              houseRows += `<tr class="house-row">
                <td class="mono">${h.house_code}</td>
                <td class="r">${h.price.toLocaleString()}</td>
                <td class="r" style="color:#16a34a">${h.paid_total.toLocaleString()}</td>
                <td class="r" style="color:${remain>0?"#d97706":"#16a34a"};font-weight:700">${remain>0?remain.toLocaleString():"ครบ ✓"}</td>
                <td class="r">${pays.length} งวด</td>
              </tr>`;

              if (pays.length > 0) {
                pays.forEach((pay, idx) => {
                  houseRows += `<tr class="pay-row"><td></td><td colspan="4">
                    <div class="pay-inner">
                      <span class="ngwd">งวดที่ ${idx+1}</span>
                      <span class="pay-date">${pay.date||"-"}</span>
                      <span class="pay-inv">${pay.inv||"—"}</span>
                      <span class="pay-amt">฿${pay.amount.toLocaleString()}</span>
                      ${pay.notes ? `<span class="pay-note">${pay.notes}</span>` : ""}
                    </div></td></tr>`;
                  rowsPay.push({
                    "โครงการ": p.name, "สัญญา": c.contract_number, "รหัสบ้าน": h.house_code,
                    "งวดที่": idx+1, "วันที่": pay.date||"", "เลขใบกำกับ": pay.inv||"",
                    "ยอด (บาท)": pay.amount, "หมายเหตุ": pay.notes||"",
                  });
                });
              } else {
                houseRows += `<tr class="pay-row"><td></td><td colspan="4"><div class="no-pay">— ยังไม่มีการเบิกจ่าย —</div></td></tr>`;
              }

              rowsH.push({
                "โครงการ": p.name, "สัญญา": c.contract_number, "รหัสบ้าน": h.house_code,
                "ราคา (บาท)": h.price, "เบิกแล้ว (บาท)": h.paid_total,
                "คงเหลือ (บาท)": remain, "จำนวนงวด": pays.length, "หมายเหตุ": h.notes||"",
              });
            }

            contractsHTML += `
              <div class="contract-hd no-break">
                <span class="cnum">${c.contract_number}</span><span class="cdesc">${c.description}</span>
                <div class="cmeta">วันที่ ${c.contract_date||"-"} · มูลค่า ฿${c.value_total.toLocaleString()} · เบิก ฿${c.paid_total.toLocaleString()} · คงเหลือ ฿${(c.value_total-c.paid_total).toLocaleString()} · ${cPct}%</div>
              </div>
              <table class="no-break">
                <thead><tr><th>รหัสบ้าน</th><th class="r">ราคา (บาท)</th><th class="r">เบิกแล้ว (บาท)</th><th class="r">คงเหลือ (บาท)</th><th class="r">งวด</th></tr></thead>
                <tbody>${houseRows}</tbody>
                <tfoot><tr class="tfoot-row">
                  <td class="b">รวม ${houses.length} หลัง</td>
                  <td class="r">${c.value_total.toLocaleString()}</td>
                  <td class="r" style="color:#16a34a">${c.paid_total.toLocaleString()}</td>
                  <td class="r" style="color:#d97706">${(c.value_total-c.paid_total).toLocaleString()}</td>
                  <td class="r">${totalCngwd} งวด</td>
                </tr></tfoot>
              </table>`;

            rowsC.push({
              "โครงการ": p.name, "เลขที่สัญญา": c.contract_number, "รายละเอียด": c.description,
              "วันที่": c.contract_date||"", "มูลค่า (บาท)": c.value_total,
              "เบิกแล้ว (บาท)": c.paid_total, "คงเหลือ (บาท)": c.value_total-c.paid_total,
              "จำนวนบ้าน": houses.length, "งวดทั้งหมด": houses.reduce((s,h)=>(allPayments[h.id]||[]).length+s, 0),
            });
          }

          htmlBody += `
            <div class="project-hd no-break">
              <span class="pname">${p.name}</span>
              <div class="pmeta">${p.client||""} · วันที่เริ่ม ${p.start_date||"-"} · มูลค่า ฿${p.value_total.toLocaleString()} · เบิก ฿${p.paid_total.toLocaleString()} · คงเหลือ ฿${(p.value_total-p.paid_total).toLocaleString()} · ${pPct}%</div>
            </div>
            ${contractsHTML || '<div style="padding:8px 12px;color:#94a3b8;font-size:12px">ยังไม่มีสัญญา</div>'}`;
        }

        excelSheets = [
          { name: "สัญญา", rows: rowsC },
          { name: "บ้านและงวด", rows: rowsH },
          { name: "การเบิกจ่ายทุกงวด", rows: rowsPay },
        ];

      // ── Payment history ──────────────────────────────────
      } else if (type === "payment-history") {
        const all = [];
        Object.entries(allPayments).forEach(([hid, list]) => {
          list.forEach((pay) => {
            let house = null, contract = null, project = null;
            for (const cid of Object.keys(data.houses)) {
              const h = data.houses[cid].find(x => x.id === hid);
              if (h) { house = h;
                for (const pid of Object.keys(data.contracts)) {
                  const c = data.contracts[pid].find(x => x.id === cid);
                  if (c) { contract = c; project = projects.find(pr => pr.id === pid); break; }
                } break;
              }
            }
            all.push({ ...pay, house, contract, project });
          });
        });
        all.sort((a,b) => b.date > a.date ? 1 : -1);
        const total = all.reduce((s,p) => s+p.amount, 0);

        htmlBody = `<div class="stat-row">
          <div class="stat-box"><div class="lbl">รายการทั้งหมด</div><div class="val">${all.length}</div></div>
          <div class="stat-box"><div class="lbl">ยอดรวม (บาท)</div><div class="val" style="color:#16a34a">฿${total.toLocaleString()}</div></div>
        </div>
        <table><thead><tr>
          <th>วันที่</th><th>โครงการ</th><th>สัญญา</th><th>รหัสบ้าน</th><th>เลขใบกำกับ</th><th class="r">ยอด (บาท)</th><th>หมายเหตุ</th>
        </tr></thead><tbody>
        ${all.map(p => `<tr>
          <td class="mono">${p.date||"-"}</td>
          <td>${p.project?.name||"-"}</td>
          <td class="mono b">${p.contract?.contract_number||"-"}</td>
          <td class="mono b">${p.house?.house_code||"-"}</td>
          <td class="mono">${p.inv||"—"}</td>
          <td class="r b" style="color:#16a34a">฿${p.amount.toLocaleString()}</td>
          <td>${p.notes||"—"}</td>
        </tr>`).join("")}
        </tbody><tfoot><tr class="tfoot-row">
          <td colspan="5" class="b">รวมทั้งสิ้น</td>
          <td class="r b" style="font-size:14px;color:#16a34a">฿${total.toLocaleString()}</td>
          <td></td>
        </tr></tfoot></table>`;

        excelSheets = [{ name: "ประวัติเบิกจ่าย", rows: all.map((p,i) => ({
          "ลำดับ": i+1, "วันที่": p.date||"", "โครงการ": p.project?.name||"",
          "สัญญา": p.contract?.contract_number||"", "รหัสบ้าน": p.house?.house_code||"",
          "เลขใบกำกับ": p.inv||"", "ยอด (บาท)": p.amount, "หมายเหตุ": p.notes||"",
        })) }];

      // ── Owing houses ─────────────────────────────────────
      } else if (type === "owing-houses") {
        const owing = [];
        for (const pid of Object.keys(data.contracts)) {
          const project = projects.find(p => p.id === pid);
          for (const c of data.contracts[pid] || []) {
            const sorted = (data.houses[c.id] || [])
              .slice()
              .sort((a,b) => a.house_code.localeCompare(b.house_code, undefined, { numeric: true, sensitivity: "base" }));
            for (const h of sorted) {
              if (h.price - h.paid_total > 0) {
                const pays = allPayments[h.id] || [];
                const lastPay = pays.length > 0 ? pays.reduce((lp,p) => p.date > lp.date ? p : lp, pays[0]) : null;
                owing.push({ ...h, contract: c, project, pays, lastPay });
              }
            }
          }
        }
        const totalRemain = owing.reduce((s,h) => s+(h.price-h.paid_total), 0);

        htmlBody = `<div class="stat-row">
          <div class="stat-box"><div class="lbl">บ้านที่ยังค้างจ่าย</div><div class="val">${owing.length} หลัง</div></div>
          <div class="stat-box"><div class="lbl">ยอดคงเหลือรวม (บาท)</div><div class="val" style="color:#d97706">฿${totalRemain.toLocaleString()}</div></div>
        </div>
        <table><thead><tr>
          <th>โครงการ</th><th>สัญญา</th><th>รหัสบ้าน</th>
          <th class="r">ราคา (บาท)</th><th class="r">เบิกแล้ว (บาท)</th><th class="r">คงเหลือ (บาท)</th>
          <th class="r">งวด</th><th>เบิกครั้งล่าสุด</th><th>หมายเหตุ</th>
        </tr></thead><tbody>
        ${owing.map(h => `<tr>
          <td>${h.project?.name||"-"}</td>
          <td class="mono b">${h.contract?.contract_number||"-"}</td>
          <td class="mono b">${h.house_code}</td>
          <td class="r">${h.price.toLocaleString()}</td>
          <td class="r" style="color:#16a34a">${h.paid_total.toLocaleString()}</td>
          <td class="r b" style="color:#d97706">${(h.price-h.paid_total).toLocaleString()}</td>
          <td class="r">${h.pays.length}</td>
          <td class="mono">${h.lastPay ? `${h.lastPay.date} / ฿${h.lastPay.amount.toLocaleString()}` : "—"}</td>
          <td>${h.notes||"—"}</td>
        </tr>`).join("")}
        </tbody><tfoot><tr class="tfoot-row">
          <td colspan="5" class="b">รวม ${owing.length} หลัง</td>
          <td class="r b" style="color:#d97706;font-size:13px">฿${totalRemain.toLocaleString()}</td>
          <td colspan="3"></td>
        </tr></tfoot></table>`;

        excelSheets = [{ name: "บ้านค้างจ่าย", rows: owing.map(h => ({
          "โครงการ": h.project?.name||"", "สัญญา": h.contract?.contract_number||"",
          "รหัสบ้าน": h.house_code, "ราคา (บาท)": h.price,
          "เบิกแล้ว (บาท)": h.paid_total, "คงเหลือ (บาท)": h.price-h.paid_total,
          "จำนวนงวด": h.pays.length,
          "เบิกล่าสุดวันที่": h.lastPay?.date||"", "ยอดล่าสุด (บาท)": h.lastPay?.amount||0,
          "หมายเหตุ": h.notes||"",
        })) }];
      }

      // Step 4: build layout
      setGenerating(g => ({ ...g, step: 4 }));
      await tick(150);

      // Step 5: generate file
      setGenerating(g => ({ ...g, step: 5 }));
      await tick(100);

      if (format === "xlsx") {
        if (targetWindow && !targetWindow.closed) targetWindow.close();
        exportExcel(excelSheets, name);
        toast({ t: "สร้าง Excel สำเร็จ", s: `${name}.xlsx (${excelSheets.length} sheet)` });
      } else {
        openHTML(buildBaseHTML(name, htmlBody), targetWindow);
        toast({ t: "เปิดรายงานสำเร็จ", s: "เปิดในแท็บใหม่ · กด Ctrl+P เพื่อพิมพ์" });
      }

      setGenerating(null);
    } catch(e) {
      if (targetWindow && !targetWindow.closed) targetWindow.close();
      toast({ t: "เกิดข้อผิดพลาด", s: e.message });
      setGenerating(null);
    }
  };

  const reports = [
    { id: "summary-all",      name: "สรุปทุกโครงการ",      desc: "มูลค่ารวม · ยอดเบิก · คงเหลือ ทุกโครงการ",                               icon: "report" },
    { id: "by-project",       name: "รายงานต่อโครงการ",     desc: "โครงการ → สัญญา → บ้านแต่ละหลัง → รายการเบิกแต่ละงวด",                  icon: "building" },
    { id: "payment-history",  name: "ประวัติการเบิกจ่าย",   desc: "ทุกใบเบิกทุกงวดในระบบ เรียงตามวันที่",                                  icon: "wallet" },
    { id: "owing-houses",     name: "บ้านที่ยังค้างจ่าย",   desc: "บ้านที่ยังไม่ครบยอด พร้อมจำนวนงวดและวันที่เบิกล่าสุด",                  icon: "house" },
  ];

  return (
    <div className="page">
      <div className="page-head">
        <div>
          <h1 className="page-title">รายงาน</h1>
          <p className="page-sub">สร้างรายงาน PDF หรือ Excel — ดึงข้อมูลล่าสุดจาก Server ทุกครั้ง</p>
        </div>
      </div>

      <div style={{ display: "grid", gridTemplateColumns: "repeat(2,1fr)", gap: 14 }}>
        {reports.map((r) => (
          <div className="card" key={r.id}>
            <div className="card-body" style={{ display: "flex", gap: 14, alignItems: "flex-start" }}>
              <div style={{ width: 44, height: 44, borderRadius: 9, background: "var(--brand-50)", color: "var(--brand)", display: "grid", placeItems: "center", flexShrink: 0 }}>
                <Icon name={r.icon} size={20} />
              </div>
              <div style={{ flex: 1 }}>
                <div style={{ fontWeight: 600, fontSize: 14, marginBottom: 2 }}>{r.name}</div>
                <div className="dim" style={{ fontSize: 12.5, marginBottom: 12 }}>{r.desc}</div>
                <div className="hstack" style={{ gap: 6 }}>
                  <button className="btn sm primary" onClick={() => generateReport(r.id, r.name, "pdf")} disabled={!!generating}>
                    <Icon name="print" size={12} /> สร้าง PDF
                  </button>
                  <button className="btn sm" onClick={() => generateReport(r.id, r.name, "xlsx")} disabled={!!generating}>
                    <Icon name="excel" size={12} /> Excel
                  </button>
                </div>
              </div>
            </div>
          </div>
        ))}
      </div>

      {generating && <ReportProgressModal name={generating.name} format={generating.format} step={generating.step} />}
    </div>
  );
}

function ReportProgressModal({ name, format, step }) {
  const steps = [
    "กำลังดึงข้อมูลการเบิกจ่ายทั้งหมดจาก Server...",
    "กำลังรวบรวมข้อมูลสัญญาและบ้าน...",
    "กำลังประมวลผลรายการเบิกจ่ายทุกงวด...",
    "กำลังสร้างเลย์เอาท์รายงาน...",
    `กำลังสร้างไฟล์ ${format === "xlsx" ? "Excel" : "PDF"}...`,
  ];
  const pct = Math.min(100, (step / 5) * 100);
  return (
    <div className="modal-overlay">
      <div className="modal" style={{ maxWidth: 480 }}>
        <div className="modal-head">
          <div className="ico"><Icon name={format === "xlsx" ? "excel" : "print"} size={18} /></div>
          <h2>กำลังสร้างรายงาน</h2>
        </div>
        <div className="modal-body">
          <div style={{ fontSize: 13, color: "var(--text-2)" }}>กำลังสร้าง <b style={{ color: "var(--text)" }}>{name}.{format === "xlsx" ? "xlsx" : "pdf"}</b></div>
          <div className="prog-modal-bar"><div className="prog-modal-fill" style={{ width: pct + "%" }}></div></div>
          <div className="hstack" style={{ justifyContent: "space-between", fontSize: 12, color: "var(--text-2)" }}>
            <span>ความคืบหน้า {Math.round(pct)}%</span>
            <span className="num">ขั้นตอน {Math.min(step + 1, 5)} / 5</span>
          </div>
          <div className="prog-steps">
            {steps.map((s, i) => (
              <div key={i} className={`prog-step ${i < step ? "done" : i === step ? "active" : ""}`}>
                <div className="dot">{i < step ? <Icon name="check" size={9} /> : i === step ? <span className="spinner" style={{ width: 9, height: 9, borderWidth: 1.5 }}></span> : ""}</div>
                <span>{s}</span>
              </div>
            ))}
          </div>
          <div className="dim" style={{ fontSize: 11.5, marginTop: 12, padding: "8px 10px", background: "var(--surface-2)", borderRadius: 6 }}>
            <Icon name="info" size={11} /> ระบบจะทำงานในเบื้องหลัง — คุณสามารถใช้งานหน้าจออื่นต่อไปได้
          </div>
        </div>
      </div>
    </div>
  );
}

// =====================================================
// SETTINGS (basic)
// =====================================================
function SettingsScreen() {
  return (
    <div className="page" style={{ maxWidth: 800 }}>
      <div className="page-head">
        <div>
          <h1 className="page-title">ตั้งค่า</h1>
          <p className="page-sub">ตั้งค่าบัญชี · ทีม · การแจ้งเตือน</p>
        </div>
      </div>
      <div className="card">
        <div className="card-head"><h3>โปรไฟล์</h3></div>
        <div className="card-body vstack" style={{ gap: 12 }}>
          <div className="hstack" style={{ gap: 14 }}>
            <div style={{ width: 60, height: 60, borderRadius: "50%", background: "linear-gradient(135deg,#3B82F6,#2563EB)", display: "grid", placeItems: "center", color: "#fff", fontWeight: 600, fontSize: 22 }}>สช</div>
            <div>
              <div style={{ fontWeight: 600 }}>สมชาย จันทร์ดี</div>
              <div className="dim" style={{ fontSize: 12 }}>somchai@jscontract.co.th</div>
            </div>
            <div style={{ flex: 1 }}></div>
            <button className="btn">เปลี่ยนรูปภาพ</button>
          </div>
          <div className="divider"></div>
          <div className="field"><label>ชื่อ-นามสกุล</label><input className="input" defaultValue="สมชาย จันทร์ดี" /></div>
          <div className="field"><label>อีเมล</label><input className="input" defaultValue="somchai@jscontract.co.th" /></div>
          <div className="field"><label>ตำแหน่ง</label><input className="input" defaultValue="ผู้จัดการโครงการ" /></div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { ContractsScreen, HousesScreen, ReportsScreen, SettingsScreen });
