/* TaxFlow — main app shell, routing, state, tweaks */
/* globals React, ReactDOM, NAV, Sidebar, Topbar, Btn, IconBtn, Modal, I,
   ScreenDashboard, ScreenPL, ScreenVAT, ScreenSales, ScreenPurchases,
   ScreenSuppliers, ScreenAudit, ScreenTrash, ToastHost, toast, cls,
   TweaksPanel, useTweaks, TweakSection, TweakRadio, TweakSlider, TweakColor, TweakSelect, TweakToggle */

const { useState, useEffect, useReducer, useMemo, useRef } = React;

/* --------------------------- STORE / REDUCER --------------------------- */

const initialStore = {
  suppliers:      [],
  purchases:      [],
  sales:          [],
  trashSales:     [],
  trashPurchases: [],
  audit:          [],
};

function reducer(s, a) {
  switch (a.type) {
    case "hydrate":
      return { ...s, ...a.data };
    case "addPurchase":
      return { ...s, purchases: [a.row, ...s.purchases] };
    case "updatePurchase":
      return { ...s, purchases: s.purchases.map(p => p.id === a.row.id ? a.row : p) };
    case "deletePurchase": {
      const p = s.purchases.find(x => x.id === a.id);
      if (!p) return s;
      return {
        ...s,
        purchases: s.purchases.filter(x => x.id !== a.id),
        trashPurchases: [{
          id: p.id, invNo: p.invNo, date: p.date,
          customer: s.suppliers.find(x => x.id === p.supplierId)?.name || "",
          total: p.preVat + p.vat, reason: "",
        }, ...s.trashPurchases],
      };
    }
    case "addSale":
      return { ...s, sales: [a.row, ...s.sales] };
    case "updateSale":
      return { ...s, sales: s.sales.map(x => x.id === a.row.id ? a.row : x) };
    case "deleteSale": {
      const r = s.sales.find(x => x.id === a.id);
      if (!r) return s;
      return {
        ...s,
        sales: s.sales.filter(x => x.id !== a.id),
        trashSales: [{ id: r.id, invNo: "", date: r.date, customer: r.channel,
          total: r.preVat + r.vat, reason: "" }, ...s.trashSales],
      };
    }
    case "addSupplier":
      return { ...s, suppliers: [a.row, ...s.suppliers] };
    case "updateSupplier":
      return { ...s, suppliers: s.suppliers.map(x => x.id === a.row.id ? a.row : x) };
    case "deleteSupplier":
      return { ...s, suppliers: s.suppliers.filter(x => x.id !== a.id) };
    case "restoreTrash": {
      // a.kind = "purchase" | "sale"  (returned by the API)
      // a.row  = full restored row
      const trashKey = a.kind === "sale" ? "trashSales" : "trashPurchases";
      const listKey  = a.kind === "sale" ? "sales" : "purchases";
      return {
        ...s,
        [trashKey]: s[trashKey].filter(x => x.id !== a.id),
        [listKey]:  [a.row, ...s[listKey]],
      };
    }
    default: return s;
  }
}

/* --------------------------- ADD/EDIT MODAL --------------------------- */

const SALES_CHANNELS = ["หน้าร้าน", "lineman", "grab", "shopee", "foodpanda", "อื่นๆ"];

