/* eslint-disable @typescript-eslint/no-explicit-any, react-hooks/set-state-in-effect, @next/next/no-location-assign-relative-destination */
"use client";
import { FormEvent, useEffect, useMemo, useRef, useState } from "react";
import { createPortal } from "react-dom";
import { useRouter } from "next/navigation";
import {
  BarChart3,
  BookOpen,
  ChevronDown,
  ChevronRight,
  CircleDollarSign,
  EllipsisVertical,
  FileText,
  LayoutDashboard,
  LogOut,
  Menu,
  Package,
  Plus,
  ReceiptText,
  RefreshCw,
  RotateCcw,
  Search,
  Settings,
  Users,
  X,
} from "lucide-react";

const TODAY = new Date().toISOString().slice(0, 10);
const cash = (v: any, c = "৳") =>
  `${c}${Number(v || 0).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
async function api(url: string, options?: RequestInit) {
  const r = await fetch(url, options);
  if (r.status === 401) {
    location.href = "/login";
    throw new Error("Unauthenticated");
  }
  const j = await r.json();
  if (!r.ok) throw new Error(j.message || "Request failed");
  return j;
}
async function post(body: any) {
  return api("/api/pos", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
}
function useData(type: string, extra = "", tick = 0) {
  const [data, setData] = useState<any>([]);
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    setLoading(true);
    api(`/api/pos?type=${type}${extra}`)
      .then(setData)
      .finally(() => setLoading(false));
  }, [type, extra, tick]);
  return { data, loading };
}
function Header({
  title,
  subtitle,
  action,
}: {
  title: string;
  subtitle?: string;
  action?: React.ReactNode;
}) {
  return (
    <div className="mb-5 flex flex-wrap items-center justify-between gap-3">
      <div>
        <h1 className="text-2xl font-bold tracking-tight">{title}</h1>
        {subtitle && <p className="mt-1 text-sm text-slate-500">{subtitle}</p>}
      </div>
      {action}
    </div>
  );
}
function Empty({ text = "Nothing here yet." }: { text?: string }) {
  return <div className="py-12 text-center text-sm text-slate-400">{text}</div>;
}
function Status({ value }: { value: string }) {
  return (
    <span
      className={`badge ${value === "active" ? "badge-active" : "badge-cancelled"}`}
    >
      {value}
    </span>
  );
}
function SaleActions({
  onView,
  onEdit,
  onDelete,
}: {
  onView: () => void;
  onEdit: () => void;
  onDelete: () => void;
}) {
  const [menu, setMenu] = useState<{
    top: number;
    left: number;
    up: boolean;
  } | null>(null);
  const buttonRef = useRef<HTMLButtonElement>(null);
  useEffect(() => {
    if (!menu) return;
    const close = () => setMenu(null);
    window.addEventListener("resize", close);
    window.addEventListener("scroll", close, true);
    document.addEventListener("pointerdown", close);
    return () => {
      window.removeEventListener("resize", close);
      window.removeEventListener("scroll", close, true);
      document.removeEventListener("pointerdown", close);
    };
  }, [menu]);
  function toggle(e: React.MouseEvent) {
    e.stopPropagation();
    if (menu) return setMenu(null);
    const r = buttonRef.current!.getBoundingClientRect();
    const up = window.innerHeight - r.bottom < 140;
    setMenu({
      top: up ? r.top - 5 : r.bottom + 5,
      left: Math.max(8, Math.min(r.right - 136, window.innerWidth - 144)),
      up,
    });
  }
  function run(fn: () => void) {
    setMenu(null);
    fn();
  }
  return (
    <>
      <button
        ref={buttonRef}
        onPointerDown={(e) => e.stopPropagation()}
        onClick={toggle}
        className="grid h-8 w-8 place-items-center rounded-lg border border-slate-200 bg-white text-slate-600 hover:bg-slate-50"
        aria-label="Sale actions"
        aria-expanded={Boolean(menu)}
      >
        <EllipsisVertical size={18} />
      </button>
      {menu &&
        createPortal(
          <div
            onPointerDown={(e) => e.stopPropagation()}
            className={`fixed z-[200] w-34 overflow-hidden rounded-lg border border-slate-200 bg-white py-1 text-sm shadow-xl ${menu.up ? "-translate-y-full" : ""}`}
            style={{ top: menu.top, left: menu.left }}
          >
            <button
              className="block w-full px-3 py-2 text-left text-slate-700 hover:bg-slate-50"
              onClick={() => run(onView)}
            >
              View
            </button>
            <button
              className="block w-full px-3 py-2 text-left text-blue-700 hover:bg-blue-50"
              onClick={() => run(onEdit)}
            >
              Edit
            </button>
            <button
              className="block w-full px-3 py-2 text-left text-red-600 hover:bg-red-50"
              onClick={() => run(onDelete)}
            >
              Delete
            </button>
          </div>,
          document.body,
        )}
    </>
  );
}
function ReturnActions({
  canEdit,
  onView,
  onEdit,
  onDelete,
}: {
  canEdit: boolean;
  onView: () => void;
  onEdit: () => void;
  onDelete: () => void;
}) {
  const [menu, setMenu] = useState<{
    top: number;
    left: number;
    up: boolean;
  } | null>(null);
  const ref = useRef<HTMLButtonElement>(null);
  useEffect(() => {
    if (!menu) return;
    const close = () => setMenu(null);
    document.addEventListener("pointerdown", close);
    window.addEventListener("scroll", close, true);
    return () => {
      document.removeEventListener("pointerdown", close);
      window.removeEventListener("scroll", close, true);
    };
  }, [menu]);
  function toggle(e: React.MouseEvent) {
    e.stopPropagation();
    if (menu) return setMenu(null);
    const r = ref.current!.getBoundingClientRect();
    const up = window.innerHeight - r.bottom < 140;
    setMenu({
      top: up ? r.top - 5 : r.bottom + 5,
      left: Math.max(8, Math.min(r.right - 136, window.innerWidth - 144)),
      up,
    });
  }
  function run(fn: () => void) {
    setMenu(null);
    fn();
  }
  return (
    <>
      <button
        ref={ref}
        onPointerDown={(e) => e.stopPropagation()}
        onClick={toggle}
        className="grid h-8 w-8 place-items-center rounded-lg border border-slate-200 bg-white text-slate-600 hover:bg-slate-50"
        aria-label="Return actions"
      >
        <EllipsisVertical size={18} />
      </button>
      {menu &&
        createPortal(
          <div
            onPointerDown={(e) => e.stopPropagation()}
            className={`fixed z-[200] w-34 overflow-hidden rounded-lg border border-slate-200 bg-white py-1 text-sm shadow-xl ${menu.up ? "-translate-y-full" : ""}`}
            style={{ top: menu.top, left: menu.left }}
          >
            <button
              className="block w-full px-3 py-2 text-left hover:bg-slate-50"
              onClick={() => run(onView)}
            >
              View
            </button>
            {canEdit && (
              <button
                className="block w-full px-3 py-2 text-left text-blue-700 hover:bg-blue-50"
                onClick={() => run(onEdit)}
              >
                Edit
              </button>
            )}
            <button
              className="block w-full px-3 py-2 text-left text-red-600 hover:bg-red-50"
              onClick={() => run(onDelete)}
            >
              Delete
            </button>
          </div>,
          document.body,
        )}
    </>
  );
}
function ProductActions({
  onEdit,
  onDelete,
}: {
  onEdit: () => void;
  onDelete: () => void;
}) {
  const [menu, setMenu] = useState<{
    top: number;
    left: number;
    up: boolean;
  } | null>(null);
  const ref = useRef<HTMLButtonElement>(null);
  useEffect(() => {
    if (!menu) return;
    const close = () => setMenu(null);
    document.addEventListener("pointerdown", close);
    window.addEventListener("scroll", close, true);
    return () => {
      document.removeEventListener("pointerdown", close);
      window.removeEventListener("scroll", close, true);
    };
  }, [menu]);
  function toggle(e: React.MouseEvent) {
    e.stopPropagation();
    if (menu) return setMenu(null);
    const r = ref.current!.getBoundingClientRect();
    const up = window.innerHeight - r.bottom < 110;
    setMenu({
      top: up ? r.top - 5 : r.bottom + 5,
      left: Math.max(8, Math.min(r.right - 136, window.innerWidth - 144)),
      up,
    });
  }
  function run(fn: () => void) {
    setMenu(null);
    fn();
  }
  return (
    <>
      <button
        ref={ref}
        onPointerDown={(e) => e.stopPropagation()}
        onClick={toggle}
        className="grid h-8 w-8 place-items-center rounded-lg border border-slate-200 bg-white text-slate-600 hover:bg-slate-50"
        aria-label="Product actions"
      >
        <EllipsisVertical size={18} />
      </button>
      {menu &&
        createPortal(
          <div
            onPointerDown={(e) => e.stopPropagation()}
            className={`fixed z-[200] w-34 overflow-hidden rounded-lg border border-slate-200 bg-white py-1 text-sm shadow-xl ${menu.up ? "-translate-y-full" : ""}`}
            style={{ top: menu.top, left: menu.left }}
          >
            <button
              className="block w-full px-3 py-2 text-left text-blue-700 hover:bg-blue-50"
              onClick={() => run(onEdit)}
            >
              Edit
            </button>
            <button
              className="block w-full px-3 py-2 text-left text-red-600 hover:bg-red-50"
              onClick={() => run(onDelete)}
            >
              Delete
            </button>
          </div>,
          document.body,
        )}
    </>
  );
}
function Modal({
  title,
  children,
  onClose,
  wide = false,
}: {
  title: string;
  children: React.ReactNode;
  onClose: () => void;
  wide?: boolean;
}) {
  return (
    <div className="modal-bg">
      <div className={`modal ${wide ? "!w-[min(1050px,100%)]" : ""}`}>
        <div className="no-print mb-5 flex items-center justify-between">
          <h2 className="text-lg font-bold">{title}</h2>
          <button
            onClick={onClose}
            className="rounded-lg p-2 hover:bg-slate-100"
          >
            <X size={19} />
          </button>
        </div>
        {children}
      </div>
    </div>
  );
}

const nav = [
  ["dashboard", "Dashboard", LayoutDashboard],
  ["sales", "Sales", ReceiptText],
  ["customers", "Customers", Users],
  ["products", "Products", Package],
  ["payments", "Payments", CircleDollarSign],
  ["returns", "Returns", RotateCcw],
  ["ledger", "Customer Ledger", BookOpen],
  ["settings", "Settings", Settings],
] as const;

export default function PosApp() {
  const router = useRouter();
  const [page, setPage] = useState("dashboard");
  const [mobile, setMobile] = useState(false);
  const [toast, setToast] = useState("");
  const [tick, setTick] = useState(0);
  const { data: businessSettings } = useData("settings", "", tick);
  const businessName = businessSettings?.business_name || "Lite POS";
  const notify = (s: string) => {
    setToast(s);
    setTimeout(() => setToast(""), 2500);
  };
  const refresh = () => setTick((x) => x + 1);
  async function logout() {
    await fetch("/api/auth/logout", { method: "POST" });
    router.push("/login");
  }
  const View =
    page === "dashboard"
      ? Dashboard
      : page === "sale"
        ? SaleForm
        : page === "sales"
          ? Sales
          : page === "customers"
            ? Customers
            : page === "products"
              ? Products
              : page === "payments"
                ? Payments
                : page === "returns"
                  ? Returns
                  : page === "ledger"
                    ? Ledger
                    : page === "sales-report"
                      ? Reports
                      : page === "product-return-report"
                        ? ProductReturnReport
                        : page === "customer-due-report"
                          ? CustomerDueReport
                          : page === "customer-payment-report"
                            ? CustomerPaymentReport
                            : SettingsView;
  return (
    <div className="min-h-screen md:flex">
      {toast && <div className="toast">{toast}</div>}
      <aside
        className={`no-print fixed inset-y-0 left-0 z-50 flex w-64 flex-col bg-[#152b28] text-white transition-transform md:sticky md:h-screen md:translate-x-0 ${mobile ? "translate-x-0" : "-translate-x-full"}`}
      >
        <div className="flex h-18 items-center gap-3 border-b border-white/10 px-5">
          <span className="grid h-9 w-9 place-items-center rounded-lg bg-[#43a88e]">
            <ReceiptText size={20} />
          </span>
          <div className="min-w-0">
            <b className="block truncate" title={businessName}>
              {businessName}
            </b>
            <p className="text-xs text-white/55">Sales made simple</p>
          </div>
          <button
            onClick={() => setMobile(false)}
            className="ml-auto md:hidden"
          >
            <X />
          </button>
        </div>
        <SidebarNav
          page={page}
          select={(id) => {
            setPage(id);
            setMobile(false);
          }}
        />
        <button
          onClick={logout}
          className="m-3 mt-1 flex shrink-0 items-center gap-3 rounded-lg border-t border-white/10 px-3 py-3 text-sm text-white/60 hover:bg-white/10 hover:text-white"
        >
          <LogOut size={18} />
          Log out
        </button>
      </aside>
      <main className="min-w-0 flex-1">
        <header className="no-print flex h-16 items-center border-b border-slate-200 bg-white px-4 md:px-7">
          <button className="mr-3 md:hidden" onClick={() => setMobile(true)}>
            <Menu />
          </button>
          <p className="truncate text-sm font-semibold" title={businessName}>
            {businessName}
          </p>
          <button
            onClick={refresh}
            className="ml-auto rounded-lg p-2 text-slate-500 hover:bg-slate-100"
            title="Refresh"
          >
            <RefreshCw size={18} />
          </button>
        </header>
        <div className="main-pad p-5 md:p-7">
          <View tick={tick} notify={notify} refresh={refresh} go={setPage} />
        </div>
      </main>
    </div>
  );
}

