/* global React, I, UI */
// =============== รายรับรายจ่าย (งบหลังบ้าน) — กรอกเอง + รวมบิลอัตโนมัติ ===============
const { useState: useStateCB, useEffect: useEffectCB, useMemo: useMemoCB } = React;

// ---------- Thai date helpers ----------
const CB_TH_MONTHS = { "ม.ค.": 1, "ก.พ.": 2, "มี.ค.": 3, "เม.ย.": 4, "พ.ค.": 5, "มิ.ย.": 6, "ก.ค.": 7, "ส.ค.": 8, "ก.ย.": 9, "ต.ค.": 10, "พ.ย.": 11, "ธ.ค.": 12 };
const CB_TH_MONTH_NAMES = ["ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค.", "พ.ย.", "ธ.ค."];

function cbThaiToISO(s) {
  // "21 พ.ค. 2569" -> "2026-05-21"
  if (!s) return null;
  const m = /^(\d{1,2})\s+(\S+)\s+(\d{4})$/.exec(String(s).trim());
  if (!m) return null;
  const mon = CB_TH_MONTHS[m[2]];
  if (!mon) return null;
  const y = parseInt(m[3], 10) - 543;
  return `${y}-${String(mon).padStart(2, "0")}-${String(m[1]).padStart(2, "0")}`;
}
function cbISOToThai(iso) {
  if (!iso) return "—";
  const [y, m, d] = iso.split("-").map(Number);
  return `${d} ${CB_TH_MONTH_NAMES[m - 1]} ${y + 543}`;
}
function cbMonthLabel(ym) {
  const [y, m] = ym.split("-").map(Number);
  return `${CB_TH_MONTH_NAMES[m - 1]} ${y + 543}`;
}

// ---------- Storage (manual entries) ----------
const CB_KEY = "sss-cashbook";
function cbLoad() {
  try { return JSON.parse(localStorage.getItem(CB_KEY) || "[]"); } catch { return []; }
}
function cbSave(list) {
  try { localStorage.setItem(CB_KEY, JSON.stringify(list)); } catch {
    window.toast && window.toast("พื้นที่จัดเก็บใกล้เต็ม — หลักฐานบางส่วนอาจไม่ถูกบันทึก");
  }
  window.dispatchEvent(new Event("sss-cashbook-changed"));
}

// ---------- Auto entries from system documents ----------
function buildAutoEntries() {
  const D = window.SSSData;
  const out = [];

  // เลขที่ EX ที่ถูกออกใบสำคัญจ่ายแล้ว (กันนับซ้ำ)
  const pvRefs = new Set();
  (D.PaymentVouchers || []).forEach(pv => String(pv.ref || "").split(/[,\s]+/).forEach(r => r && pvRefs.add(r)));

  (D.Receipts || []).forEach(r => out.push({
    id: "auto-rc-" + r.no, auto: true, kind: "รับ",
    date: cbThaiToISO(r.date), category: "รับชำระจากลูกค้า",
    desc: `${r.customer} · อ้างอิง ${r.ref}`, amount: r.amount, method: r.method,
    source: { label: "ใบเสร็จรับเงิน", no: r.no, go: "receipts" }
  }));

  (D.PaymentVouchers || []).forEach(pv => out.push({
    id: "auto-pv-" + pv.no, auto: true, kind: "จ่าย",
    date: cbThaiToISO(pv.date), category: "ใบสำคัญจ่าย",
    desc: `${pv.payee} · อ้างอิง ${pv.ref}`, amount: pv.amount, method: pv.method,
    source: { label: "ใบสำคัญจ่าย", no: pv.no, go: "payment-vouchers" }
  }));

  (D.Expenses || []).forEach(ex => {
    if (pvRefs.has(ex.no)) return; // จ่ายผ่าน PV แล้ว ไม่นับซ้ำ
    out.push({
      id: "auto-ex-" + ex.no, auto: true, kind: "จ่าย",
      date: cbThaiToISO(ex.date), category: ex.category,
      desc: `${ex.vendor}`, amount: ex.amount, method: "—",
      source: { label: "ค่าใช้จ่าย", no: ex.no, go: "expenses" }
    });
  });

  (D.ReceiptVouchers || []).forEach(rv => {
    if (rv.ref && pvRefs.has(rv.ref)) return; // จ่ายผ่าน PV แล้ว
    out.push({
      id: "auto-rv-" + rv.no, auto: true, kind: "จ่าย",
      date: cbThaiToISO(rv.date), category: "จ่ายบุคคล (ใบสำคัญรับเงิน)",
      desc: `${rv.payee} · ${rv.purpose}`, amount: rv.amount - (rv.wht || 0), method: rv.method,
      source: { label: "ใบสำคัญรับเงิน", no: rv.no, go: "receipt-vouchers" }
    });
  });

  return out.filter(e => e.date);
}

