/* global React, Icon */
const {
  useState: useCfSt, useEffect: useCfEf, useMemo: useCfMm,
  useRef: useCfRf, useCallback: useCfCb,
} = React;

// ─── Constants ───────────────────────────────────────────────
const THAI_MONTHS_CF = [
  "มกราคม","กุมภาพันธ์","มีนาคม","เมษายน","พฤษภาคม","มิถุนายน",
  "กรกฎาคม","สิงหาคม","กันยายน","ตุลาคม","พฤศจิกายน","ธันวาคม",
];

// ─── Helpers ─────────────────────────────────────────────────
function toBE(ce)  { return ce + 543; }
function toCE(be)  { return be - 543; }

function getCurrentYmCF() {
  const n = new Date();
  return `${toBE(n.getFullYear())}-${String(n.getMonth()+1).padStart(2,"0")}`;
}
function ymLabel(ym) {
  if (!ym) return "";
  const [y, m] = ym.split("-");
  return `${THAI_MONTHS_CF[parseInt(m)-1]} ${y}`;
}
function ymStep(ym, delta) {
  let [y, m] = ym.split("-").map(Number);
  m += delta;
  if (m < 1)  { m = 12; y--; }
  if (m > 12) { m = 1;  y++; }
  return `${y}-${String(m).padStart(2,"0")}`;
}

