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

interface UseApiOptions<T> extends Omit<ApiRequestOptions, "cacheTTL"> {
  cacheTTL?: number;
  onSuccess?: (data: T) => void;
  onError?: (error: unknown) => void;
  enabled?: boolean;
}

interface UseApiReturn<T> {
  data: T | null;
  loading: boolean;
  error: unknown | null;
  execute: () => Promise<void>;
  reset: () => void;
}

export function useApi<T = unknown>(
  url: string,
  options: UseApiOptions<T> = {},
): UseApiReturn<T> {
  const {
    onSuccess,
    onError,
    enabled = true,
    cacheTTL,
    ...requestOptions
  } = options;

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

  const isMountedRef = useRef(true);
  const abortControllerRef = useRef<AbortController | null>(null);

  useEffect(() => {
    isMountedRef.current = true;
    return () => {
      isMountedRef.current = false;
      if (abortControllerRef.current) {
        abortControllerRef.current.abort();
      }
    };
  }, []);

  const execute = useCallback(async () => {
    if (!enabled) return;

    // Cancel previous request
    if (abortControllerRef.current) {
      abortControllerRef.current.abort();
    }

    abortControllerRef.current = new AbortController();

    setLoading(true);
    setError(null);

    try {
      const response = await apiClient.request<T>(url, {
        ...requestOptions,
        signal: abortControllerRef.current.signal,
        cacheTTL,
      });

      if (!isMountedRef.current) return;

      setData(response.data);
      onSuccess?.(response.data);
    } catch (err) {
      if (!isMountedRef.current) return;
      if (err instanceof Error && err.name === "AbortError") return;

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

  const reset = useCallback(() => {
    setData(null);
    setError(null);
    setLoading(false);
  }, []);

  return {
    data,
    loading,
    error,
    execute,
    reset,
  };
}