function PurchaseModal({ open, onClose, initial, suppliers, onSave, onAddSupplier }) {
  const [form, setForm] = useState(initial || blank());
  const [uploading, setUploading] = useState(false);
  useEffect(() => { setForm(initial || blank()); setUploading(false); }, [initial, open]);
  function blank() {
    return { id: "p_" + Math.random().toString(36).slice(2, 8),
      invNo: "", date: new Date().toISOString().slice(0,10), supplierId: null,
      detail: "", preVat: 0, vat: 0, credit: false,
      attachmentKey: null, attachmentName: null };
  }
  async function handleFileUpload(file) {
    setUploading(true);
    try {
      const r = await window.TaxFlowAPI.uploadFile(file);
      setForm(f => ({ ...f, attachmentKey: r.key, attachmentName: r.name }));
    } catch (e) {
      toast("อัปโหลดไม่สำเร็จ: " + e.message);
    } finally {
      setUploading(false);
    }
  }
  async function handleRemoveFile() {
    const key = form.attachmentKey;
    setForm(f => ({ ...f, attachmentKey: null, attachmentName: null }));
    if (key) window.TaxFlowAPI.deleteFile(key).catch(() => {});
  }
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  // When the user edits total, derive preVat & vat (assume 7%); when credit OFF, vat=0
  const setTotal = (totalStr) => {
    const total = parseFloat(totalStr) || 0;
    if (form.credit) {
      const pre = +(total / 1.07).toFixed(2);
      const v   = +(total - pre).toFixed(2);
      setForm(f => ({ ...f, preVat: pre, vat: v, total }));
    } else {
      setForm(f => ({ ...f, preVat: total, vat: 0, total }));
    }
  };
  const total = form.total != null ? form.total : (Number(form.preVat)||0) + (Number(form.vat)||0);

  // re-derive when credit toggle changes
  useEffect(() => {
    if (form.total == null) return;
    setTotal(form.total);
  // eslint-disable-next-line
  }, [form.credit]);

  const valid = form.date && total > 0;

  return (
    <Modal open={open} onClose={onClose}
      title={initial ? "แก้ไขภาษีซื้อ" : "เพิ่มภาษีซื้อ"}
      width={620}
      footer={
        <>
          <Btn variant="ghost" onClick={onClose}>ยกเลิก</Btn>
          <Btn variant="primary" disabled={!valid} onClick={() => {
            const preVat = +form.preVat || 0;
            const vat = form.credit ? (+form.vat || 0) : 0;
            onSave({ ...form, preVat, vat });
            onClose();
            toast(initial ? "บันทึกการแก้ไขแล้ว" : "เพิ่มใบกำกับใหม่แล้ว");
          }}>
            <I.check width="14" height="14"/> บันทึก
          </Btn>
        </>
      }
    >
      <div className="form-grid">
        <Field label="เลขที่ใบกำกับภาษี">
          <input value={form.invNo} onChange={e => set("invNo", e.target.value)} placeholder="เช่น P69050003"/>
        </Field>
        <Field label={<span>วันที่ <span className="req">*</span></span>}>
          <input type="date" value={form.date} onChange={e => set("date", e.target.value)}/>
        </Field>

        <Field full label={<>
            <span>ผู้ขาย / ซัพพลายเออร์</span>
            <button type="button" className="link-btn" onClick={onAddSupplier}>
              <I.plus width="12" height="12"/> เพิ่มผู้ขายใหม่
            </button>
          </>}>
          <select value={form.supplierId || ""} onChange={e => set("supplierId", e.target.value || null)}>
            <option value="">— เลือกผู้ขาย —</option>
            {suppliers.map(s => <option key={s.id} value={s.id}>{s.name}</option>)}
          </select>
        </Field>

        <Field label="รายละเอียด" full>
          <input value={form.detail} onChange={e => set("detail", e.target.value)} placeholder="รายละเอียดสินค้า/บริการ"/>
        </Field>

        <div className="field-full money-group">
          <div className="money-h">จำนวนเงิน</div>
          <div className="money-row">
            <Field label="มูลค่าก่อน VAT">
              <NumberInput value={form.preVat} onChange={(v) => setForm(f => ({...f, preVat: v, total: null}))} disabled={form.credit}/>
            </Field>
            <Field label="VAT 7%">
              <NumberInput value={form.vat} onChange={(v) => setForm(f => ({...f, vat: v, total: null}))} disabled={!form.credit}/>
            </Field>
            <Field label={<span>มูลค่ารวม VAT <span className="req">*</span></span>}>
              <NumberInput value={total} onChange={setTotal} highlight/>
            </Field>
          </div>
          <div className="hint">กรอกมูลค่ารวม VAT แล้วระบบจะคำนวณอัตโนมัติ</div>
        </div>

        <label className={cls("credit-box field-full", form.credit && "is-on")}>
          <input type="checkbox" checked={form.credit} onChange={e => set("credit", e.target.checked)}/>
          <div>
            <div className="credit-t">นำ VAT ไปขอเครดิตคืนได้</div>
            <div className="credit-s">ติ๊กถ้าใบกำกับนี้มีสิทธิ์ขอคืนภาษีซื้อ (Input Tax Credit)</div>
          </div>
        </label>

        <AttachmentField full
          attachmentKey={form.attachmentKey}
          attachmentName={form.attachmentName}
          uploading={uploading}
          onUploaded={handleFileUpload}
          onRemove={handleRemoveFile}
        />
      </div>
    </Modal>
  );
}