function SidebarNav({
  page,
  select,
}: {
  page: string;
  select: (id: string) => void;
}) {
  const reportPage = page.endsWith("-report");
  const [reportsOpen, setReportsOpen] = useState(reportPage);
  const [customerOpen, setCustomerOpen] = useState(
    page.startsWith("customer-") && reportPage,
  );
  const item = (id: string, label: string, Icon: any) => (
    <button
      key={id}
      onClick={() => select(id)}
      className={`flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-sm ${page === id ? "bg-white/13 text-white" : "text-white/65 hover:bg-white/7 hover:text-white"}`}
    >
      <Icon size={18} />
      {label}
      {page === id && <ChevronRight size={15} className="ml-auto" />}
    </button>
  );
  return (
    <nav className="min-h-0 flex-1 space-y-1 overflow-y-auto p-3">
      {nav.slice(0, -1).map(([id, label, Icon]) => item(id, label, Icon))}
      <button
        onClick={() => setReportsOpen((v) => !v)}
        className={`flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-sm ${reportPage ? "text-white" : "text-white/65 hover:bg-white/7 hover:text-white"}`}
      >
        <BarChart3 size={18} />
        Reports
        {reportsOpen ? (
          <ChevronDown size={15} className="ml-auto" />
        ) : (
          <ChevronRight size={15} className="ml-auto" />
        )}
      </button>
      {reportsOpen && (
        <div className="ml-5 space-y-1 border-l border-white/10 pl-2">
          <button
            onClick={() => select("sales-report")}
            className={`block w-full rounded-md px-3 py-2 text-left text-xs ${page === "sales-report" ? "bg-white/13 text-white" : "text-white/60 hover:text-white"}`}
          >
            Detailed Sales Report
          </button>
          <button
            onClick={() => select("product-return-report")}
            className={`block w-full rounded-md px-3 py-2 text-left text-xs ${page === "product-return-report" ? "bg-white/13 text-white" : "text-white/60 hover:text-white"}`}
          >
            Product Return Report
          </button>
          <button
            onClick={() => setCustomerOpen((v) => !v)}
            className="flex w-full items-center rounded-md px-3 py-2 text-left text-xs text-white/60 hover:text-white"
          >
            Customer Reports
            {customerOpen ? (
              <ChevronDown size={13} className="ml-auto" />
            ) : (
              <ChevronRight size={13} className="ml-auto" />
            )}
          </button>
          {customerOpen && (
            <div className="ml-3 space-y-1 border-l border-white/10 pl-2">
              <button
                onClick={() => select("customer-due-report")}
                className={`block w-full rounded-md px-2 py-2 text-left text-xs ${page === "customer-due-report" ? "bg-white/13 text-white" : "text-white/55 hover:text-white"}`}
              >
                Customer Due Report
              </button>
              <button
                onClick={() => select("customer-payment-report")}
                className={`block w-full rounded-md px-2 py-2 text-left text-xs ${page === "customer-payment-report" ? "bg-white/13 text-white" : "text-white/55 hover:text-white"}`}
              >
                Payment History
              </button>
            </div>
          )}
        </div>
      )}
      {item("settings", "Settings", Settings)}
    </nav>
  );
}

