/* global React, I, UI, SSSData, SSSAccounting, XLSX */
const { useState: useStateB, useMemo: useMemoB } = React;

// ============================================================
//  สมุดรายวันเฉพาะ (Specialized Journals)
//  ตามมาตรฐานการบัญชีไทย — ขาย / ซื้อ / รับเงิน / จ่ายเงิน
//  + drill-in รายการบันทึกบัญชี + ลิงก์รูปเอกสาร + ส่งออก Excel
// ============================================================

const fmt2B = (n) => (n || 0).toLocaleString("th-TH", { minimumFractionDigits: 2, maximumFractionDigits: 2 });

// คอลัมน์เฉพาะของแต่ละสมุด ตามรูปแบบบัญชีไทย
const BOOK_SPECS = {
  SJ: {
    title: "สมุดรายวันขาย", en: "Sales Journal",
    refLabel: "เลขที่ใบกำกับภาษี/ใบแจ้งหนี้", partyLabel: "ลูกค้า",
    legal: "บันทึกเฉพาะการขายเชื่อ — เดบิตลูกหนี้การค้า เครดิตรายได้และภาษีขาย (มาตรฐานการบัญชี + ภ.พ.30)",
    cols: [
      { label: "ลูกหนี้การค้า", sub: "1130", side: "Dr", accs: ["1130"] },
      { label: "ขายสินค้า", sub: "4110", side: "Cr", accs: ["4110"] },
      { label: "รายได้บริการ", sub: "4120", side: "Cr", accs: ["4120"] },
      { label: "ภาษีขาย", sub: "2120", side: "Cr", accs: ["2120"] }
    ]
  },
  PJ: {
    title: "สมุดรายวันซื้อ", en: "Purchases Journal",
    refLabel: "เลขที่ใบกำกับภาษีซื้อ", partyLabel: "ผู้ขาย/เจ้าหนี้",
    legal: "บันทึกเฉพาะการซื้อเชื่อ — เดบิตสินค้า/ภาษีซื้อ เครดิตเจ้าหนี้การค้า (ภาษีซื้อใช้ใน ภ.พ.30)",
    cols: [
      { label: "ซื้อ/สินค้าคงเหลือ", sub: "1140", side: "Dr", accs: ["1140"] },
      { label: "ภาษีซื้อ", sub: "1151", side: "Dr", accs: ["1151"] },
      { label: "เจ้าหนี้การค้า", sub: "2110", side: "Cr", accs: ["2110"] }
    ]
  },
  CR: {
    title: "สมุดรายวันรับเงิน", en: "Cash Receipts Journal",
    refLabel: "เลขที่ใบเสร็จรับเงิน", partyLabel: "ผู้ชำระ/รายการ",
    legal: "บันทึกการรับเงินทุกประเภท — เดบิตเงินสด/ธนาคาร เครดิตลูกหนี้หรือรายได้",
    cols: [
      { label: "เงินสด/ธนาคาร", sub: "1110-1122", side: "Dr", accs: ["1110", "1121", "1122"] },
      { label: "ลูกหนี้การค้า", sub: "1130", side: "Cr", accs: ["1130"] },
      { label: "ขายสด", sub: "4110", side: "Cr", accs: ["4110"] }
    ]
  },
  CP: {
    title: "สมุดรายวันจ่ายเงิน", en: "Cash Payments Journal",
    refLabel: "เลขที่ใบสำคัญจ่าย", partyLabel: "ผู้รับเงิน/รายการ",
    legal: "บันทึกการจ่ายเงินทุกประเภท — เดบิตค่าใช้จ่าย/เจ้าหนี้ เครดิตภาษีหัก ณ ที่จ่ายและเงินสด/ธนาคาร",
    cols: [
      { label: "เงินสด/ธนาคาร", sub: "1110-1122", side: "Cr", accs: ["1110", "1121", "1122"] },
      { label: "ภาษีหัก ณ ที่จ่าย", sub: "2131-2133", side: "Cr", accs: ["2131", "2132", "2133"] },
      { label: "ประกันสังคมค้าง", sub: "2140", side: "Cr", accs: ["2140"] }
    ]
  },
  GJ: {
    title: "สมุดรายวันทั่วไป", en: "General Journal",
    refLabel: "เลขที่เอกสารอ้างอิง", partyLabel: "คำอธิบายรายการ",
    legal: "บันทึกรายการที่ไม่เข้าสมุดรายวันเฉพาะ เช่น รายการปรับปรุง ค่าเสื่อมราคา",
    cols: []
  }
};