function SaleModal({ open, onClose, initial, onSave }) {
  const [form, setForm] = useState(initial || blank());
  const [uploading, setUploading] = useState(false);
  useEffect(() => { setForm(initial || blank()); setUploading(false); }, [initial, open]);
  function blank() {
    return { id: "sa_" + Math.random().toString(36).slice(2, 8),
      date: new Date().toISOString().slice(0,10), channel: "หน้าร้าน",
      detail: "", preVat: 0, vat: 0, hasVat: true,
      attachmentKey: null, attachmentName: null };
  }
  async function handleFileUpload(file) {
    setUploading(true);
    try {
      const r = await window.TaxFlowAPI.uploadFile(file);
      setForm(f => ({ ...f, attachmentKey: r.key, attachmentName: r.name }));
    } catch (e) {
      toast("อัปโหลดไม่สำเร็จ: " + e.message);
    } finally {
      setUploading(false);
    }
  }
  async function handleRemoveFile() {
    const key = form.attachmentKey;
    setForm(f => ({ ...f, attachmentKey: null, attachmentName: null }));
    if (key) window.TaxFlowAPI.deleteFile(key).catch(() => {});
  }
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const setTotal = (totalStr) => {
    const total = parseFloat(totalStr) || 0;
    if (form.hasVat) {
      const pre = +(total / 1.07).toFixed(2);
      const v   = +(total - pre).toFixed(2);
      setForm(f => ({ ...f, preVat: pre, vat: v, total }));
    } else {
      setForm(f => ({ ...f, preVat: total, vat: 0, total }));
    }
  };
  const total = form.total != null ? form.total : (Number(form.preVat)||0) + (Number(form.vat)||0);
  const valid = form.date && total > 0;

  return (
    <Modal open={open} onClose={onClose}
      title={initial ? "แก้ไขภาษีขาย" : "เพิ่มภาษีขาย"}
      width={620}
      footer={
        <>
          <Btn variant="ghost" onClick={onClose}>ยกเลิก</Btn>
          <Btn variant="primary" disabled={!valid} onClick={() => {
            onSave({ ...form, preVat: +form.preVat || 0, vat: +form.vat || 0 });
            onClose();
            toast(initial ? "บันทึกการแก้ไขแล้ว" : "เพิ่มรายการขายแล้ว");
          }}>
            <I.check width="14" height="14"/> บันทึก
          </Btn>
        </>
      }
    >
      <div className="form-grid">
        <Field label={<span>วันที่ <span className="req">*</span></span>}>
          <input type="date" value={form.date} onChange={e => set("date", e.target.value)}/>
        </Field>
        <Field label={<span>ช่องทาง <span className="req">*</span></span>}>
          <select value={form.channel} onChange={e => set("channel", e.target.value)}>
            {SALES_CHANNELS.map(c => <option key={c} value={c}>{c}</option>)}
          </select>
        </Field>

        <Field label="รายละเอียด" full>
          <input value={form.detail} onChange={e => set("detail", e.target.value)} placeholder="เช่น ยอดขายรวมประจำวัน"/>
        </Field>

        <div className="field-full money-group">
          <div className="money-h">จำนวนเงิน</div>
          <div className="money-row">
            <Field label="มูลค่าก่อน VAT">
              <NumberInput value={form.preVat} onChange={(v) => setForm(f => ({...f, preVat: v, total: null}))} disabled={form.hasVat}/>
            </Field>
            <Field label="VAT 7%">
              <NumberInput value={form.vat} onChange={(v) => setForm(f => ({...f, vat: v, total: null}))} disabled={!form.hasVat}/>
            </Field>
            <Field label={<span>มูลค่ารวม VAT <span className="req">*</span></span>}>
              <NumberInput value={total} onChange={setTotal} highlight/>
            </Field>
          </div>
          <div className="hint">กรอกมูลค่ารวม VAT แล้วระบบจะคำนวณอัตโนมัติ</div>
        </div>

        <AttachmentField full
          attachmentKey={form.attachmentKey}
          attachmentName={form.attachmentName}
          uploading={uploading}
          onUploaded={handleFileUpload}
          onRemove={handleRemoveFile}
        />
      </div>
    </Modal>
  );
}