function fmtN(v) {
  const n = parseFloat(v) || 0;
  return n.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
function parseN(s) {
  return parseFloat(String(s || 0).replace(/,/g,"")) || 0;
}

// ─── API ─────────────────────────────────────────────────────
const CF_API = {
  async get(url) {
    const r = await fetch(url);
    if (!r.ok) throw new Error(await r.text());
    return r.json();
  },
  async post(url, body) {
    const r = await fetch(url, {
      method: "POST", headers: { "Content-Type": "application/json" },
      body: JSON.stringify(body),
    });
    if (!r.ok) throw new Error(await r.text());
    return r.json();
  },
  async put(url, body) {
    const r = await fetch(url, {
      method: "PUT", headers: { "Content-Type": "application/json" },
      body: JSON.stringify(body),
    });
    if (!r.ok) throw new Error(await r.text());
    return r.json();
  },
  async del(url) {
    const r = await fetch(url, { method: "DELETE" });
    if (!r.ok) throw new Error(await r.text());
    return r.json();
  },
};

// ─── Toast ───────────────────────────────────────────────────
function CfToast({ msg }) {
  if (!msg) return null;
  return (
    <div style={{
      position: "fixed", bottom: 28, right: 24, zIndex: 9999,
      background: "var(--accent)", color: "#fff",
      padding: "8px 20px", borderRadius: 10, fontWeight: 600,
      fontSize: "0.85rem", boxShadow: "0 4px 20px rgba(0,0,0,0.18)",
      pointerEvents: "none",
    }}>{msg}</div>
  );
}

// ─── Settings Modal ───────────────────────────────────────────
function CfSettingsModal({ open, onClose, onSave, initial }) {
  const blank = { owner_name: "", id_card: "", business_name: "", tax_id: "" };
  const [form, setForm] = useCfSt(blank);
  const [saving, setSaving] = useCfSt(false);

  useCfEf(() => {
    if (open) setForm(initial && initial.owner_name ? initial : blank);
  }, [open]);

  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const handleSave = async () => {
    setSaving(true);
    try { await onSave(form); onClose(); }
    catch(e) { alert("บันทึกไม่ได้: " + e.message); }
    finally { setSaving(false); }
  };

  if (!open) return null;
  const Field = ({ label, k, placeholder }) => (
    <div style={{ marginBottom: 14 }}>
      <label style={{ display: "block", fontSize: "0.82rem", fontWeight: 600, color: "var(--ink-2)", marginBottom: 4 }}>{label}</label>
      <input className="field" value={form[k] || ""} placeholder={placeholder || ""}
        onChange={e => set(k, e.target.value)}
        style={{ width: "100%", boxSizing: "border-box" }}/>
    </div>
  );

  return (
    <div style={{ position: "fixed", inset: 0, zIndex: 1000, background: "rgba(0,0,0,0.35)", display: "flex", alignItems: "center", justifyContent: "center" }}
      onClick={e => e.target === e.currentTarget && onClose()}>
      <div style={{ background: "var(--surface)", borderRadius: 16, padding: 28, width: 380, maxWidth: "calc(100vw - 32px)", boxShadow: "0 8px 40px rgba(0,0,0,0.18)" }}>
        <div style={{ fontWeight: 700, fontSize: "1rem", marginBottom: 20, display: "flex", alignItems: "center", gap: 8 }}>
          <Icon name="settings" size={18}/> ข้อมูลกิจการ
        </div>
        <Field label="ชื่อผู้ประกอบการ" k="owner_name" placeholder="ชื่อ นามสกุล"/>
        <Field label="เลขบัตรประชาชน" k="id_card" placeholder="0-0000-00000-00-0"/>
        <Field label="ชื่อกิจการ / ร้านค้า" k="business_name" placeholder="ชื่อกิจการ"/>
        <Field label="เลขประจำตัวผู้เสียภาษี" k="tax_id" placeholder="0-0000-00000-00-0"/>
        <div style={{ display: "flex", gap: 10, justifyContent: "flex-end", marginTop: 8 }}>
          <button className="btn" onClick={onClose}>ยกเลิก</button>
          <button className="btn primary" onClick={handleSave} disabled={saving}>
            {saving ? "กำลังบันทึก..." : "บันทึก"}
          </button>
        </div>
      </div>
    </div>
  );
}

// ─── Multi-Month Export Modal ─────────────────────────────────
function CfMultiExportModal({ open, onClose, months, onExportPDF, onExportExcel }) {
  const [selected, setSelected] = useCfSt([]);
  const [loading, setLoading] = useCfSt(""); // "pdf" | "excel" | ""

  useCfEf(() => { if (open) setSelected([]); }, [open]);

  const toggle = (ym) => setSelected(s => s.includes(ym) ? s.filter(x => x !== ym) : [...s, ym]);

  const handleExport = async (type) => {
    if (!selected.length) return;
    setLoading(type);
    try {
      const list = [...selected].sort();
      if (type === "excel") await onExportExcel(list);
      else                  await onExportPDF(list);
      onClose();
    }
    catch(e) { alert("Export ไม่ได้: " + e.message); }
    finally { setLoading(""); }
  };

  if (!open) return null;
  const sorted = [...months].sort();
  const busy = !!loading;
  const n = selected.length;
  return (
    <div style={{ position: "fixed", inset: 0, zIndex: 1000, background: "rgba(0,0,0,0.35)", display: "flex", alignItems: "center", justifyContent: "center" }}
      onClick={e => e.target === e.currentTarget && onClose()}>
      <div style={{ background: "var(--surface)", borderRadius: 16, padding: 28, width: 360, maxWidth: "calc(100vw - 32px)", boxShadow: "0 8px 40px rgba(0,0,0,0.18)" }}>
        <div style={{ fontWeight: 700, fontSize: "1rem", marginBottom: 16, display: "flex", alignItems: "center", gap: 8 }}>
          <Icon name="download" size={18}/> Export หลายเดือน
        </div>
        {sorted.length === 0 && (
          <div style={{ color: "var(--ink-3)", fontSize: "0.9rem", textAlign: "center", padding: "20px 0" }}>ยังไม่มีข้อมูล</div>
        )}
        <div style={{ maxHeight: 280, overflowY: "auto", display: "flex", flexDirection: "column", gap: 6 }}>
          {sorted.map(ym => (
            <label key={ym} style={{ display: "flex", alignItems: "center", gap: 10, padding: "6px 10px", borderRadius: 8, cursor: "pointer", background: selected.includes(ym) ? "var(--accent-soft, rgba(37,99,235,0.08))" : "transparent" }}>
              <input type="checkbox" checked={selected.includes(ym)} onChange={() => toggle(ym)}/>
              <span style={{ fontSize: "0.9rem" }}>{ymLabel(ym)}</span>
            </label>
          ))}
        </div>
        <div style={{ display: "flex", gap: 8, justifyContent: "flex-end", marginTop: 16, flexWrap: "wrap" }}>
          <button className="btn" onClick={onClose} disabled={busy}>ยกเลิก</button>
          <button className="btn" style={{ color: "#16a34a", borderColor: "#16a34a", display: "flex", alignItems: "center", gap: 6 }}
            onClick={() => handleExport("excel")} disabled={busy || !n}>
            {loading === "excel" ? "กำลัง Export..." : <><Icon name="doc" size={14}/>Excel {n > 0 ? `${n} เดือน` : ""}</>}
          </button>
          <button className="btn primary" style={{ display: "flex", alignItems: "center", gap: 6 }}
            onClick={() => handleExport("pdf")} disabled={busy || !n}>
            {loading === "pdf" ? "กำลัง Export..." : <><Icon name="download" size={14}/>PDF {n > 0 ? `${n} เดือน` : ""}</>}
          </button>
        </div>
      </div>
    </div>
  );
}

// ─── Canvas-based PDF Export (ไม่ใช้ html2canvas / window.print) ──────────────

const ROWS_PER_PAGE = 40;

const CF_FONT = "'Noto Sans Thai','IBM Plex Sans Thai',sans-serif";

// column: label, w(px), ha=header-align, da=data-align
const CF_COLS = [
  { label: "ลำดับ",                w: 28,  ha: "center", da: "center" },
  { label: "วัน/เดือน/ปี",         w: 66,  ha: "center", da: "left"   },
  { label: "รายการ",               w: 280, ha: "center", da: "left"   },
  { label: "รายรับ",               w: 86,  ha: "center", da: "right",  sub: "(บาท)" },
  { label: "ซื้อสินค้า",           w: 86,  ha: "center", da: "right",  sub: "(บาท)" },
  { label: "ค่าใช้จ่ายอื่นๆ",     w: 90,  ha: "center", da: "right",  sub: "(บาท)" },
  { label: "หมายเหตุ",             w: 70,  ha: "center", da: "left"   },
];

function cfTrunc(ctx, text, maxW) {
  if (!text) return "";
  if (ctx.measureText(text).width <= maxW) return text;
  let t = text;
  while (t.length > 0 && ctx.measureText(t + "…").width > maxW) t = t.slice(0, -1);
  return t + "…";
}

async function drawCfPageToCanvas(settings, ym, rows, pageIndex, totalPages, totals) {
  const PW = 794, PH = 1122; // A4 @96 dpi
  const SCALE = 2;            // @2x for crisp output
  const canvas = document.createElement("canvas");
  canvas.width  = PW * SCALE;
  canvas.height = PH * SCALE;
  const ctx = canvas.getContext("2d");
  ctx.scale(SCALE, SCALE);

  const ML = 44, MR = 44, MT = 36;
  const CW = PW - ML - MR; // 706 px

  // ── Background ──
  ctx.fillStyle = "#fff";
  ctx.fillRect(0, 0, PW, PH);

  // ── Page number ──
  ctx.fillStyle = "#888";
  ctx.font = `10px ${CF_FONT}`;
  ctx.textAlign = "right";
  ctx.fillText(`หน้า ${pageIndex + 1} / ${totalPages}`, PW - MR, MT - 8);

  const s = settings || {};
  let y = MT;

  // ── Header ──
  if (pageIndex === 0) {
    ctx.fillStyle = "#111";
    ctx.font = `bold 17px ${CF_FONT}`;
    ctx.textAlign = "left";
    ctx.fillText("สมุดรายรับ-รายจ่าย", ML, y + 16);
    y += 22;

    ctx.fillStyle = "#555";
    ctx.font = `12px ${CF_FONT}`;
    ctx.fillText(`ประจำเดือน ${ymLabel(ym)}`, ML, y + 12);
    y += 20;

    // 2-column info
    const col2X = ML + CW / 2 + 14;
    ctx.fillStyle = "#111";
    ctx.font = `10.5px ${CF_FONT}`;
    ctx.fillText(`ชื่อผู้ประกอบการ: ${s.owner_name || "-"}`, ML, y + 11);
    ctx.fillText(`เลขบัตรประชาชน: ${s.id_card || "-"}`, col2X, y + 11);
    y += 15;
    ctx.fillText(`ชื่อกิจการ: ${s.business_name || "-"}`, ML, y + 11);
    ctx.fillText(`เลขประจำตัวผู้เสียภาษี: ${s.tax_id || "-"}`, col2X, y + 11);
    y += 18;
  } else {
    ctx.fillStyle = "#111";
    ctx.font = `bold 13px ${CF_FONT}`;
    ctx.textAlign = "left";
    ctx.fillText("สมุดรายรับ-รายจ่าย", ML, y + 13);
    ctx.fillStyle = "#555";
    ctx.font = `11px ${CF_FONT}`;
    ctx.textAlign = "right";
    ctx.fillText(`ประจำเดือน ${ymLabel(ym)}`, PW - MR, y + 13);
    y += 17;
    ctx.strokeStyle = "#ccc";
    ctx.lineWidth = 0.75;
    ctx.beginPath(); ctx.moveTo(ML, y); ctx.lineTo(PW - MR, y); ctx.stroke();
    y += 9;
  }

  // ── Column x offsets ──
  let cx = ML;
  const colX = CF_COLS.map(c => { const x = cx; cx += c.w; return x; });

  const TH_H = 30; // header row height (2-line labels)
  const TR_H = 20; // data row height
  const PAD  = 3;

  // ── Table header ──
  ctx.fillStyle = "#eef1fb";
  ctx.fillRect(ML, y, CW, TH_H);
  ctx.strokeStyle = "#c8d0e0";
  ctx.lineWidth = 0.75;

  for (let ci = 0; ci < CF_COLS.length; ci++) {
    const col = CF_COLS[ci];
    const x = colX[ci];
    ctx.strokeRect(x, y, col.w, TH_H);
    ctx.fillStyle = "#111";
    ctx.font = `bold 9px ${CF_FONT}`;
    ctx.textAlign = "center";
    if (col.sub) {
      // 2-line: label on top, "(บาท)" on bottom
      ctx.fillText(col.label, x + col.w / 2, y + TH_H / 2 - 1, col.w - PAD * 2);
      ctx.font = `8px ${CF_FONT}`;
      ctx.fillText(col.sub,   x + col.w / 2, y + TH_H / 2 + 10, col.w - PAD * 2);
    } else {
      ctx.fillText(col.label, x + col.w / 2, y + TH_H / 2 + 3.5, col.w - PAD * 2);
    }
  }
  y += TH_H;

  // ── Data rows ──
  const startNo = pageIndex * ROWS_PER_PAGE;
  ctx.strokeStyle = "#d4d8e8";
  ctx.lineWidth = 0.5;

  for (let ri = 0; ri < rows.length; ri++) {
    const e = rows[ri];
    const cells = [
      String(startNo + ri + 1),
      e.entry_date  || "",
      e.description || "",
      parseN(e.income)        ? fmtN(e.income)        : "",
      parseN(e.purchase)      ? fmtN(e.purchase)      : "",
      parseN(e.other_expense) ? fmtN(e.other_expense) : "",
      e.note || "",
    ];

    ctx.fillStyle = "#111";
    ctx.font = `10px ${CF_FONT}`;

    for (let ci = 0; ci < CF_COLS.length; ci++) {
      const col = CF_COLS[ci];
      const x = colX[ci];
      ctx.strokeRect(x, y, col.w, TR_H);
      const text = cfTrunc(ctx, cells[ci], col.w - PAD * 2);
      ctx.textAlign = col.da;
      const tx = col.da === "right"  ? x + col.w - PAD
               : col.da === "center" ? x + col.w / 2
               : x + PAD;
      ctx.fillText(text, tx, y + TR_H / 2 + 3.5);
    }
    y += TR_H;
  }

  // ── Total row + summary (last page only) ──
  if (totals) {
    const TTOT_H = 22;
    const totalCells  = ["", "", "รวมทั้งสิ้น",
      fmtN(totals.income), fmtN(totals.purchase), fmtN(totals.other_expense), ""];
    const totalAligns = ["center","left","right","right","right","right","left"];

    ctx.fillStyle = "#f4f6fb";
    ctx.fillRect(ML, y, CW, TTOT_H);
    ctx.strokeStyle = "#c8d0e0";
    ctx.lineWidth = 0.75;

    for (let ci = 0; ci < CF_COLS.length; ci++) {
      const col = CF_COLS[ci];
      const x = colX[ci];
      ctx.strokeRect(x, y, col.w, TTOT_H);
      ctx.fillStyle = "#111";
      ctx.font = `bold 10px ${CF_FONT}`;
      ctx.textAlign = totalAligns[ci];
      const tx = totalAligns[ci] === "right"  ? x + col.w - PAD
               : totalAligns[ci] === "center" ? x + col.w / 2
               : x + PAD;
      ctx.fillText(totalCells[ci], tx, y + TTOT_H / 2 + 3.5);
    }
    y += TTOT_H + 14;

    // Summary box (bottom-right)
    const totalExp = totals.purchase + totals.other_expense;
    const profit   = totals.income - totalExp;

    const BW = 248, BH = 115;
    const BX = ML + CW - BW, BY = y;
    ctx.strokeStyle = "#c8d0e0";
    ctx.lineWidth = 1.5;
    ctx.strokeRect(BX, BY, BW, BH);

    const sumRows = [
      { label: "รายรับจากการขาย",   val: fmtN(totals.income)        + " บาท" },
      { label: "รายจ่ายซื้อสินค้า",  val: fmtN(totals.purchase)      + " บาท" },
      { label: "ค่าใช้จ่ายอื่นๆ",    val: fmtN(totals.other_expense) + " บาท", sep: true },
      { label: "รวมรายจ่าย",         val: fmtN(totalExp) + " บาท" },
      { label: "กำไรสุทธิ",          val: (profit >= 0 ? "+" : "") + fmtN(profit) + " บาท",
        bold: true, profit },
    ];

    let sy = BY + 16;
    for (const row of sumRows) {
      if (row.sep) {
        ctx.strokeStyle = "#ccc";
        ctx.lineWidth = 0.75;
        ctx.beginPath();
        ctx.moveTo(BX + 8, sy - 6); ctx.lineTo(BX + BW - 8, sy - 6);
        ctx.stroke();
        sy += 2;
      }
      ctx.fillStyle = row.bold ? (profit >= 0 ? "#16a34a" : "#dc2626") : "#111";
      ctx.font = row.bold ? `bold 11px ${CF_FONT}` : `10.5px ${CF_FONT}`;
      ctx.textAlign = "left";
      ctx.fillText(row.label, BX + 10, sy);
      ctx.textAlign = "right";
      ctx.fillText(row.val, BX + BW - 10, sy);
      sy += 19;
    }
  }

  ctx.textAlign = "left"; // reset
  return canvas;
}

async function exportCfPDF(settings, ymList, fetchFn) {
  if (!window.jspdf) throw new Error("jsPDF ยังไม่โหลด — กรุณารีเฟรชหน้าแล้วลองใหม่");
  const { jsPDF } = window.jspdf;

  await document.fonts.ready; // รอ Noto Sans Thai

  const doc = new jsPDF({ unit: "mm", format: "a4", orientation: "portrait" });
  let firstPage = true;

  for (const ym of ymList) {
    const entries = await fetchFn(ym);

    // chunk 30 แถว/หน้า
    const chunks = [];
    for (let i = 0; i < entries.length; i += ROWS_PER_PAGE) chunks.push(entries.slice(i, i + ROWS_PER_PAGE));
    if (chunks.length === 0) chunks.push([]);
    const totalPages = chunks.length;

    const tots = {
      income:        entries.reduce((a, e) => a + parseN(e.income), 0),
      purchase:      entries.reduce((a, e) => a + parseN(e.purchase), 0),
      other_expense: entries.reduce((a, e) => a + parseN(e.other_expense), 0),
    };

    for (let pi = 0; pi < chunks.length; pi++) {
      const canvas = await drawCfPageToCanvas(
        settings, ym, chunks[pi], pi, totalPages,
        pi === chunks.length - 1 ? tots : null
      );
      if (!firstPage) doc.addPage();
      firstPage = false;
      doc.addImage(canvas.toDataURL("image/jpeg", 0.92), "JPEG", 0, 0, 210, 297);
    }
  }

  const fym = ymList.length === 1
    ? ymList[0]
    : `${ymList[0]}_${ymList[ymList.length - 1]}`;
  doc.save(`สมุดรายรับ-จ่าย-${fym}.pdf`);
}

// ─── Excel Export ─────────────────────────────────────────────
async function exportCfExcel(settings, ymList, fetchFn) {
  if (!window.XLSX) throw new Error("XLSX ยังไม่โหลด — กรุณารีเฟรชหน้าแล้วลองใหม่");
  const { utils, writeFile } = window.XLSX;
  const s = settings || {};
  const wb = utils.book_new();

  for (const ym of ymList) {
    const entries = await fetchFn(ym);
    const tots = {
      income:        entries.reduce((a, e) => a + parseN(e.income), 0),
      purchase:      entries.reduce((a, e) => a + parseN(e.purchase), 0),
      other_expense: entries.reduce((a, e) => a + parseN(e.other_expense), 0),
    };
    const totalExp = tots.purchase + tots.other_expense;
    const profit   = tots.income - totalExp;

    const aoa = [];
    aoa.push(["สมุดรายรับ-รายจ่าย"]);
    aoa.push([`ประจำเดือน ${ymLabel(ym)}`]);
    if (s.owner_name)   aoa.push([`ชื่อผู้ประกอบการ: ${s.owner_name}`,  "", "", `เลขบัตรประชาชน: ${s.id_card || "-"}`]);
    if (s.business_name) aoa.push([`ชื่อกิจการ: ${s.business_name}`,   "", "", `เลขประจำตัวผู้เสียภาษี: ${s.tax_id || "-"}`]);
    aoa.push([]);
    // Header row
    aoa.push(["ลำดับ", "วัน/เดือน/ปี", "รายการ", "รายรับ (บาท)", "ซื้อสินค้า (บาท)", "ค่าใช้จ่ายอื่นๆ (บาท)", "หมายเหตุ"]);
    // Data rows
    entries.forEach((e, i) => aoa.push([
      i + 1,
      e.entry_date  || "",
      e.description || "",
      parseN(e.income)        || null,
      parseN(e.purchase)      || null,
      parseN(e.other_expense) || null,
      e.note || "",
    ]));
    // Total row
    aoa.push(["", "", "รวมทั้งสิ้น", tots.income, tots.purchase, tots.other_expense, ""]);
    aoa.push([]);
    // Summary
    aoa.push(["รายรับจากการขาย",  tots.income]);
    aoa.push(["รายจ่ายซื้อสินค้า", tots.purchase]);
    aoa.push(["ค่าใช้จ่ายอื่นๆ",  tots.other_expense]);
    aoa.push(["รวมรายจ่าย",        totalExp]);
    aoa.push(["กำไรสุทธิ",         profit]);

    const ws = utils.aoa_to_sheet(aoa);
    ws["!cols"] = [
      { wch: 7 }, { wch: 13 }, { wch: 36 },
      { wch: 15 }, { wch: 17 }, { wch: 20 }, { wch: 15 },
    ];
    const sheetName = ymLabel(ym).replace(/[:/\\?*[\]]/g, "").slice(0, 31);
    utils.book_append_sheet(wb, ws, sheetName);
  }

  const fym = ymList.length === 1
    ? ymList[0] : `${ymList[0]}_${ymList[ymList.length - 1]}`;
  writeFile(wb, `สมุดรายรับ-จ่าย-${fym}.xlsx`);
}

// ─── Number Cell ──────────────────────────────────────────────
function NumCell({ value, onSave, disabled }) {
  const [raw, setRaw] = useCfSt(() => {
    const n = parseN(value);
    return n ? fmtN(n) : "";
  });
  const [focused, setFocused] = useCfSt(false);

  useCfEf(() => {
    if (!focused) {
      const n = parseN(value);
      setRaw(n ? fmtN(n) : "");
    }
  }, [value, focused]);

  return (
    <input
      type="text"
      value={focused ? (raw === "0.00" ? "" : raw) : raw}
      onChange={e => setRaw(e.target.value)}
      onFocus={() => {
        setFocused(true);
        setRaw(parseN(raw) ? String(parseN(raw)) : "");
      }}
      onBlur={() => {
        setFocused(false);
        const n = parseN(raw);
        setRaw(n ? fmtN(n) : "");
        onSave(n);
      }}
      disabled={disabled}
      style={{
        width: "100%", border: "none", background: "transparent",
        textAlign: "right", fontSize: "inherit", fontFamily: "inherit",
        padding: "2px 0", outline: "none", minWidth: 0,
        fontVariantNumeric: "tabular-nums",
      }}
      placeholder="0.00"
    />
  );
}

// ─── Main Component ───────────────────────────────────────────
function CashFlow() {
  const [ym, setYm]               = useCfSt(getCurrentYmCF);
  const [entries, setEntries]     = useCfSt([]);
  const [settings, setSettings]   = useCfSt(null);
  const [months, setMonths]       = useCfSt([]);
  const [loading, setLoading]     = useCfSt(true);
  const [entriesLoading, setEntriesLoading] = useCfSt(false);
  const [toast, setToast]         = useCfSt("");
  const [showSettings, setShowSettings]   = useCfSt(false);
  const [showMultiExport, setShowMultiExport] = useCfSt(false);
  const timers = useCfRf({});

  function showToast(msg) {
    setToast(msg);
    clearTimeout(timers.current.__toast);
    timers.current.__toast = setTimeout(() => setToast(""), 2200);
  }

  // ── Load ──
  useCfEf(() => {
    (async () => {
      try {
        const [s, m] = await Promise.all([
          CF_API.get("/api/cash-flow-settings"),
          CF_API.get("/api/cash-flow-months"),
        ]);
        setSettings(s);
        setMonths(m || []);
      } catch(e) { showToast("โหลดข้อมูลไม่ได้"); }
      finally { setLoading(false); }
    })();
  }, []);

  useCfEf(() => {
    (async () => {
      setEntriesLoading(true);
      try {
        const data = await CF_API.get(`/api/cash-flow-entries?year_month=${ym}`);
        setEntries(data || []);
      } catch(e) { showToast("โหลดรายการไม่ได้"); }
      finally { setEntriesLoading(false); }
    })();
  }, [ym]);

  // ── Add rows ──
  const addRows = async (count) => {
    try {
      const newRows = Array.from({ length: count }, (_, i) => ({
        year_month: ym, entry_date: "", description: "",
        income: 0, purchase: 0, other_expense: 0, note: "",
        sort_order: entries.length + i,
      }));
      const res = await CF_API.post("/api/cash-flow-entries", newRows);
      // Reload entries
      const data = await CF_API.get(`/api/cash-flow-entries?year_month=${ym}`);
      setEntries(data || []);
      if (!months.includes(ym)) {
        setMonths(m => [...m, ym].sort());
      }
    } catch(e) { showToast("เพิ่มแถวไม่ได้: " + e.message); }
  };

  // ── Update local + debounce save ──
  const updateEntry = (id, field, value) => {
    setEntries(prev => prev.map(e => e.id === id ? { ...e, [field]: value } : e));
    const key = `${id}_${field}`;
    clearTimeout(timers.current[key]);
    timers.current[key] = setTimeout(async () => {
      try {
        await CF_API.put("/api/cash-flow-entries", [{ id, [field]: value }]);
        showToast("บันทึกแล้ว ✓");
      } catch(e) { showToast("บันทึกไม่ได้"); }
    }, 800);
  };

  // ── Delete ──
  const deleteEntry = async (id) => {
    try {
      await CF_API.del(`/api/cash-flow-entries?id=${id}`);
      setEntries(prev => prev.filter(e => e.id !== id));
    } catch(e) { showToast("ลบไม่ได้"); }
  };

  // ── Save settings ──
  const saveSettings = async (form) => {
    await CF_API.post("/api/cash-flow-settings", form);
    setSettings(form);
    showToast("บันทึกข้อมูลกิจการแล้ว ✓");
  };

  // ── Totals ──
  const totals = useCfMm(() => ({
    income:        entries.reduce((s, e) => s + parseN(e.income), 0),
    purchase:      entries.reduce((s, e) => s + parseN(e.purchase), 0),
    other_expense: entries.reduce((s, e) => s + parseN(e.other_expense), 0),
  }), [entries]);
  const totalExp = totals.purchase + totals.other_expense;
  const profit   = totals.income - totalExp;

  // ── Export helpers ──
  const fetchEntriesForYm = (targetYm) =>
    CF_API.get(`/api/cash-flow-entries?year_month=${targetYm}`);

  const exportSingle = () =>
    exportCfPDF(settings, [ym], fetchEntriesForYm)
      .catch(e => showToast("Export PDF ไม่ได้: " + e.message));

  const exportSingleExcel = () =>
    exportCfExcel(settings, [ym], fetchEntriesForYm)
      .catch(e => showToast("Export Excel ไม่ได้: " + e.message));

  const exportMultiPDF   = (list) => exportCfPDF(settings, list, fetchEntriesForYm);
  const exportMultiExcel = (list) => exportCfExcel(settings, list, fetchEntriesForYm);

  // ── Cell style ──
  const cell = {
    padding: "4px 6px", borderBottom: "1px solid var(--border)",
    verticalAlign: "middle", fontSize: "0.84rem",
  };
  const thStyle = {
    ...cell, background: "var(--surface-2)", fontWeight: 700,
    fontSize: "0.8rem", color: "var(--ink-2)", whiteSpace: "nowrap",
    borderBottom: "2px solid var(--border)", position: "sticky", top: 0, zIndex: 1,
  };
  const inputCell = {
    width: "100%", border: "none", background: "transparent",
    fontSize: "inherit", fontFamily: "inherit", padding: "2px 0",
    outline: "none", minWidth: 0,
  };

  const hasData = months.includes(ym);
  const s = settings || {};

  if (loading) return (
    <div style={{ display: "grid", placeItems: "center", height: 200, color: "var(--ink-3)" }}>
      กำลังโหลด...
    </div>
  );

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 16, paddingBottom: 32 }}>

      {/* ── Month Selector ── */}
      <div style={{
        display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap",
        background: "var(--surface)", borderRadius: 14, padding: "12px 16px",
        border: "1px solid var(--border)", boxShadow: "0 1px 4px rgba(0,0,0,0.05)",
      }}>
        <button className="btn" style={{ padding: "5px 10px", fontSize: "1rem" }}
          onClick={() => setYm(y => ymStep(y, -1))}>‹</button>

        <div style={{ fontWeight: 700, fontSize: "1rem", minWidth: 160, textAlign: "center" }}>
          {ymLabel(ym)}
          {hasData && (
            <span style={{ marginLeft: 8, fontSize: "0.72rem", background: "var(--accent)", color: "#fff", padding: "2px 8px", borderRadius: 99, fontWeight: 600 }}>
              มีข้อมูล
            </span>
          )}
        </div>

        <button className="btn" style={{ padding: "5px 10px", fontSize: "1rem" }}
          onClick={() => setYm(y => ymStep(y, 1))}>›</button>

        <div style={{ flex: 1 }}/>

        <button className="btn" style={{ display: "flex", alignItems: "center", gap: 6, fontSize: "0.84rem" }}
          onClick={() => setShowSettings(true)}>
          <Icon name="settings" size={15}/>ตั้งค่าข้อมูลกิจการ
        </button>
      </div>

      {/* ── Business Header ── */}
      <div style={{
        background: "var(--surface)", borderRadius: 14, padding: "14px 20px",
        border: "1px solid var(--border)", display: "grid",
        gridTemplateColumns: "1fr 1fr", gap: "6px 24px",
      }}>
        <InfoRow label="ชื่อผู้ประกอบการ" value={s.owner_name}/>
        <InfoRow label="เลขบัตรประชาชน"   value={s.id_card}/>
        <InfoRow label="ชื่อกิจการ"        value={s.business_name}/>
        <InfoRow label="เลขผู้เสียภาษี"    value={s.tax_id}/>
      </div>

      {/* ── Table ── */}
      <div style={{
        background: "var(--surface)", borderRadius: 14,
        border: "1px solid var(--border)", overflow: "hidden",
      }}>
        <div style={{ overflowX: "auto" }}>
          <table style={{ width: "100%", borderCollapse: "collapse", minWidth: 700 }}>
            <thead>
              <tr>
                <th style={{ ...thStyle, width: 36, textAlign: "center" }}>ลำดับ</th>
                <th style={{ ...thStyle, width: 90 }}>วัน/เดือน/ปี</th>
                <th style={{ ...thStyle }}>รายการ</th>
                <th style={{ ...thStyle, width: 110, textAlign: "right" }}>รายรับ (บาท)</th>
                <th style={{ ...thStyle, width: 110, textAlign: "right" }}>ซื้อสินค้า (บาท)</th>
                <th style={{ ...thStyle, width: 120, textAlign: "right" }}>ค่าใช้จ่ายอื่นๆ (บาท)</th>
                <th style={{ ...thStyle, width: 100 }}>หมายเหตุ</th>
                <th style={{ ...thStyle, width: 36 }}></th>
              </tr>
            </thead>
            <tbody>
              {entriesLoading && (
                <tr><td colSpan={8} style={{ ...cell, textAlign: "center", color: "var(--ink-3)", padding: "20px 0" }}>กำลังโหลด...</td></tr>
              )}
              {!entriesLoading && entries.length === 0 && (
                <tr><td colSpan={8} style={{ ...cell, textAlign: "center", color: "var(--ink-3)", padding: "28px 0" }}>
                  ยังไม่มีรายการ — กด "+ เพิ่มแถว" เพื่อเริ่ม
                </td></tr>
              )}
              {!entriesLoading && entries.map((e, i) => (
                <tr key={e.id} style={{ background: i % 2 === 0 ? "transparent" : "var(--surface-2, rgba(0,0,0,0.015))" }}>
                  <td style={{ ...cell, textAlign: "center", color: "var(--ink-3)", fontSize: "0.78rem" }}>{i + 1}</td>
                  <td style={cell}>
                    <input style={inputCell}
                      value={e.entry_date || ""}
                      onChange={ev => updateEntry(e.id, "entry_date", ev.target.value)}
                      placeholder="01/06/69"/>
                  </td>
                  <td style={cell}>
                    <input style={inputCell}
                      value={e.description || ""}
                      onChange={ev => updateEntry(e.id, "description", ev.target.value)}
                      placeholder="รายการ..."/>
                  </td>
                  <td style={{ ...cell, textAlign: "right" }}>
                    <NumCell value={e.income} onSave={v => updateEntry(e.id, "income", v)}/>
                  </td>
                  <td style={{ ...cell, textAlign: "right" }}>
                    <NumCell value={e.purchase} onSave={v => updateEntry(e.id, "purchase", v)}/>
                  </td>
                  <td style={{ ...cell, textAlign: "right" }}>
                    <NumCell value={e.other_expense} onSave={v => updateEntry(e.id, "other_expense", v)}/>
                  </td>
                  <td style={cell}>
                    <input style={inputCell}
                      value={e.note || ""}
                      onChange={ev => updateEntry(e.id, "note", ev.target.value)}
                      placeholder="หมายเหตุ"/>
                  </td>
                  <td style={{ ...cell, textAlign: "center" }}>
                    <button onClick={() => deleteEntry(e.id)}
                      style={{ background: "none", border: "none", cursor: "pointer", color: "var(--danger, #dc2626)", padding: 2, display: "inline-flex", alignItems: "center" }}
                      title="ลบแถวนี้">
                      <Icon name="trash" size={14}/>
                    </button>
                  </td>
                </tr>
              ))}

              {/* Total row */}
              {!entriesLoading && entries.length > 0 && (
                <tr style={{ background: "var(--surface-2)", fontWeight: 700 }}>
                  <td colSpan={3} style={{ ...cell, textAlign: "right", fontSize: "0.84rem" }}>รวมทั้งสิ้น</td>
                  <td style={{ ...cell, textAlign: "right", fontVariantNumeric: "tabular-nums" }}>{fmtN(totals.income)}</td>
                  <td style={{ ...cell, textAlign: "right", fontVariantNumeric: "tabular-nums" }}>{fmtN(totals.purchase)}</td>
                  <td style={{ ...cell, textAlign: "right", fontVariantNumeric: "tabular-nums" }}>{fmtN(totals.other_expense)}</td>
                  <td colSpan={2} style={cell}></td>
                </tr>
              )}
            </tbody>
          </table>
        </div>

        {/* Add row buttons */}
        <div style={{ display: "flex", gap: 8, padding: "10px 14px", borderTop: "1px solid var(--border)" }}>
          <button className="btn" style={{ fontSize: "0.84rem", display: "flex", alignItems: "center", gap: 5 }}
            onClick={() => addRows(1)}>
            <Icon name="plus" size={14}/> เพิ่มแถว
          </button>
          <button className="btn" style={{ fontSize: "0.84rem", display: "flex", alignItems: "center", gap: 5 }}
            onClick={() => addRows(5)}>
            <Icon name="plus" size={14}/> เพิ่ม 5 แถว
          </button>
        </div>
      </div>

      {/* ── Summary Cards ── */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(160px, 1fr))", gap: 12 }}>
        <SumCard label="รายรับจากการขาย" value={totals.income} color="var(--ok, #16a34a)"/>
        <SumCard label="รายจ่ายซื้อสินค้า" value={totals.purchase} color="var(--danger, #dc2626)"/>
        <SumCard label="ค่าใช้จ่ายอื่นๆ" value={totals.other_expense} color="var(--danger, #dc2626)"/>
        <SumCard label="รวมรายจ่าย" value={totalExp} color="var(--danger, #dc2626)"/>
        <SumCard label="กำไรสุทธิ" value={profit} big
          color={profit >= 0 ? "var(--ok, #16a34a)" : "var(--danger, #dc2626)"}/>
      </div>

      {/* ── Export Buttons ── */}
      <div style={{ display: "flex", gap: 10, flexWrap: "wrap" }}>
        <button className="btn primary" style={{ display: "flex", alignItems: "center", gap: 7 }}
          onClick={exportSingle}>
          <Icon name="download" size={16}/> Export PDF เดือนนี้
        </button>
        <button className="btn" style={{ display: "flex", alignItems: "center", gap: 7, color: "#16a34a", borderColor: "#16a34a" }}
          onClick={exportSingleExcel}>
          <Icon name="doc" size={16}/> Export Excel เดือนนี้
        </button>
        <button className="btn" style={{ display: "flex", alignItems: "center", gap: 7 }}
          onClick={() => setShowMultiExport(true)}>
          <Icon name="doc" size={16}/> Export หลายเดือน
        </button>
      </div>

      {/* ── Modals ── */}
      <CfSettingsModal open={showSettings} onClose={() => setShowSettings(false)}
        onSave={saveSettings} initial={settings}/>
      <CfMultiExportModal open={showMultiExport} onClose={() => setShowMultiExport(false)}
        months={months} onExportPDF={exportMultiPDF} onExportExcel={exportMultiExcel}/>
      <CfToast msg={toast}/>
    </div>
  );
}