// prefix เอกสาร → route + label สำหรับลิงก์
const REF_MAP = [
  { p: "TI-V", route: null, label: "ใบกำกับภาษีซื้อ (ผู้ขายออก)", scan: true },
  { p: "INV", route: "invoices", label: "ใบแจ้งหนี้" },
  { p: "TX", route: "tax-invoices", label: "ใบกำกับภาษีขาย" },
  { p: "RC", route: "receipts", label: "ใบเสร็จรับเงิน" },
  { p: "PO", route: "purchase-orders", label: "ใบสั่งซื้อ" },
  { p: "PV", route: "payment-vouchers", label: "ใบสำคัญจ่าย" },
  { p: "BN", route: "billing-notes", label: "ใบวางบิล" },
  { p: "ADJ", route: null, label: "ใบสำคัญทั่วไป (ปรับปรุง)", scan: true },
  { p: "PR", route: null, label: "สรุปการจ่ายเงินเดือน", scan: true }
];

function resolveRef(token) {
  const t = token.trim();
  const m = REF_MAP.find(r => t.toUpperCase().startsWith(r.p));
  return m ? { ...m, token: t } : { p: "?", route: null, label: "เอกสารอ้างอิง", token: t, scan: true };
}

// ============================================================
//  Hub — segmented control across the 5 books
// ============================================================
function JournalHub({ navigate }) {
  const A = window.SSSAccounting;
  const [book, setBook] = useStateB("SJ");
  const [detail, setDetail] = useStateB(null);

  const books = [
    { k: "SJ", label: "ขาย" },
    { k: "PJ", label: "ซื้อ" },
    { k: "CR", label: "รับเงิน" },
    { k: "CP", label: "จ่ายเงิน" },
    { k: "GJ", label: "ทั่วไป" },
    { k: "ALL", label: "รวมทุกสมุด" }
  ];

  return (
    <div style={{display: "flex", flexDirection: "column", gap: 14}}>
      {/* Segmented book selector */}
      <div style={{display: "inline-flex", gap: 2, padding: 3, background: "var(--surface-2)",
        border: "1px solid var(--line)", borderRadius: 8, alignSelf: "flex-start", flexWrap: "wrap"}}>
        {books.map(b => {
          const active = book === b.k;
          const c = b.k === "ALL" ? A.JournalEntries.length : A.JournalEntries.filter(e => e.type === b.k).length;
          const color = b.k === "ALL" ? "var(--ink-1)" : window.JOURNAL_TYPES[b.k].color;
          return (
            <button key={b.k} onClick={() => setBook(b.k)} style={{
              padding: "7px 14px", borderRadius: 6, cursor: "pointer", fontFamily: "var(--font)",
              fontSize: 13, fontWeight: active ? 600 : 400,
              background: active ? "var(--surface)" : "transparent",
              color: active ? "var(--ink-1)" : "var(--ink-3)",
              border: active ? "1px solid var(--line)" : "1px solid transparent",
              boxShadow: active ? "var(--shadow-sm)" : "none",
              display: "inline-flex", alignItems: "center", gap: 7
            }}>
              {b.k !== "ALL" && <span style={{width: 7, height: 7, borderRadius: "50%", background: color}}/>}
              สมุดรายวัน{b.label === "รวมทุกสมุด" ? "" : ""}{b.label}
              <span style={{fontSize: 11, opacity: 0.6}}>{c}</span>
            </button>
          );
        })}
      </div>

      {book === "ALL"
        ? <window.JournalBook onOpen={setDetail}/>
        : <SpecializedJournal jtype={book} onOpen={setDetail}/>}

      {detail && <JournalEntryDetail entry={detail} navigate={navigate} onClose={() => setDetail(null)}/>}
    </div>
  );
}