const CB_CATS_IN = ["ขายสินค้า/บริการ (เงินสด)", "รับชำระจากลูกค้า", "รับคืนเงิน/เคลม", "ดอกเบี้ยรับ", "รายรับอื่น ๆ"];
const CB_CATS_OUT = ["ซื้อวัตถุดิบ/ของเข้าโรงงาน", "ค่าแรง/ค่าจ้างรายวัน", "ค่าน้ำมัน/ขนส่ง", "ค่าน้ำ/ค่าไฟ/โทรศัพท์", "ค่าเช่า", "ค่าอาหาร/รับรอง", "อุปกรณ์/ซ่อมบำรุง", "รายจ่ายอื่น ๆ"];
// บัญชีบริษัท (ดึงจากหน้าบัญชีธนาคาร) — ใช้เลือกว่ารับ/จ่ายผ่านบัญชีไหน
function cbAccounts() { return (window.CompanyCashStore && window.CompanyCashStore.ACCOUNTS) || [{ id: "CASH", name: "เงินสดบริษัท", short: "เงินสด", emoji: "💵" }]; }
function cbAcc(id) { return cbAccounts().find(a => a.id === id) || cbAccounts()[0]; }

// ---------- Entry modal ----------
function CBEntryModal({ initial, onClose, onSave }) {
  const { Btn } = window.UI;
  const S = window.DeliveryStore;
  const [f, setF] = useStateCB(initial || {
    kind: "รับ", date: S.todayStr(), category: CB_CATS_IN[0],
    desc: "", amount: "", accountId: "CASH", attachments: []
  });
  const upd = (k, v) => setF(p => ({ ...p, [k]: v }));
  const setKind = (kind) => setF(p => ({ ...p, kind, category: kind === "รับ" ? CB_CATS_IN[0] : CB_CATS_OUT[0] }));
  const cats = f.kind === "รับ" ? CB_CATS_IN : CB_CATS_OUT;

  const save = () => {
    const amount = Number(f.amount);
    if (!amount || amount <= 0) { window.toast && window.toast("กรอกจำนวนเงินให้ถูกต้อง"); return; }
    if (!f.desc.trim()) { window.toast && window.toast("กรอกรายละเอียดรายการ"); return; }
    onSave({ ...f, amount, desc: f.desc.trim(), method: cbAcc(f.accountId).name });
    onClose();
  };

  return (
    <div className="scrim" style={{display: "flex", alignItems: "center", justifyContent: "center", padding: 18, zIndex: 220}} onClick={onClose}>
      <div style={{background: "var(--surface)", borderRadius: 14, width: 560, maxWidth: "96vw", maxHeight: "94vh", display: "flex", flexDirection: "column", overflow: "hidden"}} onClick={e => e.stopPropagation()}>
        <div style={{padding: "16px 20px 12px", borderBottom: "1px solid var(--line)", display: "flex", alignItems: "center"}}>
          <div style={{flex: 1}}>
            <div style={{fontSize: 15, fontWeight: 700}}>{initial ? "แก้ไขรายการ" : "เพิ่มรายการรับ-จ่าย"}</div>
            <div style={{fontSize: 12, color: "var(--ink-3)"}}>งบหลังบ้าน · แนบหลักฐานได้ (สลิป, บิล, รูปถ่าย)</div>
          </div>
          <button className="icon-btn" onClick={onClose}><I.close size={14}/></button>
        </div>

        <div style={{padding: "14px 20px", overflow: "auto", display: "flex", flexDirection: "column", gap: 12}}>
          <div style={{display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8}}>
            <button className="btn" onClick={() => setKind("รับ")} style={f.kind === "รับ" ? {background: "var(--success)", color: "white", borderColor: "var(--success)", fontWeight: 600} : {}}>
              <I.arrowDown size={14}/> รายรับ
            </button>
            <button className="btn" onClick={() => setKind("จ่าย")} style={f.kind === "จ่าย" ? {background: "var(--danger)", color: "white", borderColor: "var(--danger)", fontWeight: 600} : {}}>
              <I.arrowUp size={14}/> รายจ่าย
            </button>
          </div>

          <div className="field-row cols-2">
            <div className="field"><label>วันที่</label><input className="input" type="date" value={f.date} onChange={e => upd("date", e.target.value)}></input></div>
            <div className="field"><label>จำนวนเงิน (บาท)</label><input className="input" type="number" min="0" placeholder="0.00" value={f.amount} onChange={e => upd("amount", e.target.value)} style={{fontSize: 16, fontWeight: 600}}></input></div>
          </div>

          <div className="field-row cols-2">
            <div className="field"><label>หมวดหมู่</label>
              <select className="input" value={f.category} onChange={e => upd("category", e.target.value)}>
                {cats.map(c => <option key={c}>{c}</option>)}
              </select>
            </div>
            <div className="field"><label>{f.kind === "รับ" ? "รับเงินเข้าบัญชี" : "จ่ายจากบัญชี"}</label>
              <select className="input" value={f.accountId} onChange={e => upd("accountId", e.target.value)}>
                {cbAccounts().map(a => <option key={a.id} value={a.id}>{a.emoji} {a.name}</option>)}
              </select>
            </div>
          </div>

          <div className="field"><label>รายละเอียด</label>
            <input className="input" value={f.desc} onChange={e => upd("desc", e.target.value)} placeholder={f.kind === "รับ" ? "เช่น ขายเศษสแตนเลสหน้าโรงงาน" : "เช่น ซื้อใบตัดร้านวี.ที. (ไม่มีบิล VAT)"}></input>
          </div>

          <window.DeliveryPhotoStrip label="แนบหลักฐาน (สลิปโอน / บิล / รูปถ่าย)" photos={f.attachments} onChange={(v) => upd("attachments", v)} hint="แนบได้หลายรูป ระบบย่อขนาดให้อัตโนมัติ"/>
        </div>

        <div style={{padding: "12px 20px", borderTop: "1px solid var(--line)", background: "var(--surface-2)", display: "flex", gap: 8, justifyContent: "flex-end"}}>
          <Btn kind="ghost" onClick={onClose}>ยกเลิก</Btn>
          <Btn kind="primary" icon={I.check} onClick={save}>{initial ? "บันทึกการแก้ไข" : "บันทึกรายการ"}</Btn>
        </div>
      </div>
    </div>
  );
}