function NumberInput({ value, onChange, disabled, highlight }) {
  const [focused, setFocused] = useState(false);
  const [draft, setDraft] = useState("");
  const num = Number(value) || 0;
  const display = focused
    ? draft
    : num.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });

  return (
    <div className={cls("num-input", disabled && "is-disabled", highlight && "is-highlight")}>
      <input
        type="text"
        inputMode="decimal"
        value={display}
        disabled={disabled}
        onFocus={(e) => {
          setFocused(true);
          // start draft from the unformatted number so the user can type from a clean state
          const v = num === 0 ? "" : String(num);
          setDraft(v);
          // select-all so typing replaces the value
          requestAnimationFrame(() => e.target.select());
        }}
        onChange={(e) => {
          // allow only digits + a single decimal point
          let raw = e.target.value.replace(/[^\d.]/g, "");
          const firstDot = raw.indexOf(".");
          if (firstDot !== -1) {
            raw = raw.slice(0, firstDot + 1) + raw.slice(firstDot + 1).replace(/\./g, "");
          }
          setDraft(raw);
          onChange(raw === "" ? 0 : parseFloat(raw) || 0);
        }}
        onBlur={() => setFocused(false)}
      />
      <div className="num-input-step">
        <button type="button" tabIndex={-1} disabled={disabled} onClick={() => onChange((+value || 0) + 1)}>▴</button>
        <button type="button" tabIndex={-1} disabled={disabled} onClick={() => onChange(Math.max(0, (+value || 0) - 1))}>▾</button>
      </div>
    </div>
  );
}

function AttachmentField({ attachmentKey, attachmentName, onUploaded, onRemove, uploading, full }) {
  const ref = useRef(null);
  const [drag, setDrag] = useState(false);

  if (attachmentKey) {
    return (
      <div className={cls("field", full && "field-full")}>
        <span className="field-l">แนบไฟล์ใบกำกับภาษี</span>
        <div className="file-drop is-on">
          <I.clip width="16" height="16"/>
          <span className="attach-name">{attachmentName}</span>
          <a href={`/api/uploads/${encodeURIComponent(attachmentKey)}`} target="_blank" rel="noreferrer"
             className="attach-view" onClick={e => e.stopPropagation()}>ดู</a>
          <button type="button" className="x-btn" onClick={onRemove}>
            <I.x width="12" height="12"/>
          </button>
        </div>
      </div>
    );
  }

  if (uploading) {
    return (
      <div className={cls("field", full && "field-full")}>
        <span className="field-l">แนบไฟล์ใบกำกับภาษี</span>
        <div className="file-drop"><span>กำลังอัปโหลด…</span></div>
      </div>
    );
  }

  return (
    <div className={cls("field", full && "field-full")}>
      <span className="field-l">แนบไฟล์ใบกำกับภาษี</span>
      <div
        className={cls("file-drop", drag && "is-drag")}
        onClick={() => ref.current.click()}
        onDragOver={(e) => { e.preventDefault(); setDrag(true); }}
        onDragLeave={() => setDrag(false)}
        onDrop={(e) => { e.preventDefault(); setDrag(false); const f = e.dataTransfer.files[0]; if (f) onUploaded(f); }}
      >
        <I.clip width="16" height="16"/>
        <span>เลือกไฟล์ (PDF, JPG, PNG)</span>
        <input ref={ref} type="file" accept=".pdf,.jpg,.jpeg,.png" hidden
               onChange={(e) => { const f = e.target.files[0]; if (f) { onUploaded(f); e.target.value = ""; } }}/>
      </div>
    </div>
  );
}