// ============================================================
//  Specialized journal table
// ============================================================
function SpecializedJournal({ jtype, onOpen }) {
  const { Card, Btn } = window.UI;
  const A = window.SSSAccounting;
  const spec = BOOK_SPECS[jtype];
  const T = window.JOURNAL_TYPES[jtype];
  const [search, setSearch] = useStateB("");

  const entries = useMemoB(() => A.JournalEntries
    .filter(e => e.type === jtype)
    .filter(e => {
      if (!search) return true;
      const q = search.toLowerCase();
      return e.desc.toLowerCase().includes(q) || e.ref.toLowerCase().includes(q) || e.id.toLowerCase().includes(q);
    })
    .sort((a, b) => cmpThaiDate(a.date, b.date)), [jtype, search]);

  const rows = entries.map(e => ({ entry: e, ...distribute(e, spec) }));
  const colTotals = spec.cols.map((_, i) => rows.reduce((s, r) => s + r.colSums[i], 0));
  const sundryDr = rows.reduce((s, r) => s + r.sundry.filter(x => x.side === "Dr").reduce((a, x) => a + x.amt, 0), 0);
  const sundryCr = rows.reduce((s, r) => s + r.sundry.filter(x => x.side === "Cr").reduce((a, x) => a + x.amt, 0), 0);
  const hasSundry = rows.some(r => r.sundry.length > 0);

  return (
    <div style={{display: "flex", flexDirection: "column", gap: 12}}>
      {/* Legal note */}
      <div style={{padding: "10px 14px", background: "var(--surface-2)", border: `1px solid var(--line)`,
        borderLeft: `3px solid ${T.color}`, borderRadius: "var(--radius-sm)", fontSize: 12, color: "var(--ink-2)"}}>
        <b>{spec.title} ({spec.en})</b> — {spec.legal}
      </div>

      {/* Toolbar */}
      <div style={{display: "flex", gap: 8, alignItems: "center"}}>
        <div className="search" style={{maxWidth: 280, position: "relative"}}>
          <I.search size={14}/>
          <input placeholder="ค้นหา JV / เอกสาร / คำอธิบาย…" value={search} onChange={e => setSearch(e.target.value)}/>
        </div>
        <div style={{flex: 1}}/>
        <span style={{fontSize: 12, color: "var(--ink-3)"}}>{entries.length} รายการ · งวด พ.ค. 2569</span>
        <Btn size="sm" kind="ghost" icon={I.download} onClick={() => exportBookExcel(jtype)}>ส่งออก Excel</Btn>
      </div>

      <Card flush>
        <div className="table-wrap">
          <table className="t spec-journal">
            <thead>
              <tr>
                <th style={{width: 78}}>วันที่</th>
                <th style={{width: 96}}>เลขที่ JV</th>
                <th style={{width: 150}}>{spec.refLabel}</th>
                <th style={{minWidth: 160}}>{spec.partyLabel}</th>
                {spec.cols.map((c, i) => (
                  <th key={i} className="right" style={{width: 116}}>
                    <div>{c.label}</div>
                    <div style={{fontSize: 10, fontWeight: 400, color: "var(--ink-4)"}}>{c.sub} · {c.side}</div>
                  </th>
                ))}
                {(hasSundry || spec.cols.length === 0) && <th style={{minWidth: 180}}>บัญชีอื่น ๆ (Dr/Cr)</th>}
                <th style={{width: 40}}></th>
              </tr>
            </thead>
            <tbody>
              {rows.map(({ entry, colSums, sundry }) => (
                <tr key={entry.id} className="spec-row" onClick={() => onOpen(entry)} style={{cursor: "pointer"}}>
                  <td style={{fontSize: 12}}>{entry.date}</td>
                  <td className="mono" style={{fontSize: 12, fontWeight: 600}}>{entry.id}</td>
                  <td>
                    {entry.ref.split("/").map((r, i) => (
                      <div key={i} className="mono" style={{fontSize: 11, color: "var(--ink-2)"}}>{r.trim()}</div>
                    ))}
                  </td>
                  <td>
                    <div style={{fontSize: 12.5}}>{extractParty(entry)}</div>
                    <div style={{fontSize: 11, color: "var(--ink-3)", marginTop: 1}}>{entry.desc}</div>
                  </td>
                  {colSums.map((v, i) => (
                    <td key={i} className="right amount" style={{fontVariantNumeric: "tabular-nums", color: v ? "var(--ink-1)" : "var(--ink-4)"}}>
                      {v ? fmt2B(v) : "–"}
                    </td>
                  ))}
                  {(hasSundry || spec.cols.length === 0) && (
                    <td>
                      {sundry.length === 0 ? <span style={{color: "var(--ink-4)"}}>–</span> :
                        sundry.map((x, i) => {
                          const acc = A.accByCode[x.acc];
                          return (
                            <div key={i} style={{fontSize: 11.5, display: "flex", justifyContent: "space-between", gap: 8}}>
                              <span style={{color: "var(--ink-2)"}}>
                                <span className="mono" style={{color: "var(--ink-4)"}}>{x.acc}</span> {acc?.name}
                                <span style={{color: x.side === "Dr" ? "var(--info)" : "var(--warning)", fontWeight: 600, marginLeft: 4}}>{x.side}</span>
                              </span>
                              <span className="amount" style={{fontVariantNumeric: "tabular-nums"}}>{fmt2B(x.amt)}</span>
                            </div>
                          );
                        })}
                    </td>
                  )}
                  <td style={{textAlign: "center", color: "var(--ink-3)"}}><I.chevronRight size={14}/></td>
                </tr>
              ))}
              {rows.length === 0 && (
                <tr><td colSpan={spec.cols.length + 6} style={{textAlign: "center", padding: 40, color: "var(--ink-4)"}}>ไม่มีรายการในสมุดนี้</td></tr>
              )}
            </tbody>
            <tfoot>
              <tr style={{borderTop: "2px solid var(--ink-1)", background: "var(--surface-2)", fontWeight: 600}}>
                <td colSpan="4" style={{padding: "12px 14px"}}>ยอดรวม {spec.title}</td>
                {colTotals.map((v, i) => (
                  <td key={i} className="right amount" style={{padding: "12px 8px", fontVariantNumeric: "tabular-nums"}}>{fmt2B(v)}</td>
                ))}
                {(hasSundry || spec.cols.length === 0) && (
                  <td style={{padding: "12px 8px", fontSize: 11.5}}>
                    <div style={{display: "flex", justifyContent: "space-between"}}><span>รวม Dr</span><span className="amount">{fmt2B(sundryDr)}</span></div>
                    <div style={{display: "flex", justifyContent: "space-between"}}><span>รวม Cr</span><span className="amount">{fmt2B(sundryCr)}</span></div>
                  </td>
                )}
                <td></td>
              </tr>
            </tfoot>
          </table>
        </div>
      </Card>
    </div>
  );
}

