import { useState, useEffect, useCallback, useRef } from "react";
import { apiClient, type ApiRequestOptions, type ApiResponse } from "@/lib/api/client";

interface UseApiQueryOptions<T> extends Omit<ApiRequestOptions, "cacheTTL"> {
  cacheTTL?: number;
  refetchInterval?: number; // in milliseconds
  refetchOnMount?: boolean;
  refetchOnWindowFocus?: boolean;
  onSuccess?: (data: T) => void;
  onError?: (error: unknown) => void;
  enabled?: boolean;
}

interface UseApiQueryReturn<T> {
  data: T | null;
  loading: boolean;
  error: unknown | null;
  refetch: () => Promise<void>;
  invalidate: () => void;
}

export function useApiQuery<T = unknown>(
  url: string,
  options: UseApiQueryOptions<T> = {},
): UseApiQueryReturn<T> {
  const {
    cacheTTL,
    refetchInterval,
    refetchOnMount = true,
    refetchOnWindowFocus = false,
    onSuccess,
    onError,
    enabled = true,
    ...requestOptions
  } = options;

  const [data, setData] = useState<T | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<unknown | null>(null);

  const isMountedRef = useRef(true);
  const fetchRef = useRef<() => Promise<void>>(undefined);
  const intervalRef = useRef<NodeJS.Timeout | null>(null);
  const lastFetchRef = useRef<number>(0);

  const fetchData = useCallback(async (skipCache = false) => {
    if (!enabled) return;

    setLoading(true);
    setError(null);

    try {
      const response = await apiClient.request<T>(url, {
        ...requestOptions,
        cache: skipCache ? "no-store" : requestOptions.cache,
        cacheTTL,
      });

      if (!isMountedRef.current) return;

      setData(response.data);
      onSuccess?.(response.data);
      lastFetchRef.current = Date.now();
    } catch (err) {
      if (!isMountedRef.current) return;

      setError(err);
      onError?.(err);
    } finally {
      if (isMountedRef.current) {
        setLoading(false);
      }
    }
  }, [url, enabled, cacheTTL, onSuccess, onError, ...Object.values(requestOptions)]);

  fetchRef.current = fetchData;

  const refetch = useCallback(async () => {
    await fetchData(true);
  }, [fetchData]);

  const invalidate = useCallback(() => {
    apiClient.clearCacheForUrl(url);
    refetch();
  }, [url, refetch]);

  useEffect(() => {
    isMountedRef.current = true;

    // Initial fetch
    if (refetchOnMount && enabled) {
      fetchData();
    }

    // Refetch interval
    if (refetchInterval && refetchInterval > 0) {
      intervalRef.current = setInterval(() => {
        if (isMountedRef.current && enabled) {
          fetchData();
        }
      }, refetchInterval);
    }

    // Refetch on window focus
    if (refetchOnWindowFocus) {
      const handleFocus = () => {
        if (isMountedRef.current && enabled) {
          const timeSinceLastFetch = Date.now() - lastFetchRef.current;
          // Only refetch if it's been more than 5 seconds since last fetch
          if (timeSinceLastFetch > 5000) {
            fetchData();
          }
        }
      };

      window.addEventListener("focus", handleFocus);
      return () => {
        window.removeEventListener("focus", handleFocus);
        if (intervalRef.current) {
          clearInterval(intervalRef.current);
        }
      };
    }

    return () => {
      isMountedRef.current = false;
      if (intervalRef.current) {
        clearInterval(intervalRef.current);
      }
    };
  }, [enabled, refetchOnMount, refetchInterval, refetchOnWindowFocus, fetchData]);

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