function SupplierModal({ open, onClose, initial, onSave }) {
  const [form, setForm] = useState(initial || { id: "s_"+Math.random().toString(36).slice(2,7), name: "", taxId: "" });
  useEffect(() => { setForm(initial || { id: "s_"+Math.random().toString(36).slice(2,7), name: "", taxId: "" }); }, [initial, open]);
  return (
    <Modal open={open} onClose={onClose}
      title={initial ? "แก้ไขผู้ขาย" : "เพิ่มผู้ขาย"}
      footer={
        <>
          <Btn variant="ghost" onClick={onClose}>ยกเลิก</Btn>
          <Btn variant="primary" onClick={() => { onSave(form); onClose(); toast("บันทึกผู้ขายแล้ว"); }}><I.check width="14" height="14"/> บันทึก</Btn>
        </>
      }
    >
      <div className="form-grid">
        <Field label="ชื่อผู้ขาย / ซัพพลายเออร์" full>
          <input value={form.name} onChange={e => setForm({...form, name: e.target.value})} placeholder="บริษัท…"/>
        </Field>
        <Field label="เลขผู้เสียภาษี" full>
          <input value={form.taxId} onChange={e => setForm({...form, taxId: e.target.value.replace(/\D/g,'').slice(0,13)})} placeholder="13 หลัก" className="mono"/>
        </Field>
      </div>
    </Modal>
  );
}

function Field({ label, full, children }) {
  return (
    <label className={cls("field", full && "field-full")}>
      <span className="field-l">{label}</span>
      {children}
    </label>
  );
}

/* --------------------------- TWEAKS --------------------------- */

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#2563eb",
  "radius": 12,
  "density": "comfortable",
  "preset": "clean"
}/*EDITMODE-END*/;

const ACCENT_OPTIONS = ["#2563eb", "#10b981", "#7c3aed", "#ea580c", "#0f172a", "#06b6d4"];

function TweaksAdapter() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  useEffect(() => {
    const r = document.documentElement;
    r.style.setProperty("--accent", t.accent);
    r.style.setProperty("--accent-soft", t.accent + "1f");
    r.style.setProperty("--accent-tint", t.accent + "0a");
    r.style.setProperty("--r-lg", t.radius + "px");
    r.style.setProperty("--r-md", Math.max(4, t.radius - 4) + "px");
    r.style.setProperty("--r-sm", Math.max(2, t.radius - 8) + "px");
    r.setAttribute("data-density", t.density);
    r.setAttribute("data-preset", t.preset);
  }, [t.accent, t.radius, t.density, t.preset]);

  return (
    <TweaksPanel title="Tweaks">
      <TweakSection label="Look & Feel"/>
      <TweakRadio label="Preset" value={t.preset} onChange={(v) => setTweak("preset", v)}
        options={[
          { value: "clean",   label: "Clean" },
          { value: "fintech", label: "Fintech" },
          { value: "soft",    label: "Soft" },
        ]}/>
      <TweakSection label="Accent"/>
      <TweakColor label="Color" value={t.accent} options={ACCENT_OPTIONS} onChange={(v) => setTweak("accent", v)}/>
      <TweakSection label="Shape & Density"/>
      <TweakSlider label="Radius" min={2} max={24} step={1} value={t.radius} onChange={(v) => setTweak("radius", v)} unit="px"/>
      <TweakRadio label="Density" value={t.density} onChange={(v) => setTweak("density", v)}
        options={[
          { value: "compact",     label: "Compact" },
          { value: "comfortable", label: "Default" },
          { value: "spacious",    label: "Spacious" },
        ]}/>
    </TweaksPanel>
  );
}

/* --------------------------- APP --------------------------- */

