import { useState, useEffect, useCallback, useRef } from "react";

interface UseAdminDataOptions<T> {
  fetchFn: () => Promise<T>;
  onSuccess?: (data: T) => void;
  onError?: (error: Error) => void;
}

export function useAdminData<T>({
  fetchFn,
  onSuccess,
  onError,
}: UseAdminDataOptions<T>) {
  const [data, setData] = useState<T | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<Error | null>(null);

  // Use refs to store the latest versions of callbacks without causing re-renders
  const fetchFnRef = useRef(fetchFn);
  const onSuccessRef = useRef(onSuccess);
  const onErrorRef = useRef(onError);
  
  // Track if we've already started fetching to prevent duplicate calls
  const isFetchingRef = useRef(false);
  const hasMountedRef = useRef(false);

  // Keep refs up to date (runs on every render, but doesn't cause effects to re-run)
  fetchFnRef.current = fetchFn;
  onSuccessRef.current = onSuccess;
  onErrorRef.current = onError;

  const fetchData = useCallback(async () => {
    // Prevent concurrent fetches
    if (isFetchingRef.current) return;
    isFetchingRef.current = true;
    
    try {
      setLoading(true);
      setError(null);
      const result = await fetchFnRef.current();
      setData(result);
      onSuccessRef.current?.(result);
    } catch (err) {
      const error = err instanceof Error ? err : new Error("Unknown error");
      setError(error);
      onErrorRef.current?.(error);
    } finally {
      setLoading(false);
      isFetchingRef.current = false;
    }
  }, []);

  useEffect(() => {
    // Only fetch once on mount
    if (hasMountedRef.current) return;
    hasMountedRef.current = true;
    fetchData();
  }, [fetchData]);

  const refetch = useCallback(() => {
    // Allow refetch even if we've already fetched
    isFetchingRef.current = false;
    return fetchData();
  }, [fetchData]);

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