// ─── Sub-components ───────────────────────────────────────────
function InfoRow({ label, value }) {
  return (
    <div style={{ display: "flex", gap: 6, fontSize: "0.84rem", alignItems: "baseline" }}>
      <span style={{ color: "var(--ink-3)", whiteSpace: "nowrap", minWidth: 100 }}>{label}:</span>
      <span style={{ fontWeight: 600 }}>{value || <span style={{ color: "var(--ink-3)", fontWeight: 400 }}>—</span>}</span>
    </div>
  );
}

function SumCard({ label, value, color, big }) {
  return (
    <div style={{
      background: "var(--surface)", border: "1px solid var(--border)",
      borderRadius: 12, padding: big ? "16px 20px" : "14px 18px",
      boxShadow: "0 1px 4px rgba(0,0,0,0.05)",
    }}>
      <div style={{ fontSize: "0.78rem", color: "var(--ink-3)", marginBottom: 4 }}>{label}</div>
      <div style={{
        fontWeight: 700, fontSize: big ? "1.2rem" : "1rem",
        color, fontVariantNumeric: "tabular-nums",
      }}>
        {fmtN(value)}
        <span style={{ fontSize: "0.75rem", fontWeight: 400, marginLeft: 3 }}>บาท</span>
      </div>
    </div>
  );
}

window.CashFlow = CashFlow;