function App() {
  const [page, setPage] = useState(() => {
    const h = location.hash.replace("#", "");
    return NAV.some(n => n.id === h) ? h : "dashboard";
  });
  useEffect(() => { location.hash = page; }, [page]);

  const [store, baseDispatch] = useReducer(reducer, initialStore);
  const [bootState, setBootState] = useState("loading"); // loading | ready | error
  const [bootError, setBootError] = useState("");

  useEffect(() => {
    let cancelled = false;
    window.TaxFlowAPI.bootstrap()
      .then((data) => { if (!cancelled) { baseDispatch({ type: "hydrate", data }); setBootState("ready"); } })
      .catch((e) => { if (!cancelled) { setBootError(e.message || String(e)); setBootState("error"); } });
    return () => { cancelled = true; };
  }, []);

  // Wrap dispatch so each mutation also persists to D1 via the Pages Functions API.
  const dispatch = (action) => {
    baseDispatch(action);
    const api = window.TaxFlowAPI;
    const onErr = (e) => toast("บันทึกไม่สำเร็จ: " + e.message);
    switch (action.type) {
      case "addPurchase":     api.createPurchase(action.row).catch(onErr); break;
      case "updatePurchase":  api.updatePurchase(action.row).catch(onErr); break;
      case "deletePurchase":  api.deletePurchase(action.id).catch(onErr); break;
      case "addSale":         api.createSale(action.row).catch(onErr); break;
      case "updateSale":      api.updateSale(action.row).catch(onErr); break;
      case "deleteSale":      api.deleteSale(action.id).catch(onErr); break;
      case "addSupplier":     api.createSupplier(action.row).catch(onErr); break;
      case "updateSupplier":  api.updateSupplier(action.row).catch(onErr); break;
      case "deleteSupplier":  api.deleteSupplier(action.id).catch(onErr); break;
    }
  };

  const [dark, setDark] = useState(() => localStorage.getItem("taxflow-dark") === "1");
  useEffect(() => {
    document.documentElement.setAttribute("data-theme", dark ? "dark" : "light");
    localStorage.setItem("taxflow-dark", dark ? "1" : "0");
  }, [dark]);

  const [month, setMonth] = useState({ y: 2026, m: 5 });

  const [search, setSearch] = useState("");
  useEffect(() => { setSearch(""); }, [page]);

  const [purchaseModal, setPurchaseModal] = useState({ open: false, initial: null });
  const [saleModal, setSaleModal]         = useState({ open: false, initial: null });
  const [supplierModal, setSupplierModal] = useState({ open: false, initial: null });

  const onRestore = async (id, tab) => {
    try {
      const result = await window.TaxFlowAPI.restoreTrash(id);
      baseDispatch({ type: "restoreTrash", id, kind: result.kind, row: result.row });
      toast("กู้คืนแล้ว — ดูได้ที่หน้า" + (result.kind === "sale" ? "ขาย" : "ซื้อ"));
    } catch (e) {
      toast("กู้คืนไม่สำเร็จ: " + e.message);
    }
  };

  /* topbar config per page */
  const tb = useMemo(() => {
    const navItem = NAV.find(n => n.id === page);
    const title = navItem?.label || "";
    switch (page) {
      case "dashboard":
        return { title: "TaxFlow", subtitle: "Dashboard", searchable: false, addBtn: { label: "Add New", onClick: () => setPurchaseModal({open:true, initial:null}) } };
      case "purchases":
        return { title, subtitle: "ภาษีซื้อ", searchable: true, searchPlaceholder: "ค้นหาเลขที่ใบกำกับ ผู้ขาย…",
          addBtn: { label: "Add New", onClick: () => setPurchaseModal({open:true, initial:null}) } };
      case "sales":
        return { title, subtitle: "ภาษีขาย", searchable: true, searchPlaceholder: "ค้นหารายละเอียด ช่องทาง…",
          addBtn: { label: "Add New", onClick: () => setSaleModal({open:true, initial:null}) } };
      case "suppliers":
        return { title, subtitle: "ผู้ขาย / ซัพพลายเออร์", searchable: true, searchPlaceholder: "ค้นหาชื่อ หรือ เลขผู้เสียภาษี…",
          addBtn: { label: "Add New", onClick: () => setSupplierModal({open:true, initial:null}) } };
      case "vat":     return { title: "รายงาน ภ.พ.30", searchable: false };
      case "pl":      return { title: "กำไร/ขาดทุน",   searchable: false };
      case "audit":   return { title: "Audit Log",     searchable: true, searchPlaceholder: "ค้นหาประเภท รหัส ผู้ดำเนินการ…" };
      case "trash":   return { title: "ถังขยะ",         searchable: false };
      default: return { title };
    }
  }, [page]);

  if (bootState !== "ready") {
    return (
      <div className="boot-screen">
        <div className="boot-card">
          <div className="boot-logo">TaxFlow</div>
          {bootState === "loading" && <div className="boot-msg">กำลังโหลดข้อมูลจากฐานข้อมูล…</div>}
          {bootState === "error" && (
            <>
              <div className="boot-msg boot-err">เชื่อมต่อ API ไม่สำเร็จ</div>
              <div className="boot-sub">{bootError}</div>
              <button className="boot-btn" onClick={() => { window.TaxFlowAPI.clearKey(); location.reload(); }}>เปลี่ยน API key</button>
            </>
          )}
        </div>
      </div>
    );
  }

  return (
    <div className="app">
      <Sidebar page={page} setPage={setPage} dark={dark} setDark={setDark}/>

      <div className="main">
        <Topbar
          title={tb.title}
          subtitle={tb.subtitle}
          search={tb.searchable ? search : undefined}
          onSearch={setSearch}
          searchPlaceholder={tb.searchPlaceholder}
          right={
            <div className="row gap-8 ai-c">
              <IconBtn title="แจ้งเตือน"><I.bell width="18" height="18"/></IconBtn>
              {tb.addBtn && (
                <Btn variant="primary" onClick={tb.addBtn.onClick}>
                  <I.plus width="14" height="14"/> {tb.addBtn.label}
                </Btn>
              )}
            </div>
          }
        />

        <div className={cls("scroll-wrap", `page-key-${page}`)} key={page}>
          {page === "dashboard" && <ScreenDashboard store={store} month={month} setMonth={setMonth} setPage={setPage}/>}
          {page === "pl"        && <ScreenPL store={store} month={month} setMonth={setMonth}/>}
          {page === "vat" && (
  <ScreenVAT
    store={store}
    month={month}
    setMonth={setMonth}
  />
)}
          {page === "sales"     && <ScreenSales store={store} dispatch={dispatch} month={month} setMonth={setMonth}
                                                search={search} setSearch={setSearch}
                                                onAdd={() => setSaleModal({open:true, initial:null})}
                                                onEdit={(s) => setSaleModal({open:true, initial:s})}/>}
          {page === "purchases" && <ScreenPurchases store={store} dispatch={dispatch} month={month} setMonth={setMonth}
                                                    search={search} setSearch={setSearch}
                                                    onAdd={() => setPurchaseModal({open:true, initial:null})}
                                                    onEdit={(p) => setPurchaseModal({open:true, initial:p})}/>}
          {page === "suppliers" && <ScreenSuppliers store={store} dispatch={dispatch}
                                                    search={search} setSearch={setSearch}
                                                    onAdd={() => setSupplierModal({open:true, initial:null})}
                                                    onEdit={(s) => setSupplierModal({open:true, initial:s})}/>}
          {page === "audit"     && <ScreenAudit store={store} search={search} setSearch={setSearch}/>}
          {page === "trash"     && <ScreenTrash store={store} onRestore={onRestore}/>}
        </div>
      </div>

      <PurchaseModal open={purchaseModal.open} onClose={() => setPurchaseModal({open:false, initial:null})}
                     initial={purchaseModal.initial} suppliers={store.suppliers}
                     onSave={(row) => dispatch({type: purchaseModal.initial ? "updatePurchase" : "addPurchase", row})}
                     onAddSupplier={() => setSupplierModal({open:true, initial:null, fromPurchase:true})}/>
      <SaleModal open={saleModal.open} onClose={() => setSaleModal({open:false, initial:null})}
                     initial={saleModal.initial}
                     onSave={(row) => dispatch({type: saleModal.initial ? "updateSale" : "addSale", row})}/>
      <SupplierModal open={supplierModal.open} onClose={() => setSupplierModal({open:false, initial:null})}
                     initial={supplierModal.initial}
                     onSave={(row) => dispatch({type: supplierModal.initial ? "updateSupplier" : "addSupplier", row})}/>

      <TweaksAdapter/>
      <ToastHost/>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App/>);