// ====== helpers ======
function distribute(entry, spec) {
  const colSums = spec.cols.map(() => 0);
  const sundry = [];
  entry.lines.forEach(l => {
    const side = l.dr > 0 ? "Dr" : "Cr";
    const amt = l.dr > 0 ? l.dr : l.cr;
    let placed = false;
    spec.cols.forEach((c, i) => {
      if (!placed && c.side === side && c.accs.includes(l.acc)) { colSums[i] += amt; placed = true; }
    });
    if (!placed) sundry.push({ acc: l.acc, side, amt, note: l.note });
  });
  return { colSums, sundry };
}

function extractParty(entry) {
  // pull a party name out of the description heuristically
  const d = entry.desc;
  const m = d.match(/(บจก\.|หจก\.|บริษัท|ร้าน|คุณ)[^—\-]+/);
  if (m) return m[0].trim();
  // company names like "POSCO Thailand", "Bangkok Stainless Works", "Modern Kitchen Design"
  const m2 = d.match(/[A-Z][A-Za-z]+(?:\s[A-Z][A-Za-z]+){0,3}/);
  if (m2) return m2[0].trim();
  return d.split("—")[0].trim();
}

function cmpThaiDate(a, b) {
  // dates like "21/05/2569"
  const pa = a.split("/").map(Number), pb = b.split("/").map(Number);
  return (pa[2] - pb[2]) || (pa[1] - pb[1]) || (pa[0] - pb[0]);
}

window.JournalHub = JournalHub;
window.SpecializedJournal = SpecializedJournal;
window.BOOK_SPECS = BOOK_SPECS;
window.resolveRef = resolveRef;
window.distribute = distribute;
window.extractParty = extractParty;
