/**
 * API Hooks — wraps fetch calls with React state + loading/error handling.
 * All hooks return { data, loading, error, refetch }.
 * data is always the meaningful array or object (never the raw { count, items } envelope).
 */

function _useApi(fetchFn, deps = []) {
  const [data, setData]       = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [error, setError]     = React.useState(null);
  const [tick, setTick]       = React.useState(0);
  const refetch = () => setTick((t) => t + 1);

  React.useEffect(() => {
    let cancelled = false;
    setLoading(true);
    setError(null);
    fetchFn()
      .then((result) => { if (!cancelled) setData(result); })
      .catch((err)   => { if (!cancelled) setError(err.message || 'Request failed'); })
      .finally(()    => { if (!cancelled) setLoading(false); });
    return () => { cancelled = true; };
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [...deps, tick]);

  return { data, loading, error, refetch };
}

// Debounce a fast-changing value (search box) so we only hit the API on pause.
function useDebounced(value, delay = 350) {
  const [v, setV] = React.useState(value);
  React.useEffect(() => {
    const t = setTimeout(() => setV(value), delay);
    return () => clearTimeout(t);
  }, [value, delay]);
  return v;
}

/**
 * usePagedList — server-side pagination for the web tables.
 * fetchPage(page) resolves to { items, total, summary? }. Returns the
 * accumulated items plus loadMore()/refetch(). Guards against out-of-order
 * responses and duplicate load-more calls.
 */
function usePagedList(fetchPage, deps = []) {
  const [items, setItems]     = React.useState([]);
  const [total, setTotal]     = React.useState(0);
  const [summary, setSummary] = React.useState(null);
  const [page, setPage]       = React.useState(1);
  const [loading, setLoading] = React.useState(true);
  const [error, setError]     = React.useState(null);
  const [more, setMore]       = React.useState(false);
  const [tick, setTick]       = React.useState(0);
  const refetch = () => setTick((t) => t + 1);
  const reqRef  = React.useRef(0);
  const busyRef = React.useRef(false);

  React.useEffect(() => {
    const rid = ++reqRef.current;
    busyRef.current = false;
    setLoading(true);
    setError(null);
    Promise.resolve(fetchPage(1))
      .then((r) => {
        if (rid !== reqRef.current) return;
        setItems(r.items || []);
        setTotal(r.total || 0);
        if (r.summary !== undefined && r.summary !== null) setSummary(r.summary);
        setPage(1);
      })
      .catch((e) => { if (rid === reqRef.current) { setItems([]); setTotal(0); setError(e.message || 'Request failed'); } })
      .finally(() => { if (rid === reqRef.current) setLoading(false); });
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [...deps, tick]);

  const hasMore = items.length < total;

  const loadMore = () => {
    if (busyRef.current || loading || !hasMore) return;
    const rid = reqRef.current;
    const next = page + 1;
    busyRef.current = true;
    setMore(true);
    Promise.resolve(fetchPage(next))
      .then((r) => {
        if (rid !== reqRef.current) return;
        setItems((prev) => [...prev, ...(r.items || [])]);
        setPage(next);
      })
      .finally(() => { busyRef.current = false; if (rid === reqRef.current) setMore(false); });
  };

  return { items, total, summary, loading, error, more, hasMore, loadMore, refetch };
}

// ── Dashboard ───────────────────────────────────────────────────
function useDashboard(filters = {}) {
  const key = JSON.stringify(filters);
  const h = _useApi(() => api.getDashboard(filters), [key]);
  return { ...h, data: h.data || {} };
}

// ── Branches ────────────────────────────────────────────────────
function useBranches() {
  const h = _useApi(() => api.getBranches(), []);
  return { ...h, data: h.data ? h.data.branches : [] };
}

// ── Customers ───────────────────────────────────────────────────
function useCustomers(filters = {}) {
  const key = JSON.stringify(filters);
  const h = _useApi(() => api.getCustomers(filters), [key]);
  return { ...h, data: h.data ? h.data.customers : [] };
}

// ── Products ────────────────────────────────────────────────────
function useProducts(filters = {}) {
  const key = JSON.stringify(filters);
  const h = _useApi(() => api.getProducts(filters), [key]);
  return { ...h, data: h.data ? h.data.products : [] };
}

// ── Invoices ────────────────────────────────────────────────────
function useInvoices(filters = {}) {
  const key = JSON.stringify(filters);
  const h = _useApi(() => api.getInvoices(filters), [key]);
  return { ...h, data: h.data ? h.data.invoices : [] };
}

// ── Quotations ──────────────────────────────────────────────────
function useQuotations(filters = {}) {
  const key = JSON.stringify(filters);
  const h = _useApi(() => api.getQuotations(filters), [key]);
  const raw = h.data ? h.data.quotations : [];
  // Map DB columns -> the shape the quotations UI + DATA.quote* helpers expect
  const mapItem = (it) => ({
    ...it,
    desc:       it.desc ?? it.description ?? it.name ?? '',
    type:       it.type || 'Machine',
    fulfilment: it.fulfilment || 'Sale',
    qty:        Number(it.qty ?? it.quantity ?? 1),
    rate:       Number(it.rate ?? it.unit_price ?? 0),
    deposit:    Number(it.deposit || 0),
    plan:       it.plan || null,
    warranty:   it.warranty || '',
    serialReq:  it.serialReq != null ? it.serialReq : !!it.serial_required,
  });
  const data = raw.map(q => ({
    ...q,
    no:       q.no       || q.quotation_number || '',
    cust:     q.cust     || q.customer_name  || '',
    rep:      q.rep      || q.user_name      || '',
    doctor:   q.doctor   || q.doctor_name    || '—',
    validity: q.validity || q.validity_date  || '',
    date:     q.date     || (q.created_at ? String(q.created_at).slice(0, 10) : ''),
    items: (q.items && q.items.length ? q.items
            : (() => { try { return JSON.parse(q.items_json || '[]'); } catch { return []; } })()).map(mapItem),
  }));
  return { ...h, data };
}

// ── Rentals ─────────────────────────────────────────────────────
function useRentals(filters = {}) {
  const key = JSON.stringify(filters);
  const h = _useApi(() => api.getRentals(filters), [key]);
  return { ...h, data: h.data ? h.data.rentals : [] };
}

// ── Payments ────────────────────────────────────────────────────
function usePayments(filters = {}) {
  const key = JSON.stringify(filters);
  const h = _useApi(() => api.getPayments(filters), [key]);
  return { ...h, data: h.data ? h.data.payments : [] };
}

// ── Workshop Jobs ────────────────────────────────────────────────
function useWorkshopJobs(filters = {}) {
  const key = JSON.stringify(filters);
  const h = _useApi(() => api.getWorkshopJobs(filters), [key]);
  return { ...h, data: h.data ? h.data.jobs : [] };
}

// ── Inventory ────────────────────────────────────────────────────
function useInventory(filters = {}) {
  const key = JSON.stringify(filters);
  const h = _useApi(() => api.getInventory(filters), [key]);
  return { ...h, data: h.data ? h.data.inventory : [] };
}

// ── Stock Moves ──────────────────────────────────────────────────
function useStockMoves(filters = {}) {
  const key = JSON.stringify(filters);
  const h = _useApi(() => api.getStockMoves(filters), [key]);
  return { ...h, data: h.data ? h.data.moves : [] };
}

// ── Users ────────────────────────────────────────────────────────
function useUsers() {
  const h = _useApi(() => api.getUsers(), []);
  return { ...h, data: h.data ? h.data.users : [] };
}

// ── Invites ──────────────────────────────────────────────────────
function useInvites() {
  const h = _useApi(() => api.getInvites(), []);
  return { ...h, data: h.data ? h.data.invites : [] };
}

// ── Notifications ────────────────────────────────────────────────
function useNotifications() {
  const h = _useApi(() => api.getNotifications(), []);
  return { ...h, data: h.data ? h.data.notifications : [] };
}

// ── Doctors ──────────────────────────────────────────────────────
function useDoctors(filters = {}) {
  const key = JSON.stringify(filters);
  const h = _useApi(() => api.getDoctors(filters), [key]);
  return { ...h, data: h.data ? h.data.doctors : [] };
}

// ── Companies ────────────────────────────────────────────────────
function useCompanies() {
  const h = _useApi(() => api.getCompanies(), []);
  return { ...h, data: h.data ? h.data.companies : [] };
}

// ── Opex ─────────────────────────────────────────────────────────
function useOpex(filters = {}) {
  const key = JSON.stringify(filters);
  const h = _useApi(() => api.getOpex(filters), [key]);
  return { ...h, data: h.data ? h.data.entries : [] };
}

// ── Notification Channels ────────────────────────────────────────
function useNotificationChannels() {
  const h = _useApi(() => api.getNotificationChannels(), []);
  return { ...h, data: h.data ? h.data.channels : [], refetch: h.refetch };
}

// ── Extended Reports ─────────────────────────────────────────────
function useMonthlySales(filters = {}) {
  const key = JSON.stringify(filters);
  const h = _useApi(() => api.getMonthlySales(filters), [key]);
  return { ...h, data: h.data || null };
}

function useSalesTeamReport() {
  const h = _useApi(() => api.getSalesTeamReport(), []);
  return { ...h, data: h.data ? h.data.salesTeam : [] };
}

function useDoctorReport() {
  const h = _useApi(() => api.getDoctorReport(), []);
  return { ...h, data: h.data ? h.data.doctors : [] };
}

function useSalesByModel(filters = {}) {
  const key = JSON.stringify(filters);
  const h = _useApi(() => api.getSalesByModel(filters), [key]);
  return { ...h, data: h.data ? h.data.byModel : [] };
}

// ── Sleep Tests ──────────────────────────────────────────────────
function useSleepTests(filters = {}) {
  const key = JSON.stringify(filters);
  const h = _useApi(() => api.getSleepTests(filters), [key]);
  return { ...h, data: h.data ? h.data.sleepTests : [] };
}

// ── Rental Payments ──────────────────────────────────────────────
function useRentalPayments(rentalId) {
  const h = _useApi(() => api.getRentalPayments(rentalId), [rentalId]);
  return { ...h, data: h.data ? h.data.payments : [] };
}

// ── Study Types ──────────────────────────────────────────────────
function useStudyTypes() {
  const h = _useApi(() => api.getStudyTypes(), []);
  return { ...h, data: h.data ? h.data.studyTypes : [] };
}

// ── Reports ──────────────────────────────────────────────────────
function useSalesReport(filters = {}) {
  const key = JSON.stringify(filters);
  const h = _useApi(() => api.getSalesReport(filters), [key]);
  return { ...h, data: h.data || {} };
}

function usePaymentsReport(filters = {}) {
  const key = JSON.stringify(filters);
  const h = _useApi(() => api.getPaymentsReport(filters), [key]);
  return { ...h, data: h.data || {} };
}

function useRentalReport(filters = {}) {
  const key = JSON.stringify(filters);
  const h = _useApi(() => api.getRentalReport(filters), [key]);
  return { ...h, data: h.data || {} };
}

function useCustomerReport(filters = {}) {
  const key = JSON.stringify(filters);
  const h = _useApi(() => api.getCustomerReport(filters), [key]);
  return { ...h, data: h.data || {} };
}
