// ui/hooks.jsx — React hook aliases shared by every .jsx file, the per-page data
// hook, and the loading / error states a page shows around its fetch.
// All visual styling lives in the host CSS (classes); these stay structural.
const { useState, useEffect, useRef, useMemo, useCallback } = React;

/* --------------------------------------------------- per-page data fetching */
// Each screen fetches its own page endpoint with this hook → { data, loading, error, refetch }.
// A 401 anywhere routes through the shell's logout handler (window.__vcOn401).
// refetch() re-runs the fetch (wire it to <PageError onRetry={refetch} /> so a
// transient failure can recover without reloading the whole app).
function useApi(fn, deps) {
  const [state, setState] = useState({ data: null, loading: true, error: "" });
  const [nonce, setNonce] = useState(0);
  useEffect(() => {
    // Real cancellation: fn receives an AbortSignal and the effect aborts it on
    // unmount / dep-change, so a stale in-flight request can never setState late.
    const ctrl = new AbortController();
    setState((s) => ({ data: s.data, loading: true, error: "" }));
    Promise.resolve().then(() => fn(ctrl.signal)).then(
      (data) => { if (!ctrl.signal.aborted) setState({ data, loading: false, error: "" }); },
      (e) => {
        if (ctrl.signal.aborted || (e && e.aborted)) return; // superseded / unmounted — ignore
        if (e && e.status === 401 && window.__vcOn401) { window.__vcOn401(); return; }
        setState({ data: null, loading: false, error: (e && e.message) || "Request failed." });
      }
    );
    return () => ctrl.abort();
  }, [...(deps || []), nonce]);
  return { ...state, refetch: () => setNonce((n) => n + 1) };
}

// Shared full-page loading / error states for per-page fetches.
function PageLoading({ label }) {
  return (
    <div style={{ display: "grid", placeItems: "center", minHeight: "60vh", gap: 14, textAlign: "center" }}>
      <span className="btn-spin" style={{ width: 28, height: 28, borderWidth: 3 }} />
      <span style={{ opacity: 0.7 }}>{label || "Loading…"}</span>
    </div>
  );
}
function PageError({ message, onRetry }) {
  return (
    <div className="page">
      <div className="empty">
        <Icon name="alert" size={22} />
        <p>{message || "Something went wrong loading this page."}</p>
        {onRetry && <button className="btn btn-ghost btn-sm" onClick={onRetry}>Retry</button>}
      </div>
    </div>
  );
}