// ---------- Main page ----------
function CashbookPage({ navigate }) {
  const { Btn, Badge, Stat, PageHead, Tabs, fmt0 } = window.UI;
  const [manual, setManual] = useStateCB(() => cbLoad());
  const [tab, setTab] = useStateCB("all");
  const [month, setMonth] = useStateCB("2026-05");
  const [showNew, setShowNew] = useStateCB(false);
  const [editing, setEditing] = useStateCB(null);
  const [viewer, setViewer] = useStateCB(null);

  useEffectCB(() => {
    const h = () => setManual(cbLoad());
    window.addEventListener("sss-cashbook-changed", h);
    return () => window.removeEventListener("sss-cashbook-changed", h);
  }, []);

  const auto = useMemoCB(() => buildAutoEntries(), []);
  const all = useMemoCB(() => {
    const m = manual.map(e => ({ ...e, auto: false }));
    return [...auto, ...m].sort((a, b) => (b.date || "").localeCompare(a.date || ""));
  }, [auto, manual]);

  const months = useMemoCB(() => {
    const s = new Set(all.map(e => (e.date || "").slice(0, 7)).filter(Boolean));
    return [...s].sort().reverse();
  }, [all]);

  const inMonth = all.filter(e => month === "all" || (e.date || "").startsWith(month));
  const filtered = inMonth.filter(e => tab === "all" || e.kind === (tab === "in" ? "รับ" : "จ่าย"));

  const totalIn = inMonth.filter(e => e.kind === "รับ").reduce((s, e) => s + e.amount, 0);
  const totalOut = inMonth.filter(e => e.kind === "จ่าย").reduce((s, e) => s + e.amount, 0);
  const autoCount = inMonth.filter(e => e.auto).length;

  const addEntry = (f) => {
    const accId = f.accountId || "CASH";
    let movementId = null;
    if (window.CompanyCashStore && window.CompanyCashStore.addMovement) {
      movementId = window.CompanyCashStore.addMovement({
        accountId: accId, direction: f.kind === "รับ" ? "in" : "out",
        amount: f.amount, desc: `${f.kind === "รับ" ? "รับ" : "จ่าย"} — ${f.desc} (${f.category})`, source: "รายรับรายจ่าย"
      });
    }
    const rec = { ...f, accountId: accId, movementId, id: "cb-" + Date.now(), by: window.SSSData.Company.currentUser.name };
    const next = [...manual, rec];
    setManual(next); cbSave(next);
    window.logActivity && window.logActivity(`บันทึก${f.kind === "รับ" ? "รายรับ" : "รายจ่าย"}`, `${f.desc} · ฿${fmt0(f.amount)} · ${cbAcc(accId).short}`, "cashbook");
    window.toast && window.toast(`บันทึกรายการแล้ว — ${f.kind === "รับ" ? "รับเข้า" : "จ่ายจาก"}${cbAcc(accId).name}`);
  };
  const updateEntry = (id, f) => {
    const old = manual.find(e => e.id === id);
    if (old && old.movementId && window.CompanyCashStore) window.CompanyCashStore.removeMovement(old.movementId);
    const accId = f.accountId || "CASH";
    let movementId = null;
    if (window.CompanyCashStore && window.CompanyCashStore.addMovement) {
      movementId = window.CompanyCashStore.addMovement({
        accountId: accId, direction: f.kind === "รับ" ? "in" : "out",
        amount: f.amount, desc: `${f.kind === "รับ" ? "รับ" : "จ่าย"} — ${f.desc} (${f.category})`, source: "รายรับรายจ่าย"
      });
    }
    const next = manual.map(e => e.id === id ? { ...e, ...f, accountId: accId, movementId } : e);
    setManual(next); cbSave(next);
    window.toast && window.toast("แก้ไขรายการแล้ว");
  };
  const removeEntry = async (e) => {
    const ok = await (window.confirmDelete ? window.confirmDelete(`รายการ "${e.desc}"`, `฿${fmt0(e.amount)}`) : Promise.resolve(confirm("ลบ?")));
    if (!ok) return;
    if (e.movementId && window.CompanyCashStore) window.CompanyCashStore.removeMovement(e.movementId);
    const next = manual.filter(x => x.id !== e.id);
    setManual(next); cbSave(next);
  };

  const exportCSV = () => {
    const rows = filtered.map(e => ({
      date: cbISOToThai(e.date), kind: e.kind, category: e.category, desc: e.desc,
      income: e.kind === "รับ" ? e.amount : "", expense: e.kind === "จ่าย" ? e.amount : "",
      method: e.method || "—",
      source: e.auto ? `${e.source.label} ${e.source.no}` : `กรอกเอง${e.by ? " · " + e.by : ""}`,
      proof: e.auto ? "ดูที่เอกสารต้นทาง" : `${(e.attachments || []).length} ไฟล์`
    }));
    window.exportRowsCSV("สรุปรายรับรายจ่าย", [
      { key: "date", label: "วันที่" }, { key: "kind", label: "ประเภท" }, { key: "category", label: "หมวดหมู่" },
      { key: "desc", label: "รายละเอียด" }, { key: "income", label: "รายรับ (บาท)" }, { key: "expense", label: "รายจ่าย (บาท)" },
      { key: "method", label: "ช่องทาง" }, { key: "source", label: "ที่มา" }, { key: "proof", label: "หลักฐาน" }
    ], rows);
  };

  // group by date
  const groups = useMemoCB(() => {
    const m = {};
    filtered.forEach(e => { (m[e.date] = m[e.date] || []).push(e); });
    return Object.keys(m).sort().reverse().map(date => ({ date, rows: m[date] }));
  }, [filtered]);

  return (
    <>
      <PageHead
        title="รายรับรายจ่าย"
        sub="งบหลังบ้าน · บิลในระบบ (ใบเสร็จ, ใบสำคัญจ่าย, ค่าใช้จ่าย) ถูกรวมให้อัตโนมัติ + กรอกเองได้"
        right={<>
          <Btn icon={I.download} kind="ghost" onClick={exportCSV}>ส่งออกสรุป (Excel)</Btn>
          <Btn icon={I.plus} kind="primary" onClick={() => setShowNew(true)}>เพิ่มรายการ</Btn>
        </>}
      />

      <div style={{display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(170px, 1fr))", gap: 12, marginBottom: 16}}>
        <Stat label={`รายรับ · ${month === "all" ? "ทั้งหมด" : cbMonthLabel(month)}`} value={`฿${fmt0(totalIn)}`} deltaDir="up" delta={`${inMonth.filter(e => e.kind === "รับ").length} รายการ`} icon={I.arrowDown}/>
        <Stat label={`รายจ่าย · ${month === "all" ? "ทั้งหมด" : cbMonthLabel(month)}`} value={`฿${fmt0(totalOut)}`} deltaDir="down" delta={`${inMonth.filter(e => e.kind === "จ่าย").length} รายการ`} icon={I.arrowUp}/>
        <Stat label="คงเหลือสุทธิ" value={`${totalIn - totalOut < 0 ? "−" : ""}฿${fmt0(Math.abs(totalIn - totalOut))}`} sub={totalIn - totalOut >= 0 ? "รับมากกว่าจ่าย" : "จ่ายมากกว่ารับ"} icon={I.money}/>
        <Stat label="รวมจากบิลอัตโนมัติ" value={autoCount} sub="ใบเสร็จ · ใบสำคัญจ่าย · ค่าใช้จ่าย · ใบสำคัญรับเงิน" icon={I.sparkle}/>
      </div>

      <div style={{display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap"}}>
        <Tabs items={[
          { key: "all", label: "ทั้งหมด", count: inMonth.length },
          { key: "in", label: "รายรับ", count: inMonth.filter(e => e.kind === "รับ").length },
          { key: "out", label: "รายจ่าย", count: inMonth.filter(e => e.kind === "จ่าย").length }
        ]} active={tab} onChange={setTab}/>
        <div style={{flex: 1}}></div>
        <select className="input" style={{width: 150, height: 30, fontSize: 12.5}} value={month} onChange={e => setMonth(e.target.value)}>
          {months.map(m => <option key={m} value={m}>{cbMonthLabel(m)}</option>)}
          <option value="all">ทุกเดือน</option>
        </select>
      </div>

      <div style={{marginTop: 14, display: "flex", flexDirection: "column", gap: 16}}>
        {groups.length === 0 && (
          <div style={{padding: 40, textAlign: "center", color: "var(--ink-3)", fontSize: 13, border: "1px dashed var(--line)", borderRadius: 10}}>
            ไม่มีรายการในช่วงที่เลือก — กด "เพิ่มรายการ" เพื่อบันทึกรับ-จ่ายของวันนี้
          </div>
        )}
        {groups.map(g => {
          const dIn = g.rows.filter(e => e.kind === "รับ").reduce((s, e) => s + e.amount, 0);
          const dOut = g.rows.filter(e => e.kind === "จ่าย").reduce((s, e) => s + e.amount, 0);
          return (
            <div key={g.date}>
              <div style={{display: "flex", alignItems: "center", gap: 10, marginBottom: 8, flexWrap: "wrap"}}>
                <div style={{fontSize: 13, fontWeight: 700}}>{cbISOToThai(g.date)}{g.date === window.DeliveryStore.todayStr() ? " (วันนี้)" : ""}</div>
                <span style={{fontSize: 11.5, color: "var(--success)", fontWeight: 600}}>รับ ฿{fmt0(dIn)}</span>
                <span style={{fontSize: 11.5, color: "var(--danger)", fontWeight: 600}}>จ่าย ฿{fmt0(dOut)}</span>
                <span style={{fontSize: 11.5, color: "var(--ink-3)"}}>สุทธิ {dIn - dOut < 0 ? "−" : "+"}฿{fmt0(Math.abs(dIn - dOut))}</span>
                <div style={{flex: 1, height: 1, background: "var(--line)"}}></div>
              </div>
              <div style={{display: "flex", flexDirection: "column", gap: 6}}>
                {g.rows.map(e => (
                  <div key={e.id} style={{display: "flex", gap: 12, alignItems: "center", padding: "9px 12px", border: "1px solid var(--line)", borderRadius: 8, background: "var(--surface)", borderLeft: `4px solid ${e.kind === "รับ" ? "var(--success)" : "var(--danger)"}`, flexWrap: "wrap"}}>
                    <Badge tone={e.kind === "รับ" ? "success" : "danger"}>{e.kind}</Badge>
                    <div style={{flex: 1, minWidth: 200}}>
                      <div style={{fontSize: 13, fontWeight: 600}}>{e.desc}</div>
                      <div style={{fontSize: 11, color: "var(--ink-3)", marginTop: 1}}>{e.category} · {e.auto ? (e.method || "—") : `${cbAcc(e.accountId || "CASH").emoji} ${cbAcc(e.accountId || "CASH").name}`}</div>
                    </div>
                    {(e.attachments || []).length > 0 && (
                      <div style={{display: "flex", gap: 3}}>
                        {e.attachments.slice(0, 3).map((p, i) => (
                          <img key={i} src={p.url} alt="" onClick={() => setViewer(p.url)} style={{width: 30, height: 30, objectFit: "cover", borderRadius: 4, border: "1px solid var(--line)", cursor: "zoom-in"}}/>
                        ))}
                        {e.attachments.length > 3 && <span style={{fontSize: 10, color: "var(--ink-3)", alignSelf: "center"}}>+{e.attachments.length - 3}</span>}
                      </div>
                    )}
                    {e.auto
                      ? <span className="badge outline" style={{fontSize: 10, cursor: "pointer"}} title="เปิดเอกสารต้นทาง" onClick={() => navigate && navigate(e.source.go)}><I.sparkle size={10}/> {e.source.label} · <span className="mono">{e.source.no}</span></span>
                      : <span className="badge" style={{fontSize: 10}}>กรอกเอง</span>}
                    <div style={{fontSize: 15, fontWeight: 700, minWidth: 110, textAlign: "right", color: e.kind === "รับ" ? "var(--success)" : "var(--danger)"}}>
                      {e.kind === "รับ" ? "+" : "−"}฿{fmt0(e.amount)}
                    </div>
                    <div style={{display: "flex", gap: 4, width: 58, justifyContent: "flex-end"}}>
                      {!e.auto && <button className="icon-btn" title="แก้ไข" onClick={() => setEditing(e)}><I.edit size={13}/></button>}
                      {!e.auto && <button className="icon-btn" title="ลบ" onClick={() => removeEntry(e)}><I.trash size={13}/></button>}
                    </div>
                  </div>
                ))}
              </div>
            </div>
          );
        })}
      </div>

      {showNew && <CBEntryModal onClose={() => setShowNew(false)} onSave={addEntry}/>}
      {editing && <CBEntryModal initial={editing} onClose={() => setEditing(null)} onSave={(f) => updateEntry(editing.id, f)}/>}

      {viewer && (
        <div onClick={() => setViewer(null)} style={{position: "fixed", inset: 0, zIndex: 300, background: "rgba(0,0,0,0.8)", display: "flex", alignItems: "center", justifyContent: "center", padding: 30, cursor: "zoom-out"}}>
          <img src={viewer} alt="preview" style={{maxWidth: "92%", maxHeight: "92%", borderRadius: 8, background: "white"}}/>
        </div>
      )}
    </>
  );
}

window.CashbookPage = CashbookPage;