function Dashboard({ tick, go }: { tick: number; go: (s: string) => void }) {
  const { data, loading } = useData("dashboard", "", tick);
  if (loading) return <p>Loading…</p>;
  const m = data.metrics;
  const cards = [
    ["Today's sales", m.today_sales, "bg-emerald-50 text-emerald-700"],
    ["Net sales", m.today_net, "bg-blue-50 text-blue-700"],
    ["Return & refund", m.today_returns, "bg-red-50 text-red-700"],
    ["Collections", m.today_collections, "bg-violet-50 text-violet-700"],
    ["Total due", m.total_due, "bg-amber-50 text-amber-700"],
    ["Customer advance", m.total_advance, "bg-cyan-50 text-cyan-700"],
    ["Invoices", m.today_invoices, "bg-slate-100 text-slate-700"],
  ];
  return (
    <>
      <Header
        title="Dashboard"
        subtitle="Today's business at a glance"
        action={
          <button onClick={() => go("sale")} className="btn btn-primary">
            <Plus size={17} />
            New sale
          </button>
        }
      />
      <div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-3">
        {cards.map(([l, v, c]) => (
          <div className="card p-5" key={String(l)}>
            <p className="text-sm text-slate-500">{l}</p>
            <p className="mt-2 text-2xl font-bold">
              {l === "Invoices" ? v : cash(v)}
            </p>
            <span
              className={`mt-4 inline-block rounded-md px-2 py-1 text-xs ${c}`}
            >
              Today
            </span>
          </div>
        ))}
      </div>
      <div className="mt-5 grid gap-5 xl:grid-cols-3">
        <section className="card p-5 xl:col-span-2">
          <h2 className="mb-4 font-bold">Recent sales</h2>
          <div className="table-wrap">
            <table className="table">
              <thead>
                <tr>
                  <th>Invoice</th>
                  <th>Customer</th>
                  <th>Date</th>
                  <th>Status</th>
                  <th className="amount">Total</th>
                </tr>
              </thead>
              <tbody>
                {data.recent.map((x: any) => (
                  <tr key={x.id}>
                    <td className="font-semibold">{x.invoice_no}</td>
                    <td>{x.customer_name}</td>
                    <td>{x.sale_date}</td>
                    <td>
                      <Status value={x.status} />
                    </td>
                    <td className="amount">{cash(x.grand_total)}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </section>
        <section className="card p-5">
          <h2 className="mb-4 font-bold">Top products</h2>
          {data.top.length ? (
            data.top.map((x: any) => (
              <div
                key={x.product_name}
                className="flex items-center justify-between border-b border-slate-100 py-3 last:border-0"
              >
                <div>
                  <b className="text-sm">{x.product_name}</b>
                  <p className="text-xs text-slate-400">{x.quantity} sold</p>
                </div>
                <span className="text-sm font-bold">{cash(x.amount)}</span>
              </div>
            ))
          ) : (
            <Empty />
          )}
        </section>
      </div>
    </>
  );
}

function CustomerSelect({
  value,
  onChange,
  emptyLabel = "Walk-in Customer",
}: {
  value: any;
  onChange: (v: any) => void;
  emptyLabel?: string;
}) {
  const { data = [] } = useData("customers");
  const [open, setOpen] = useState(false);
  const [query, setQuery] = useState("");
  const wrap = useRef<HTMLDivElement>(null);
  const selected = data.find((c: any) => Number(c.id) === Number(value));
  const filtered = data.filter((c: any) =>
    `${c.code} ${c.name} ${c.phone || ""}`
      .toLowerCase()
      .includes(query.toLowerCase()),
  );
  useEffect(() => {
    const close = (e: PointerEvent) => {
      if (!wrap.current?.contains(e.target as Node)) {
        setOpen(false);
        setQuery("");
      }
    };
    document.addEventListener("pointerdown", close);
    return () => document.removeEventListener("pointerdown", close);
  }, []);
  return (
    <div ref={wrap} className="relative">
      <input
        className="field"
        value={
          open
            ? query
            : selected
              ? `${selected.code} — ${selected.name}`
              : emptyLabel
        }
        onFocus={() => {
          setOpen(true);
          setQuery("");
        }}
        onClick={() => {
          setOpen(true);
          setQuery("");
        }}
        onChange={(e) => {
          setQuery(e.target.value);
          setOpen(true);
        }}
        placeholder="Search customer"
      />
      {open && (
        <div className="absolute z-40 mt-1 max-h-56 w-full min-w-64 overflow-auto rounded-lg border border-slate-200 bg-white py-1 shadow-xl">
          <button
            type="button"
            className="sticky top-0 block w-full border-b bg-emerald-50 px-3 py-2 text-left text-sm font-semibold text-emerald-800 hover:bg-emerald-100"
            onClick={() => {
              onChange(null);
              setOpen(false);
              setQuery("");
            }}
          >
            {emptyLabel}
          </button>
          {filtered.map((c: any) => (
            <button
              type="button"
              key={c.id}
              className="block w-full px-3 py-2 text-left text-sm hover:bg-slate-50"
              onClick={() => {
                onChange(Number(c.id));
                setOpen(false);
                setQuery("");
              }}
            >
              <b>{c.name}</b>
              <span className="ml-2 text-xs text-slate-400">
                {c.code}
                {c.phone ? ` • ${c.phone}` : ""}
              </span>
            </button>
          ))}
          {!filtered.length && (
            <p className="px-3 py-3 text-sm text-slate-400">
              No customer found
            </p>
          )}
        </div>
      )}
    </div>
  );
}
function ReportProductSelect({
  value,
  onChange,
}: {
  value: any;
  onChange: (v: number) => void;
}) {
  const { data = [] } = useData("product-list");
  return (
    <select
      className="field"
      value={value || ""}
      onChange={(e) => onChange(Number(e.target.value) || 0)}
    >
      <option value="">All products</option>
      {data.map((p: any) => (
        <option key={p.id} value={p.id}>
          {p.name}
        </option>
      ))}
    </select>
  );
}
function ProductInput({
  line,
  onChange,
}: {
  line: any;
  onChange: (v: any) => void;
}) {
  const [q, setQ] = useState(line.name);
  const [items, setItems] = useState<any[]>([]);
  const [open, setOpen] = useState(false);
  const wrap = useRef<HTMLDivElement>(null);
  useEffect(() => {
    if (!open) {
      setItems([]);
      return;
    }
    const t = setTimeout(() => {
      if (q.trim())
        api(`/api/pos?type=products&q=${encodeURIComponent(q)}`).then(setItems);
      else setItems([]);
    }, 180);
    return () => clearTimeout(t);
  }, [q, open]);
  useEffect(() => {
    const close = (e: PointerEvent) => {
      if (!wrap.current?.contains(e.target as Node)) setOpen(false);
    };
    document.addEventListener("pointerdown", close);
    return () => document.removeEventListener("pointerdown", close);
  }, []);
  return (
    <div ref={wrap} className="relative">
      <input
        className="field min-w-52"
        value={q}
        placeholder="Type product name"
        onFocus={() => setOpen(true)}
        onClick={() => setOpen(true)}
        onChange={(e) => {
          setQ(e.target.value);
          setOpen(true);
          onChange({ ...line, name: e.target.value, product_id: null });
        }}
        required
      />
      {open && q && items.length > 0 && (
        <div className="absolute z-20 mt-1 max-h-44 w-full overflow-auto rounded-lg border bg-white shadow-xl">
          {items.map((p) => (
            <button
              type="button"
              key={p.id}
              className="block w-full px-3 py-2 text-left text-sm font-semibold hover:bg-emerald-50"
              onClick={() => {
                setQ(p.name);
                setOpen(false);
                onChange({ ...line, name: p.name, product_id: p.id });
              }}
            >
              {p.name}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}
function SaleForm({
  notify,
  go,
}: {
  notify: (s: string) => void;
  go: (s: string) => void;
}) {
  const [customer, setCustomer] = useState<any>(null);
  const [date, setDate] = useState(TODAY);
  const [buyer, setBuyer] = useState("");
  const [phone, setPhone] = useState("");
  const [discount, setDiscount] = useState(0);
  const [paid, setPaid] = useState(0);
  const [notes, setNotes] = useState("");
  const [busy, setBusy] = useState(false);
  const [lines, setLines] = useState<any[]>([
    { name: "", product_id: null, quantity: 1, unit_price: 0, discount: 0 },
  ]);
  const update = (i: number, v: any) =>
    setLines((x) => x.map((r, n) => (n === i ? v : r)));
  const subtotal = useMemo(
    () =>
      lines.reduce(
        (a, x) => a + Number(x.quantity || 0) * Number(x.unit_price || 0),
        0,
      ),
    [lines],
  );
  const lineDisc = useMemo(
    () => lines.reduce((a, x) => a + Number(x.discount || 0), 0),
    [lines],
  );
  const total = Math.max(0, subtotal - lineDisc - Number(discount || 0));
  useEffect(() => {
    if (!customer) setPaid(total);
  }, [customer, total]);
  async function submit(e: FormEvent) {
    e.preventDefault();
    setBusy(true);
    try {
      await post({
        action: "sale.save",
        sale_date: date,
        customer_id: customer,
        buyer_name: buyer,
        buyer_phone: phone,
        invoice_discount: discount,
        paid_amount: paid,
        notes,
        items: lines,
      });
      notify("Sale saved successfully");
      go("sales");
    } catch (e: any) {
      alert(e.message);
    } finally {
      setBusy(false);
    }
  }
  return (
    <form onSubmit={submit}>
      <Header
        title="New Sale"
        subtitle="Type a product name or select a previous suggestion"
      />
      <div className="grid gap-5 xl:grid-cols-[1fr_330px]">
        <section className="card p-5">
          <div className="grid gap-4 md:grid-cols-2">
            <div>
              <label className="label">Customer</label>
              <CustomerSelect value={customer} onChange={setCustomer} />
            </div>
            <div>
              <label className="label">Sale date</label>
              <input
                className="field"
                type="date"
                value={date}
                onChange={(e) => setDate(e.target.value)}
                required
              />
            </div>
            {!customer && (
              <>
                <div>
                  <label className="label">Buyer name (optional)</label>
                  <input
                    className="field"
                    value={buyer}
                    onChange={(e) => setBuyer(e.target.value)}
                  />
                </div>
                <div>
                  <label className="label">Buyer phone (optional)</label>
                  <input
                    className="field"
                    value={phone}
                    onChange={(e) => setPhone(e.target.value)}
                  />
                </div>
              </>
            )}
          </div>
          <div className="mt-5 table-wrap overflow-visible">
            <table className="table">
              <thead>
                <tr>
                  <th>Product</th>
                  <th className="w-24">Qty</th>
                  <th className="w-32">Price</th>
                  <th className="w-28">Discount</th>
                  <th className="amount">Total</th>
                  <th></th>
                </tr>
              </thead>
              <tbody>
                {lines.map((x, i) => (
                  <tr key={i}>
                    <td>
                      <ProductInput line={x} onChange={(v) => update(i, v)} />
                    </td>
                    <td>
                      <input
                        className="field"
                        type="number"
                        step="0.01"
                        min="0.01"
                        value={x.quantity}
                        onChange={(e) =>
                          update(i, { ...x, quantity: e.target.value })
                        }
                      />
                    </td>
                    <td>
                      <input
                        className="field"
                        type="number"
                        step="0.01"
                        min="0"
                        value={x.unit_price}
                        onChange={(e) =>
                          update(i, { ...x, unit_price: e.target.value })
                        }
                      />
                    </td>
                    <td>
                      <input
                        className="field"
                        type="number"
                        step="0.01"
                        min="0"
                        value={x.discount}
                        onChange={(e) =>
                          update(i, { ...x, discount: e.target.value })
                        }
                      />
                    </td>
                    <td className="amount font-semibold">
                      {cash(
                        Number(x.quantity) * Number(x.unit_price) -
                          Number(x.discount),
                      )}
                    </td>
                    <td>
                      <button
                        type="button"
                        disabled={lines.length === 1}
                        onClick={() =>
                          setLines((v) => v.filter((_, n) => n !== i))
                        }
                        className="text-red-500"
                      >
                        <X size={17} />
                      </button>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
          <button
            type="button"
            onClick={() =>
              setLines((v) => [
                ...v,
                {
                  name: "",
                  product_id: null,
                  quantity: 1,
                  unit_price: 0,
                  discount: 0,
                },
              ])
            }
            className="btn btn-soft mt-4"
          >
            <Plus size={16} />
            Add row
          </button>
        </section>
        <aside className="card h-fit p-5">
          <h2 className="mb-4 font-bold">Payment summary</h2>
          <div className="space-y-3 text-sm">
            <div className="flex justify-between">
              <span>Subtotal</span>
              <b>{cash(subtotal)}</b>
            </div>
            <div className="flex justify-between">
              <span>Line discount</span>
              <b>- {cash(lineDisc)}</b>
            </div>
            <div>
              <label className="label">Invoice discount</label>
              <input
                className="field text-right"
                type="number"
                min="0"
                step="0.01"
                value={discount}
                onChange={(e) => setDiscount(Number(e.target.value))}
              />
            </div>
            <div className="flex justify-between border-t pt-3 text-lg">
              <b>Grand total</b>
              <b>{cash(total)}</b>
            </div>
            <div>
              <label className="label">Paid amount (Cash)</label>
              <input
                className="field text-right"
                type="number"
                min="0"
                step="0.01"
                value={paid}
                onChange={(e) => setPaid(Number(e.target.value))}
              />
            </div>
            <div className="flex justify-between">
              <span>Due</span>
              <b className="text-amber-700">{cash(total - paid)}</b>
            </div>
            <div>
              <label className="label">Notes</label>
              <textarea
                className="field"
                rows={2}
                value={notes}
                onChange={(e) => setNotes(e.target.value)}
              />
            </div>
            <button disabled={busy} className="btn btn-primary mt-2 w-full">
              {busy ? "Saving…" : "Save sale"}
            </button>
          </div>
        </aside>
      </div>
    </form>
  );
}

function Sales({
  tick,
  notify,
  refresh,
  go,
}: {
  tick: number;
  notify: (s: string) => void;
  refresh: () => void;
  go: (s: string) => void;
}) {
  const [q, setQ] = useState("");
  const { data = [], loading } = useData(
    "sales",
    `&q=${encodeURIComponent(q)}`,
    tick,
  );
  const [view, setView] = useState<any>(null);
  const [edit, setEdit] = useState<number | null>(null);
  async function open(id: number) {
    setView(await api(`/api/pos?type=sale&id=${id}`));
  }
  async function remove(id: number) {
    if (
      !confirm(
        "Delete this sale permanently? This will also remove its returns and customer ledger effects.",
      )
    )
      return;
    try {
      await post({ action: "sale.delete", id });
      notify("Sale deleted");
      refresh();
    } catch (e: any) {
      alert(e.message);
    }
  }
  return (
    <>
      <Header
        title="Sales"
        subtitle="View, fully edit, print, or delete invoices"
        action={
          <div className="flex flex-wrap gap-2">
            <div className="relative">
              <Search
                size={16}
                className="absolute left-3 top-3 text-slate-400"
              />
              <input
                className="field !pl-9"
                placeholder="Search invoice/customer"
                value={q}
                onChange={(e) => setQ(e.target.value)}
              />
            </div>
            <button onClick={() => go("sale")} className="btn btn-primary">
              <Plus size={17} />
              Add New Sale
            </button>
          </div>
        }
      />
      <div className="card p-4">
        {loading ? (
          <p>Loading…</p>
        ) : (
          <div className="table-wrap">
            <table className="table">
              <thead>
                <tr>
                  <th>Invoice</th>
                  <th>Date</th>
                  <th>Customer</th>
                  <th>Status</th>
                  <th className="amount">Total</th>
                  <th className="amount">Paid</th>
                  <th className="amount">Due</th>
                  <th>Actions</th>
                </tr>
              </thead>
              <tbody>
                {data.map((x: any) => (
                  <tr key={x.id}>
                    <td className="font-semibold">{x.invoice_no}</td>
                    <td>{x.sale_date}</td>
                    <td>{x.customer_name || x.buyer_name || "Walk-in"}</td>
                    <td>
                      <Status value={x.status} />
                    </td>
                    <td className="amount">{cash(x.grand_total)}</td>
                    <td className="amount">{cash(x.paid_amount)}</td>
                    <td className="amount">{cash(x.due_amount)}</td>
                    <td>
                      <SaleActions
                        onView={() => open(x.id)}
                        onEdit={() => setEdit(x.id)}
                        onDelete={() => remove(x.id)}
                      />
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>
      {view && <Invoice data={view} onClose={() => setView(null)} />}{" "}
      {edit && (
        <EditSaleModal
          saleId={edit}
          onClose={() => setEdit(null)}
          done={() => {
            setEdit(null);
            notify("Sale updated");
            refresh();
          }}
        />
      )}
    </>
  );
}
function Invoice({ data, onClose }: { data: any; onClose: () => void }) {
  const s = data.sale;
  return (
    <Modal title="Invoice" onClose={onClose}>
      <div className="print-card">
        <div className="mb-6 text-center">
          <h1 className="text-2xl font-bold">Lite POS</h1>
          <p className="text-sm text-slate-500">Sales Invoice</p>
        </div>
        <div className="mb-5 grid grid-cols-2 gap-3 text-sm">
          <div>
            <b>Invoice:</b> {s.invoice_no}
            <br />
            <b>Customer:</b> {s.customer_name || s.buyer_name || "Walk-in"}
          </div>
          <div className="text-right">
            <b>Date:</b> {s.sale_date}
            <br />
            <b>Phone:</b> {s.customer_phone || s.buyer_phone || "—"}
          </div>
        </div>
        <table className="table">
          <thead>
            <tr>
              <th>Product</th>
              <th className="amount">Qty</th>
              <th className="amount">Price</th>
              <th className="amount">Discount</th>
              <th className="amount">Total</th>
            </tr>
          </thead>
          <tbody>
            {data.items.map((x: any) => (
              <tr key={x.id}>
                <td>{x.product_name}</td>
                <td className="amount">{x.quantity}</td>
                <td className="amount">{cash(x.unit_price)}</td>
                <td className="amount">{cash(x.discount)}</td>
                <td className="amount">{cash(x.total)}</td>
              </tr>
            ))}
          </tbody>
        </table>
        <div className="ml-auto mt-5 w-64 space-y-2 text-sm">
          <div className="flex justify-between">
            <span>Grand total</span>
            <b>{cash(s.grand_total)}</b>
          </div>
          <div className="flex justify-between">
            <span>Paid</span>
            <b>{cash(s.paid_amount)}</b>
          </div>
          <div className="flex justify-between border-t pt-2">
            <span>Due</span>
            <b>{cash(s.due_amount)}</b>
          </div>
        </div>
      </div>
      <button
        onClick={() => window.print()}
        className="no-print btn btn-primary mt-6 w-full"
      >
        Print invoice
      </button>
    </Modal>
  );
}
function EditSaleModal({
  saleId,
  onClose,
  done,
}: {
  saleId: number;
  onClose: () => void;
  done: () => void;
}) {
  const { data, loading } = useData("sale", `&id=${saleId}`);
  if (loading)
    return (
      <Modal title="Edit Sale" onClose={onClose}>
        <p>Loading…</p>
      </Modal>
    );
  return (
    <Modal title={`Edit ${data.sale.invoice_no}`} onClose={onClose} wide>
      <EditSaleForm data={data} done={done} />
    </Modal>
  );
}
function EditSaleForm({ data, done }: { data: any; done: () => void }) {
  const s = data.sale;
  const [customer, setCustomer] = useState<any>(s.customer_id);
  const [date, setDate] = useState(s.sale_date);
  const [buyer, setBuyer] = useState(s.buyer_name || "");
  const [phone, setPhone] = useState(s.buyer_phone || "");
  const [discount, setDiscount] = useState(Number(s.invoice_discount));
  const [paid, setPaid] = useState(Number(s.paid_amount));
  const [notes, setNotes] = useState(s.notes || "");
  const [busy, setBusy] = useState(false);
  const [lines, setLines] = useState<any[]>(
    data.items.map((x: any) => ({
      product_id: x.product_id,
      name: x.product_name,
      quantity: Number(x.quantity),
      unit_price: Number(x.unit_price),
      discount: Number(x.discount),
    })),
  );
  const update = (i: number, v: any) =>
    setLines((x) => x.map((r, n) => (n === i ? v : r)));
  const subtotal = useMemo(
    () =>
      lines.reduce(
        (a, x) => a + Number(x.quantity || 0) * Number(x.unit_price || 0),
        0,
      ),
    [lines],
  );
  const lineDisc = useMemo(
    () => lines.reduce((a, x) => a + Number(x.discount || 0), 0),
    [lines],
  );
  const total = Math.max(0, subtotal - lineDisc - Number(discount || 0));
  useEffect(() => {
    if (!customer) setPaid(total);
  }, [customer, total]);
  async function save(e: FormEvent) {
    e.preventDefault();
    setBusy(true);
    try {
      await post({
        action: "sale.update",
        id: s.id,
        sale_date: date,
        customer_id: customer,
        buyer_name: buyer,
        buyer_phone: phone,
        invoice_discount: discount,
        paid_amount: paid,
        notes,
        items: lines,
      });
      done();
    } catch (e: any) {
      alert(e.message);
    } finally {
      setBusy(false);
    }
  }
  return (
    <form onSubmit={save}>
      <div className="grid gap-4 md:grid-cols-2">
        <div>
          <label className="label">Customer</label>
          <CustomerSelect value={customer} onChange={setCustomer} />
        </div>
        <div>
          <label className="label">Sale date</label>
          <input
            className="field"
            type="date"
            value={date}
            onChange={(e) => setDate(e.target.value)}
            required
          />
        </div>
        {!customer && (
          <>
            <div>
              <label className="label">Buyer name</label>
              <input
                className="field"
                value={buyer}
                onChange={(e) => setBuyer(e.target.value)}
              />
            </div>
            <div>
              <label className="label">Buyer phone</label>
              <input
                className="field"
                value={phone}
                onChange={(e) => setPhone(e.target.value)}
              />
            </div>
          </>
        )}
      </div>
      <div className="mt-5 table-wrap overflow-visible">
        <table className="table">
          <thead>
            <tr>
              <th>Product</th>
              <th>Qty</th>
              <th>Price</th>
              <th>Discount</th>
              <th className="amount">Total</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {lines.map((x, i) => (
              <tr key={i}>
                <td>
                  <ProductInput line={x} onChange={(v) => update(i, v)} />
                </td>
                <td>
                  <input
                    className="field w-24"
                    type="number"
                    min="0.01"
                    step="0.01"
                    value={x.quantity}
                    onChange={(e) =>
                      update(i, { ...x, quantity: e.target.value })
                    }
                  />
                </td>
                <td>
                  <input
                    className="field w-28"
                    type="number"
                    min="0"
                    step="0.01"
                    value={x.unit_price}
                    onChange={(e) =>
                      update(i, { ...x, unit_price: e.target.value })
                    }
                  />
                </td>
                <td>
                  <input
                    className="field w-28"
                    type="number"
                    min="0"
                    step="0.01"
                    value={x.discount}
                    onChange={(e) =>
                      update(i, { ...x, discount: e.target.value })
                    }
                  />
                </td>
                <td className="amount font-semibold">
                  {cash(
                    Number(x.quantity) * Number(x.unit_price) -
                      Number(x.discount),
                  )}
                </td>
                <td>
                  <button
                    type="button"
                    disabled={lines.length === 1}
                    onClick={() => setLines((v) => v.filter((_, n) => n !== i))}
                    className="text-red-500"
                  >
                    <X size={17} />
                  </button>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      <button
        type="button"
        className="btn btn-soft mt-3"
        onClick={() =>
          setLines((v) => [
            ...v,
            {
              name: "",
              product_id: null,
              quantity: 1,
              unit_price: 0,
              discount: 0,
            },
          ])
        }
      >
        <Plus size={16} />
        Add row
      </button>
      <div className="mt-5 grid gap-4 border-t pt-5 md:grid-cols-4">
        <div>
          <label className="label">Invoice discount</label>
          <input
            className="field"
            type="number"
            min="0"
            step="0.01"
            value={discount}
            onChange={(e) => setDiscount(Number(e.target.value))}
          />
        </div>
        <div>
          <label className="label">Paid amount</label>
          <input
            className="field"
            type="number"
            min="0"
            step="0.01"
            value={paid}
            onChange={(e) => setPaid(Number(e.target.value))}
          />
        </div>
        <div>
          <label className="label">Grand total</label>
          <div className="field bg-slate-50 font-bold">{cash(total)}</div>
        </div>
        <div>
          <label className="label">Due</label>
          <div className="field bg-slate-50 font-bold">
            {cash(total - paid)}
          </div>
        </div>
      </div>
      <div className="mt-4">
        <label className="label">Notes</label>
        <textarea
          className="field"
          rows={2}
          value={notes}
          onChange={(e) => setNotes(e.target.value)}
        />
      </div>
      <button disabled={busy} className="btn btn-primary mt-5 w-full">
        {busy ? "Saving changes…" : "Save changes"}
      </button>
    </form>
  );
}

function Customers({
  tick,
  notify,
  refresh,
}: {
  tick: number;
  notify: (s: string) => void;
  refresh: () => void;
}) {
  const [q, setQ] = useState("");
  const { data = [], loading } = useData(
    "customers",
    `&q=${encodeURIComponent(q)}`,
    tick,
  );
  const [form, setForm] = useState<any>(null);
  async function save(e: FormEvent<HTMLFormElement>) {
    e.preventDefault();
    const o = Object.fromEntries(new FormData(e.currentTarget));
    try {
      await post({ action: "customer.save", ...o, id: form?.id || undefined });
      setForm(null);
      notify("Customer saved");
      refresh();
    } catch (e: any) {
      alert(e.message);
    }
  }
  return (
    <>
      <Header
        title="Customers"
        subtitle="Customer setup, opening balance, and current account position"
        action={
          <div className="flex gap-2">
            <div className="relative">
              <Search
                size={16}
                className="absolute left-3 top-3 text-slate-400"
              />
              <input
                className="field !pl-9"
                value={q}
                onChange={(e) => setQ(e.target.value)}
                placeholder="Search customers"
              />
            </div>
            <button className="btn btn-primary" onClick={() => setForm({})}>
              <Plus size={17} />
              Add
            </button>
          </div>
        }
      />
      <div className="card p-4">
        {loading ? (
          <p>Loading…</p>
        ) : (
          <div className="table-wrap">
            <table className="table">
              <thead>
                <tr>
                  <th>Code</th>
                  <th>Name</th>
                  <th>Phone</th>
                  <th>Zone / Area</th>
                  <th>Status</th>
                  <th className="amount">Balance</th>
                  <th></th>
                </tr>
              </thead>
              <tbody>
                {data.map((c: any) => (
                  <tr key={c.id}>
                    <td>{c.code}</td>
                    <td className="font-semibold">{c.name}</td>
                    <td>{c.phone || "—"}</td>
                    <td>
                      {[c.zone, c.area].filter(Boolean).join(" / ") || "—"}
                    </td>
                    <td>
                      <Status value={c.status} />
                    </td>
                    <td
                      className={`amount font-bold ${c.balance > 0 ? "text-amber-700" : c.balance < 0 ? "text-emerald-700" : ""}`}
                    >
                      {c.balance > 0
                        ? `Due ${cash(c.balance)}`
                        : c.balance < 0
                          ? `Advance ${cash(-c.balance)}`
                          : cash(0)}
                    </td>
                    <td>
                      <button
                        className="text-emerald-700"
                        onClick={() => setForm(c)}
                      >
                        Edit
                      </button>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>
      {form && (
        <Modal
          title={form.id ? "Edit customer" : "New customer"}
          onClose={() => setForm(null)}
          wide
        >
          <form onSubmit={save}>
            <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
              {[
                ["name", "Customer name", true],
                ["phone", "Phone"],
                ["email", "Email"],
                ["proprietor", "Proprietor / contact"],
                ["address", "Address"],
                ["nid", "NID"],
                ["bin", "BIN"],
                ["plant", "Plant / company"],
                ["industry", "Industry"],
                ["zone", "Zone"],
                ["area", "Area"],
                ["notes", "Notes"],
              ].map(([n, l, r]) => (
                <div key={String(n)}>
                  <label className="label">{l}</label>
                  <input
                    className="field"
                    name={String(n)}
                    defaultValue={form[n as string] || ""}
                    required={Boolean(r)}
                  />
                </div>
              ))}
              <div>
                <label className="label">Status</label>
                <select
                  className="field"
                  name="status"
                  defaultValue={form.status || "active"}
                >
                  <option>active</option>
                  <option>inactive</option>
                </select>
              </div>
              {!form.id && (
                <>
                  <div>
                    <label className="label">Opening amount</label>
                    <input
                      className="field"
                      name="opening_amount"
                      type="number"
                      step="0.01"
                      min="0"
                      defaultValue="0"
                    />
                  </div>
                  <div>
                    <label className="label">Opening type</label>
                    <select className="field" name="opening_type">
                      <option value="due">Due</option>
                      <option value="advance">Advance</option>
                    </select>
                  </div>
                  <div>
                    <label className="label">Opening date</label>
                    <input
                      className="field"
                      name="opening_date"
                      type="date"
                      defaultValue={TODAY}
                    />
                  </div>
                </>
              )}
            </div>
            <button className="btn btn-primary mt-5 w-full">
              Save customer
            </button>
          </form>
        </Modal>
      )}
    </>
  );
}

function Products({
  tick,
  notify,
  refresh,
}: {
  tick: number;
  notify: (s: string) => void;
  refresh: () => void;
}) {
  const [q, setQ] = useState("");
  const { data = [], loading } = useData(
    "product-list",
    `&q=${encodeURIComponent(q)}`,
    tick,
  );
  const [edit, setEdit] = useState<any>(null);
  async function save(e: FormEvent<HTMLFormElement>) {
    e.preventDefault();
    const name = String(new FormData(e.currentTarget).get("name") || "");
    try {
      await post({ action: "product.update", id: edit.id, name });
      setEdit(null);
      notify("Product updated");
      refresh();
    } catch (e: any) {
      alert(e.message);
    }
  }
  async function remove(p: any) {
    if (!confirm(`Delete product "${p.name}"?`)) return;
    try {
      await post({ action: "product.delete", id: p.id });
      notify("Product deleted");
      refresh();
    } catch (e: any) {
      alert(e.message);
    }
  }
  return (
    <>
      <Header
        title="Products"
        subtitle="Products created automatically from sales and direct returns"
        action={
          <div className="relative">
            <Search
              size={16}
              className="absolute left-3 top-3 text-slate-400"
            />
            <input
              className="field !pl-9"
              placeholder="Search products"
              value={q}
              onChange={(e) => setQ(e.target.value)}
            />
          </div>
        }
      />
      <div className="card p-4">
        {loading ? (
          <p>Loading…</p>
        ) : data.length ? (
          <div className="table-wrap">
            <table className="table">
              <thead>
                <tr>
                  <th>Product Name</th>
                  <th>Created</th>
                  <th>Last Used</th>
                  <th className="amount">Sales</th>
                  <th className="amount">Returns</th>
                  <th>Actions</th>
                </tr>
              </thead>
              <tbody>
                {data.map((p: any) => (
                  <tr key={p.id}>
                    <td className="font-semibold">{p.name}</td>
                    <td>{String(p.created_at).slice(0, 10)}</td>
                    <td>
                      {p.last_used_at
                        ? String(p.last_used_at).slice(0, 10)
                        : "—"}
                    </td>
                    <td className="amount">{p.sale_uses}</td>
                    <td className="amount">
                      {Number(p.sale_return_uses) +
                        Number(p.direct_return_uses)}
                    </td>
                    <td>
                      <ProductActions
                        onEdit={() => setEdit(p)}
                        onDelete={() => remove(p)}
                      />
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        ) : (
          <Empty text="No products in the database." />
        )}
      </div>
      {edit && (
        <Modal title="Edit Product" onClose={() => setEdit(null)}>
          <form onSubmit={save}>
            <label className="label">Product name</label>
            <input
              className="field"
              name="name"
              defaultValue={edit.name}
              autoFocus
              required
            />
            <p className="mt-2 text-xs text-slate-500">
              Renaming changes future suggestions. Existing invoice descriptions
              remain unchanged.
            </p>
            <button className="btn btn-primary mt-5 w-full">
              Save Changes
            </button>
          </form>
        </Modal>
      )}
    </>
  );
}

function Payments({
  tick,
  notify,
  refresh,
}: {
  tick: number;
  notify: (s: string) => void;
  refresh: () => void;
}) {
  const { data = [], loading } = useData("payments", "", tick);
  const [open, setOpen] = useState(false);
  const [view, setView] = useState<any>(null);
  const [edit, setEdit] = useState<any>(null);
  async function save(e: FormEvent<HTMLFormElement>) {
    e.preventDefault();
    try {
      await post({
        action: "payment.save",
        ...Object.fromEntries(new FormData(e.currentTarget)),
      });
      setOpen(false);
      notify("Payment received");
      refresh();
    } catch (e: any) {
      alert(e.message);
    }
  }
  async function update(e: FormEvent<HTMLFormElement>) {
    e.preventDefault();
    try {
      await post({
        action: "payment.update",
        id: edit.id,
        ...Object.fromEntries(new FormData(e.currentTarget)),
      });
      setEdit(null);
      notify("Payment updated");
      refresh();
    } catch (e: any) {
      alert(e.message);
    }
  }
  async function remove(x: any) {
    if (!confirm(`Delete payment ${x.receipt_no} permanently?`)) return;
    try {
      await post({ action: "payment.delete", id: x.id });
      notify("Payment deleted");
      refresh();
    } catch (e: any) {
      alert(e.message);
    }
  }
  return (
    <>
      <Header
        title="Customer Payments"
        subtitle="Payments reduce the customer's overall balance"
        action={
          <button onClick={() => setOpen(true)} className="btn btn-primary">
            <Plus size={17} />
            Receive payment
          </button>
        }
      />
      <div className="card p-4">
        {loading ? (
          <p>Loading…</p>
        ) : (
          <div className="table-wrap">
            <table className="table">
              <thead>
                <tr>
                  <th>Receipt</th>
                  <th>Date</th>
                  <th>Customer</th>
                  <th>Reference</th>
                  <th>Status</th>
                  <th className="amount">Amount</th>
                  <th>Actions</th>
                </tr>
              </thead>
              <tbody>
                {data.map((x: any) => (
                  <tr key={x.id}>
                    <td className="font-semibold">{x.receipt_no}</td>
                    <td>{x.payment_date}</td>
                    <td>{x.customer_name}</td>
                    <td>{x.reference || "—"}</td>
                    <td>
                      <Status value={x.status} />
                    </td>
                    <td className="amount font-bold">{cash(x.amount)}</td>
                    <td>
                      <ReturnActions
                        canEdit
                        onView={() => setView(x)}
                        onEdit={() => setEdit(x)}
                        onDelete={() => remove(x)}
                      />
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>
      {open && (
        <Modal title="Receive customer payment" onClose={() => setOpen(false)}>
          <form onSubmit={save} className="space-y-4">
            <div>
              <label className="label">Customer</label>
              <select className="field" name="customer_id" required>
                <option value="">Choose customer</option>
                <CustomerOptions />
              </select>
            </div>
            <div className="grid grid-cols-2 gap-4">
              <div>
                <label className="label">Date</label>
                <input
                  className="field"
                  name="payment_date"
                  type="date"
                  defaultValue={TODAY}
                />
              </div>
              <div>
                <label className="label">Cash amount</label>
                <input
                  className="field"
                  name="amount"
                  type="number"
                  min="0.01"
                  step="0.01"
                  required
                />
              </div>
            </div>
            <div>
              <label className="label">Reference</label>
              <input className="field" name="reference" />
            </div>
            <div>
              <label className="label">Notes</label>
              <textarea className="field" name="notes" />
            </div>
            <button className="btn btn-primary w-full">Save payment</button>
          </form>
        </Modal>
      )}
      {view && (
        <Modal title="Payment Receipt" onClose={() => setView(null)}>
          <div className="print-card text-sm">
            <div className="mb-6 text-center">
              <h2 className="text-xl font-bold">Lite POS</h2>
              <p className="text-slate-500">Customer Payment Receipt</p>
            </div>
            <div className="space-y-3">
              <div className="flex justify-between">
                <span>Receipt</span>
                <b>{view.receipt_no}</b>
              </div>
              <div className="flex justify-between">
                <span>Date</span>
                <b>{view.payment_date}</b>
              </div>
              <div className="flex justify-between">
                <span>Customer</span>
                <b>{view.customer_name}</b>
              </div>
              <div className="flex justify-between">
                <span>Reference</span>
                <b>{view.reference || "—"}</b>
              </div>
              <div className="flex justify-between border-t pt-3 text-lg">
                <span>Amount received</span>
                <b>{cash(view.amount)}</b>
              </div>
              {view.notes && (
                <p className="rounded-lg bg-slate-50 p-3">{view.notes}</p>
              )}
            </div>
          </div>
          <button
            onClick={() => window.print()}
            className="no-print btn btn-primary mt-5 w-full"
          >
            Print Receipt
          </button>
        </Modal>
      )}
      {edit && (
        <Modal title={`Edit ${edit.receipt_no}`} onClose={() => setEdit(null)}>
          <form onSubmit={update} className="space-y-4">
            <div>
              <label className="label">Customer</label>
              <select
                className="field"
                name="customer_id"
                defaultValue={edit.customer_id}
                required
              >
                <CustomerOptions />
              </select>
            </div>
            <div className="grid grid-cols-2 gap-4">
              <div>
                <label className="label">Date</label>
                <input
                  className="field"
                  name="payment_date"
                  type="date"
                  defaultValue={edit.payment_date}
                  required
                />
              </div>
              <div>
                <label className="label">Cash amount</label>
                <input
                  className="field"
                  name="amount"
                  type="number"
                  min="0.01"
                  step="0.01"
                  defaultValue={edit.amount}
                  required
                />
              </div>
            </div>
            <div>
              <label className="label">Reference</label>
              <input
                className="field"
                name="reference"
                defaultValue={edit.reference || ""}
              />
            </div>
            <div>
              <label className="label">Notes</label>
              <textarea
                className="field"
                name="notes"
                defaultValue={edit.notes || ""}
              />
            </div>
            <button className="btn btn-primary w-full">Save Changes</button>
          </form>
        </Modal>
      )}
    </>
  );
}
function CustomerOptions() {
  const { data = [] } = useData("customers");
  return (
    <>
      {data.map((c: any) => (
        <option key={c.id} value={c.id}>
          {c.code} — {c.name}
        </option>
      ))}
    </>
  );
}

function Returns({
  tick,
  notify,
  refresh,
}: {
  tick: number;
  notify: (s: string) => void;
  refresh: () => void;
}) {
  const { data = [], loading } = useData("returns", "", tick);
  const [open, setOpen] = useState(false);
  const [view, setView] = useState<any>(null);
  const [edit, setEdit] = useState<number | null>(null);
  async function remove(x: any) {
    if (!confirm("Delete this return permanently?")) return;
    try {
      await post({
        action: "return.delete",
        id: x.id,
        return_type: x.return_type,
      });
      notify("Return deleted");
      refresh();
    } catch (e: any) {
      alert(e.message);
    }
  }
  return (
    <>
      <Header
        title="Sales Returns"
        subtitle="Invoice returns and standalone cash refunds"
        action={
          <button onClick={() => setOpen(true)} className="btn btn-primary">
            <Plus size={17} />
            Add Direct Return
          </button>
        }
      />
      <div className="card p-4">
        {loading ? (
          <p>Loading…</p>
        ) : data.length ? (
          <div className="table-wrap">
            <table className="table">
              <thead>
                <tr>
                  <th>Return</th>
                  <th>Source</th>
                  <th>Date</th>
                  <th>Customer</th>
                  <th>Settlement</th>
                  <th>Status</th>
                  <th className="amount">Refund</th>
                  <th>Actions</th>
                </tr>
              </thead>
              <tbody>
                {data.map((x: any) => (
                  <tr key={`${x.return_type}-${x.id}`}>
                    <td className="font-semibold">{x.return_no}</td>
                    <td>{x.invoice_no}</td>
                    <td>{x.return_date}</td>
                    <td>{x.customer_name || "Walk-in"}</td>
                    <td>{x.settlement}</td>
                    <td>
                      <Status value={x.status} />
                    </td>
                    <td className="amount">{cash(x.total)}</td>
                    <td>
                      <ReturnActions
                        canEdit={x.return_type === "direct"}
                        onView={() => setView(x)}
                        onEdit={() => setEdit(x.id)}
                        onDelete={() => remove(x)}
                      />
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        ) : (
          <Empty text="No returns have been recorded." />
        )}
      </div>
      {open && (
        <DirectReturnModal
          onClose={() => setOpen(false)}
          done={() => {
            setOpen(false);
            notify("Direct return and cash refund saved");
            refresh();
          }}
        />
      )}
      {view && (
        <Modal title="Return Details" onClose={() => setView(null)}>
          <div className="grid grid-cols-2 gap-4 text-sm">
            <div>
              <p className="text-slate-500">Return number</p>
              <b>{view.return_no}</b>
            </div>
            <div>
              <p className="text-slate-500">Date</p>
              <b>{view.return_date}</b>
            </div>
            <div>
              <p className="text-slate-500">Customer</p>
              <b>{view.customer_name || "Walk-in"}</b>
            </div>
            <div>
              <p className="text-slate-500">Source</p>
              <b>{view.invoice_no}</b>
            </div>
            <div>
              <p className="text-slate-500">Reason</p>
              <b>{view.reason}</b>
            </div>
            <div>
              <p className="text-slate-500">Cash refund</p>
              <b className="text-red-700">{cash(view.total)}</b>
            </div>
          </div>
        </Modal>
      )}
      {edit && (
        <DirectReturnEditModal
          id={edit}
          onClose={() => setEdit(null)}
          done={() => {
            setEdit(null);
            notify("Direct return updated");
            refresh();
          }}
        />
      )}
    </>
  );
}
function DirectReturnModal({
  onClose,
  done,
}: {
  onClose: () => void;
  done: () => void;
}) {
  const [customer, setCustomer] = useState<any>(null);
  const [date, setDate] = useState(TODAY);
  const [reason, setReason] = useState("");
  const [notes, setNotes] = useState("");
  const [busy, setBusy] = useState(false);
  const [lines, setLines] = useState<any[]>([
    { name: "", product_id: null, quantity: 1, unit_price: 0 },
  ]);
  const update = (i: number, v: any) =>
    setLines((x) => x.map((r, n) => (n === i ? v : r)));
  const total = useMemo(
    () =>
      lines.reduce(
        (a, x) => a + Number(x.quantity || 0) * Number(x.unit_price || 0),
        0,
      ),
    [lines],
  );
  async function save(e: FormEvent) {
    e.preventDefault();
    setBusy(true);
    try {
      await post({
        action: "direct-return.save",
        return_date: date,
        customer_id: customer,
        reason,
        notes,
        items: lines,
      });
      done();
    } catch (e: any) {
      alert(e.message);
    } finally {
      setBusy(false);
    }
  }
  return (
    <Modal title="Add Direct Return" onClose={onClose} wide>
      <form onSubmit={save}>
        <div className="grid gap-4 md:grid-cols-3">
          <div>
            <label className="label">Customer (optional)</label>
            <CustomerSelect value={customer} onChange={setCustomer} />
          </div>
          <div>
            <label className="label">Return date</label>
            <input
              className="field"
              type="date"
              value={date}
              onChange={(e) => setDate(e.target.value)}
              required
            />
          </div>
          <div>
            <label className="label">Reason</label>
            <input
              className="field"
              value={reason}
              onChange={(e) => setReason(e.target.value)}
              placeholder="Reason for return"
              required
            />
          </div>
        </div>
        <div className="mt-5 table-wrap overflow-visible">
          <table className="table">
            <thead>
              <tr>
                <th>Product</th>
                <th>Quantity</th>
                <th>Refund price</th>
                <th className="amount">Refund total</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {lines.map((x, i) => (
                <tr key={i}>
                  <td>
                    <ProductInput line={x} onChange={(v) => update(i, v)} />
                  </td>
                  <td>
                    <input
                      className="field w-28"
                      type="number"
                      min="0.01"
                      step="0.01"
                      value={x.quantity}
                      onChange={(e) =>
                        update(i, { ...x, quantity: e.target.value })
                      }
                    />
                  </td>
                  <td>
                    <input
                      className="field w-32"
                      type="number"
                      min="0"
                      step="0.01"
                      value={x.unit_price}
                      onChange={(e) =>
                        update(i, { ...x, unit_price: e.target.value })
                      }
                    />
                  </td>
                  <td className="amount font-semibold">
                    {cash(Number(x.quantity) * Number(x.unit_price))}
                  </td>
                  <td>
                    <button
                      type="button"
                      disabled={lines.length === 1}
                      onClick={() =>
                        setLines((v) => v.filter((_, n) => n !== i))
                      }
                      className="text-red-500"
                    >
                      <X size={17} />
                    </button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div className="mt-4 flex flex-wrap items-start justify-between gap-4">
          <button
            type="button"
            onClick={() =>
              setLines((v) => [
                ...v,
                { name: "", product_id: null, quantity: 1, unit_price: 0 },
              ])
            }
            className="btn btn-soft"
          >
            <Plus size={16} />
            Add product
          </button>
          <div className="text-right">
            <p className="text-sm text-slate-500">Cash refund</p>
            <p className="text-2xl font-bold text-red-700">{cash(total)}</p>
          </div>
        </div>
        <div className="mt-4">
          <label className="label">Notes</label>
          <textarea
            className="field"
            rows={2}
            value={notes}
            onChange={(e) => setNotes(e.target.value)}
          />
        </div>
        <button disabled={busy} className="btn btn-primary mt-5 w-full">
          {busy ? "Saving refund…" : `Save & Refund ${cash(total)}`}
        </button>
      </form>
    </Modal>
  );
}
function DirectReturnEditModal({
  id,
  onClose,
  done,
}: {
  id: number;
  onClose: () => void;
  done: () => void;
}) {
  const { data, loading } = useData("direct-return", `&id=${id}`);
  if (loading)
    return (
      <Modal title="Edit Direct Return" onClose={onClose}>
        <p>Loading…</p>
      </Modal>
    );
  return <DirectReturnEditForm data={data} onClose={onClose} done={done} />;
}
function DirectReturnEditForm({
  data,
  onClose,
  done,
}: {
  data: any;
  onClose: () => void;
  done: () => void;
}) {
  const r = data.return;
  const [customer, setCustomer] = useState<any>(r.customer_id);
  const [date, setDate] = useState(r.return_date);
  const [reason, setReason] = useState(r.reason || "");
  const [notes, setNotes] = useState(r.notes || "");
  const [busy, setBusy] = useState(false);
  const [lines, setLines] = useState<any[]>(
    data.items.map((x: any) => ({
      name: x.product_name,
      product_id: x.product_id,
      quantity: Number(x.quantity),
      unit_price: Number(x.unit_price),
    })),
  );
  const update = (i: number, v: any) =>
    setLines((x) => x.map((a, n) => (n === i ? v : a)));
  const total = useMemo(
    () =>
      lines.reduce(
        (a, x) => a + Number(x.quantity || 0) * Number(x.unit_price || 0),
        0,
      ),
    [lines],
  );
  async function save(e: FormEvent) {
    e.preventDefault();
    setBusy(true);
    try {
      await post({
        action: "direct-return.update",
        id: r.id,
        return_date: date,
        customer_id: customer,
        reason,
        notes,
        items: lines,
      });
      done();
    } catch (e: any) {
      alert(e.message);
    } finally {
      setBusy(false);
    }
  }
  return (
    <Modal title={`Edit ${r.return_no}`} onClose={onClose} wide>
      <form onSubmit={save}>
        <div className="grid gap-4 md:grid-cols-3">
          <div>
            <label className="label">Customer (optional)</label>
            <CustomerSelect value={customer} onChange={setCustomer} />
          </div>
          <div>
            <label className="label">Return date</label>
            <input
              className="field"
              type="date"
              value={date}
              onChange={(e) => setDate(e.target.value)}
              required
            />
          </div>
          <div>
            <label className="label">Reason</label>
            <input
              className="field"
              value={reason}
              onChange={(e) => setReason(e.target.value)}
              required
            />
          </div>
        </div>
        <div className="mt-5 table-wrap overflow-visible">
          <table className="table">
            <thead>
              <tr>
                <th>Product</th>
                <th>Quantity</th>
                <th>Refund price</th>
                <th className="amount">Total</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {lines.map((x, i) => (
                <tr key={i}>
                  <td>
                    <ProductInput line={x} onChange={(v) => update(i, v)} />
                  </td>
                  <td>
                    <input
                      className="field w-28"
                      type="number"
                      min="0.01"
                      step="0.01"
                      value={x.quantity}
                      onChange={(e) =>
                        update(i, { ...x, quantity: e.target.value })
                      }
                    />
                  </td>
                  <td>
                    <input
                      className="field w-32"
                      type="number"
                      min="0"
                      step="0.01"
                      value={x.unit_price}
                      onChange={(e) =>
                        update(i, { ...x, unit_price: e.target.value })
                      }
                    />
                  </td>
                  <td className="amount font-semibold">
                    {cash(Number(x.quantity) * Number(x.unit_price))}
                  </td>
                  <td>
                    <button
                      type="button"
                      disabled={lines.length === 1}
                      onClick={() =>
                        setLines((v) => v.filter((_, n) => n !== i))
                      }
                      className="text-red-500"
                    >
                      <X size={17} />
                    </button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div className="mt-4 flex justify-between">
          <button
            type="button"
            className="btn btn-soft"
            onClick={() =>
              setLines((v) => [
                ...v,
                { name: "", product_id: null, quantity: 1, unit_price: 0 },
              ])
            }
          >
            <Plus size={16} />
            Add product
          </button>
          <div className="text-right">
            <p className="text-sm text-slate-500">Cash refund</p>
            <p className="text-2xl font-bold text-red-700">{cash(total)}</p>
          </div>
        </div>
        <div className="mt-4">
          <label className="label">Notes</label>
          <textarea
            className="field"
            rows={2}
            value={notes}
            onChange={(e) => setNotes(e.target.value)}
          />
        </div>
        <button disabled={busy} className="btn btn-primary mt-5 w-full">
          {busy ? "Saving…" : "Save Changes"}
        </button>
      </form>
    </Modal>
  );
}

function Ledger() {
  const { data: customers = [] } = useData("customers");
  const [id, setId] = useState(0);
  const extra = useMemo(
    () => (id ? `&customer_id=${id}` : "&customer_id=0"),
    [id],
  );
  const { data } = useData("ledger", extra);
  const selected = customers.find((c: any) => c.id === id);
  return (
    <>
      <Header
        title="Customer Ledger"
        subtitle="A complete running account history"
        action={
          <select
            className="field min-w-64"
            value={id}
            onChange={(e) => setId(Number(e.target.value))}
          >
            <option value="0">Select customer</option>
            {customers.map((c: any) => (
              <option value={c.id} key={c.id}>
                {c.code} — {c.name}
              </option>
            ))}
          </select>
        }
      />
      {id && data ? (
        <section className="card print-card p-5">
          <div className="mb-5 flex justify-between">
            <div>
              <h2 className="font-bold">{selected?.name}</h2>
              <p className="text-sm text-slate-500">{selected?.phone}</p>
            </div>
            <div className="text-right">
              <p className="text-xs text-slate-500">Closing balance</p>
              <b className="text-xl">
                {data.balance >= 0
                  ? `Due ${cash(data.balance)}`
                  : `Advance ${cash(-data.balance)}`}
              </b>
            </div>
          </div>
          <div className="table-wrap">
            <table className="table">
              <thead>
                <tr>
                  <th>Date</th>
                  <th>Reference</th>
                  <th>Type</th>
                  <th>Description</th>
                  <th className="amount">Debit</th>
                  <th className="amount">Credit</th>
                  <th className="amount">Balance</th>
                </tr>
              </thead>
              <tbody>
                {data.entries.map((x: any) => (
                  <tr key={x.id}>
                    <td>{x.txn_date}</td>
                    <td>{x.reference_no}</td>
                    <td>{x.type.replaceAll("_", " ")}</td>
                    <td>{x.description}</td>
                    <td className="amount">{cash(x.debit)}</td>
                    <td className="amount">{cash(x.credit)}</td>
                    <td className="amount font-bold">
                      {cash(x.running_balance)}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
          <button
            onClick={() => window.print()}
            className="no-print btn btn-soft mt-4"
          >
            Print ledger
          </button>
        </section>
      ) : (
        <div className="card">
          <Empty text="Select a customer to view the ledger." />
        </div>
      )}
    </>
  );
}

function Reports() {
  const [from, setFrom] = useState(TODAY.slice(0, 8) + "01");
  const [to, setTo] = useState(TODAY);
  const [customer, setCustomer] = useState(0);
  const [product, setProduct] = useState(0);
  const [search, setSearch] = useState("");
  const extra = useMemo(
    () =>
      `&from=${from}&to=${to}&customer_id=${customer}&product_id=${product}&search=${encodeURIComponent(search)}`,
    [from, to, customer, product, search],
  );
  const { data, loading } = useData("report", extra);
  function csv() {
    if (!data) return;
    const lines = [
      ["Product", "Quantity", "Gross", "Returns", "Net"],
      ...data.products.map((x: any) => [
        x.product_name,
        x.quantity,
        x.gross,
        x.returned,
        Number(x.gross) - Number(x.returned),
      ]),
    ];
    const blob = new Blob(
      [
        lines
          .map((r: any[]) =>
            r.map((v) => `"${String(v).replaceAll('"', '""')}"`).join(","),
          )
          .join("\n"),
      ],
      { type: "text/csv" },
    );
    const a = document.createElement("a");
    a.href = URL.createObjectURL(blob);
    a.download = `sales-report-${from}-${to}.csv`;
    a.click();
    URL.revokeObjectURL(a.href);
  }
  return (
    <>
      <Header
        title="Detailed Sales Report"
        subtitle="Filter sales by date, customer, product, or search term"
        action={
          <button onClick={csv} className="btn btn-soft">
            <FileText size={16} />
            Export CSV
          </button>
        }
      />
      <div className="card no-print mb-5 grid gap-3 p-4 sm:grid-cols-2 xl:grid-cols-5">
        <div>
          <label className="label">From date</label>
          <input
            className="field"
            type="date"
            value={from}
            onChange={(e) => setFrom(e.target.value)}
          />
        </div>
        <div>
          <label className="label">To date</label>
          <input
            className="field"
            type="date"
            value={to}
            onChange={(e) => setTo(e.target.value)}
          />
        </div>
        <div>
          <label className="label">Customer</label>
          <CustomerSelect
            value={customer}
            onChange={(v) => setCustomer(v || 0)}
            emptyLabel="All Customers"
          />
        </div>
        <div>
          <label className="label">Product</label>
          <ReportProductSelect value={product} onChange={setProduct} />
        </div>
        <div>
          <label className="label">Search</label>
          <input
            className="field"
            placeholder="Invoice, customer, product"
            value={search}
            onChange={(e) => setSearch(e.target.value)}
          />
        </div>
      </div>
      {loading ? (
        <p>Loading…</p>
      ) : (
        data && (
          <>
            <div className="mb-5 grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
              {[
                ["Gross sales", data.summary.gross],
                ["Discount", data.summary.discount],
                ["Returns", data.returns],
                [
                  "Net sales",
                  Number(data.summary.sales) - Number(data.returns),
                ],
              ].map(([l, v]) => (
                <div className="card p-5" key={String(l)}>
                  <p className="text-sm text-slate-500">{l}</p>
                  <p className="mt-2 text-2xl font-bold">{cash(v)}</p>
                </div>
              ))}
            </div>
            <section className="card print-card p-5">
              <div className="mb-4">
                <h2 className="font-bold">Product-wise sales</h2>
                <p className="text-sm text-slate-500">
                  {from} to {to}
                </p>
              </div>
              <div className="table-wrap">
                <table className="table">
                  <thead>
                    <tr>
                      <th>Product</th>
                      <th className="amount">Quantity</th>
                      <th className="amount">Gross</th>
                      <th className="amount">Returns</th>
                      <th className="amount">Net</th>
                    </tr>
                  </thead>
                  <tbody>
                    {data.products.map((x: any) => (
                      <tr key={x.product_name}>
                        <td className="font-semibold">{x.product_name}</td>
                        <td className="amount">{x.quantity}</td>
                        <td className="amount">{cash(x.gross)}</td>
                        <td className="amount">{cash(x.returned)}</td>
                        <td className="amount font-bold">
                          {cash(Number(x.gross) - Number(x.returned))}
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
              <button
                onClick={() => window.print()}
                className="no-print btn btn-soft mt-4"
              >
                Print report
              </button>
            </section>
          </>
        )
      )}
    </>
  );
}

function ProductReturnReport({ tick }: { tick: number }) {
  const { data = [], loading } = useData("returns", "", tick);
  const [from, setFrom] = useState(TODAY.slice(0, 8) + "01");
  const [to, setTo] = useState(TODAY);
  const [customer, setCustomer] = useState(0);
  const [search, setSearch] = useState("");
  const filtered = data.filter(
    (x: any) =>
      x.return_date >= from &&
      x.return_date <= to &&
      (!customer || Number(x.customer_id) === customer) &&
      (!search ||
        `${x.return_no} ${x.invoice_no} ${x.customer_name || ""} ${x.reason || ""}`
          .toLowerCase()
          .includes(search.toLowerCase())),
  );
  const total = filtered
    .filter((x: any) => x.status === "active")
    .reduce((a: number, x: any) => a + Number(x.total), 0);
  return (
    <>
      <Header
        title="Product Return Report"
        subtitle="Invoice-linked and direct product refunds"
        action={
          <button onClick={() => window.print()} className="btn btn-soft">
            <FileText size={16} />
            Print
          </button>
        }
      />
      <div className="card no-print mb-5 grid gap-3 p-4 sm:grid-cols-2 xl:grid-cols-4">
        <div>
          <label className="label">From date</label>
          <input
            className="field"
            type="date"
            value={from}
            onChange={(e) => setFrom(e.target.value)}
          />
        </div>
        <div>
          <label className="label">To date</label>
          <input
            className="field"
            type="date"
            value={to}
            onChange={(e) => setTo(e.target.value)}
          />
        </div>
        <div>
          <label className="label">Customer</label>
          <CustomerSelect
            value={customer}
            onChange={(v) => setCustomer(v || 0)}
            emptyLabel="All Customers"
          />
        </div>
        <div>
          <label className="label">Search</label>
          <input
            className="field"
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            placeholder="Return, invoice, reason"
          />
        </div>
      </div>
      <div className="mb-5 card p-5">
        <p className="text-sm text-slate-500">
          Filtered active returns and refunds
        </p>
        <p className="mt-2 text-2xl font-bold text-red-700">{cash(total)}</p>
      </div>
      <section className="card print-card p-4">
        {loading ? (
          <p>Loading…</p>
        ) : (
          <div className="table-wrap">
            <table className="table">
              <thead>
                <tr>
                  <th>Return</th>
                  <th>Type / Source</th>
                  <th>Date</th>
                  <th>Customer</th>
                  <th>Reason</th>
                  <th>Status</th>
                  <th className="amount">Amount</th>
                </tr>
              </thead>
              <tbody>
                {filtered.map((x: any) => (
                  <tr key={`${x.return_type}-${x.id}`}>
                    <td className="font-semibold">{x.return_no}</td>
                    <td>{x.invoice_no}</td>
                    <td>{x.return_date}</td>
                    <td>{x.customer_name || "Walk-in"}</td>
                    <td>{x.reason || "—"}</td>
                    <td>
                      <Status value={x.status} />
                    </td>
                    <td className="amount">{cash(x.total)}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </section>
    </>
  );
}

function CustomerDueReport({ tick }: { tick: number }) {
  const { data = [], loading } = useData("customers", "", tick);
  const [customer, setCustomer] = useState(0);
  const [min, setMin] = useState(0);
  const [max, setMax] = useState(0);
  const due = data.filter(
    (x: any) =>
      Number(x.balance) > 0 &&
      Number(x.balance) >= min &&
      (!max || Number(x.balance) <= max) &&
      (!customer || Number(x.id) === customer),
  );
  const total = due.reduce((a: number, x: any) => a + Number(x.balance), 0);
  return (
    <>
      <Header
        title="Customer Due Report"
        subtitle="Customers with an outstanding balance"
        action={
          <button onClick={() => window.print()} className="btn btn-soft">
            <FileText size={16} />
            Print
          </button>
        }
      />
      <div className="card no-print mb-5 grid gap-3 p-4 sm:grid-cols-3">
        <div>
          <label className="label">Customer</label>
          <CustomerSelect
            value={customer}
            onChange={(v) => setCustomer(v || 0)}
            emptyLabel="All Customers"
          />
        </div>
        <div>
          <label className="label">Minimum due</label>
          <input
            className="field"
            type="number"
            min="0"
            value={min}
            onChange={(e) => setMin(Number(e.target.value))}
          />
        </div>
        <div>
          <label className="label">Maximum due (0 = any)</label>
          <input
            className="field"
            type="number"
            min="0"
            value={max}
            onChange={(e) => setMax(Number(e.target.value))}
          />
        </div>
      </div>
      <div className="mb-5 card p-5">
        <p className="text-sm text-slate-500">Filtered customer due</p>
        <p className="mt-2 text-2xl font-bold text-amber-700">{cash(total)}</p>
      </div>
      <section className="card print-card p-4">
        {loading ? (
          <p>Loading…</p>
        ) : due.length ? (
          <div className="table-wrap">
            <table className="table">
              <thead>
                <tr>
                  <th>Code</th>
                  <th>Customer</th>
                  <th>Phone</th>
                  <th>Zone / Area</th>
                  <th className="amount">Due</th>
                </tr>
              </thead>
              <tbody>
                {due.map((x: any) => (
                  <tr key={x.id}>
                    <td>{x.code}</td>
                    <td className="font-semibold">{x.name}</td>
                    <td>{x.phone || "—"}</td>
                    <td>
                      {[x.zone, x.area].filter(Boolean).join(" / ") || "—"}
                    </td>
                    <td className="amount font-bold text-amber-700">
                      {cash(x.balance)}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        ) : (
          <Empty text="No customer dues match these filters." />
        )}
      </section>
    </>
  );
}

function CustomerPaymentReport({ tick }: { tick: number }) {
  const { data = [], loading } = useData("payments", "", tick);
  const [from, setFrom] = useState(TODAY.slice(0, 8) + "01");
  const [to, setTo] = useState(TODAY);
  const [customer, setCustomer] = useState(0);
  const [search, setSearch] = useState("");
  const filtered = data.filter(
    (x: any) =>
      x.payment_date >= from &&
      x.payment_date <= to &&
      (!customer || Number(x.customer_id) === customer) &&
      (!search ||
        `${x.receipt_no} ${x.customer_name} ${x.reference || ""} ${x.notes || ""}`
          .toLowerCase()
          .includes(search.toLowerCase())),
  );
  const total = filtered
    .filter((x: any) => x.status === "active")
    .reduce((a: number, x: any) => a + Number(x.amount), 0);
  return (
    <>
      <Header
        title="Customer Payment History"
        subtitle="Complete customer collection history"
        action={
          <button onClick={() => window.print()} className="btn btn-soft">
            <FileText size={16} />
            Print
          </button>
        }
      />
      <div className="card no-print mb-5 grid gap-3 p-4 sm:grid-cols-2 xl:grid-cols-4">
        <div>
          <label className="label">From date</label>
          <input
            className="field"
            type="date"
            value={from}
            onChange={(e) => setFrom(e.target.value)}
          />
        </div>
        <div>
          <label className="label">To date</label>
          <input
            className="field"
            type="date"
            value={to}
            onChange={(e) => setTo(e.target.value)}
          />
        </div>
        <div>
          <label className="label">Customer</label>
          <CustomerSelect
            value={customer}
            onChange={(v) => setCustomer(v || 0)}
            emptyLabel="All Customers"
          />
        </div>
        <div>
          <label className="label">Search</label>
          <input
            className="field"
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            placeholder="Receipt, customer, reference"
          />
        </div>
      </div>
      <div className="mb-5 card p-5">
        <p className="text-sm text-slate-500">Filtered active collections</p>
        <p className="mt-2 text-2xl font-bold text-emerald-700">
          {cash(total)}
        </p>
      </div>
      <section className="card print-card p-4">
        {loading ? (
          <p>Loading…</p>
        ) : (
          <div className="table-wrap">
            <table className="table">
              <thead>
                <tr>
                  <th>Receipt</th>
                  <th>Date</th>
                  <th>Customer</th>
                  <th>Reference</th>
                  <th>Notes</th>
                  <th>Status</th>
                  <th className="amount">Amount</th>
                </tr>
              </thead>
              <tbody>
                {filtered.map((x: any) => (
                  <tr key={x.id}>
                    <td className="font-semibold">{x.receipt_no}</td>
                    <td>{x.payment_date}</td>
                    <td>{x.customer_name}</td>
                    <td>{x.reference || "—"}</td>
                    <td>{x.notes || "—"}</td>
                    <td>
                      <Status value={x.status} />
                    </td>
                    <td className="amount font-bold">{cash(x.amount)}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </section>
    </>
  );
}

function SettingsView({
  notify,
  refresh,
}: {
  notify: (s: string) => void;
  refresh: () => void;
}) {
  const { data, loading } = useData("settings");
  const [busy, setBusy] = useState(false);
  async function save(e: FormEvent<HTMLFormElement>) {
    e.preventDefault();
    setBusy(true);
    try {
      await post({
        action: "settings.save",
        ...Object.fromEntries(new FormData(e.currentTarget)),
      });
      refresh();
      notify("Settings saved");
    } finally {
      setBusy(false);
    }
  }
  if (loading) return <p>Loading…</p>;
  return (
    <>
      <Header
        title="Business Settings"
        subtitle="Invoice identity and print preferences"
      />
      <form onSubmit={save} className="card max-w-3xl p-5">
        <div className="grid gap-4 sm:grid-cols-2">
          {[
            ["business_name", "Business name"],
            ["phone", "Phone"],
            ["email", "Email"],
            ["address", "Address"],
            ["currency", "Currency symbol"],
            ["invoice_footer", "Invoice footer"],
          ].map(([n, l]) => (
            <div key={n}>
              <label className="label">{l}</label>
              <input className="field" name={n} defaultValue={data[n] || ""} />
            </div>
          ))}
          <div>
            <label className="label">Default invoice format</label>
            <select
              className="field"
              name="invoice_format"
              defaultValue={data.invoice_format}
            >
              <option value="thermal">Thermal</option>
              <option value="a4">A4</option>
            </select>
          </div>
          <div>
            <label className="label">Thermal width</label>
            <select
              className="field"
              name="thermal_width"
              defaultValue={data.thermal_width}
            >
              <option>80mm</option>
              <option>58mm</option>
            </select>
          </div>
        </div>
        <button disabled={busy} className="btn btn-primary mt-5">
          {busy ? "Saving…" : "Save settings"}
        </button>
      </form>
    </>
  );
}
