import { useState, useCallback } from "react";
import { useApiQuery } from "./useApiQuery";
import { useApiMutation } from "./useApiMutation";
import { apiClient } from "@/lib/api/client";

interface UseCRUDOperationsOptions<T> {
  baseUrl: string;
  cacheTTL?: number;
  onSuccess?: (action: "create" | "update" | "delete", item: T) => void;
  onError?: (action: "create" | "update" | "delete", error: unknown) => void;
}

interface UseCRUDOperationsReturn<T extends { id?: number }> {
  // Query
  items: T[];
  loading: boolean;
  error: unknown | null;
  refetch: () => Promise<void>;
  invalidate: () => void;

  // Mutations
  create: (item: Omit<T, "id">) => Promise<T | undefined>;
  update: (id: number, item: Partial<T>) => Promise<T | undefined>;
  remove: (id: number) => Promise<void>;
  createAsync: (item: Omit<T, "id">) => Promise<T>;
  updateAsync: (id: number, item: Partial<T>) => Promise<T>;
  removeAsync: (id: number) => Promise<void>;

  // Loading states
  creating: boolean;
  updating: boolean;
  deleting: boolean;
}

export function useCRUDOperations<T extends { id?: number }>(
  options: UseCRUDOperationsOptions<T>,
): UseCRUDOperationsReturn<T> {
  const { baseUrl, cacheTTL, onSuccess, onError } = options;

  // Query all items
  const { data, loading, error, refetch, invalidate } = useApiQuery<T[]>(baseUrl, {
    cacheTTL,
  });

  const items = data || [];

  // Loading states for mutations
  const [creating, setCreating] = useState(false);
  const [updating, setUpdating] = useState(false);
  const [deleting, setDeleting] = useState(false);

  // Create mutation
  const createMutation = useApiMutation<T, Omit<T, "id">>(baseUrl, "POST", {
    onSuccess: (newItem) => {
      onSuccess?.("create", newItem);
      invalidate();
    },
    onError: (err) => {
      onError?.("create", err);
    },
    invalidateQueries: [baseUrl],
  });

  // Create functions
  const createItem = useCallback(
    async (item: Omit<T, "id">): Promise<T | undefined> => {
      setCreating(true);
      try {
        return await createMutation.mutate(item);
      } finally {
        setCreating(false);
      }
    },
    [createMutation],
  );

  const createItemAsync = useCallback(
    async (item: Omit<T, "id">): Promise<T> => {
      setCreating(true);
      try {
        return await createMutation.mutateAsync(item);
      } finally {
        setCreating(false);
      }
    },
    [createMutation],
  );

  // Update functions (use direct API calls for dynamic URLs)
  const updateItem = useCallback(
    async (id: number, item: Partial<T>): Promise<T | undefined> => {
      setUpdating(true);
      try {
        const response = await apiClient.put<T>(`${baseUrl}/${id}`, item);
        invalidate();
        onSuccess?.("update", response.data);
        return response.data;
      } catch (err) {
        onError?.("update", err);
        return undefined;
      } finally {
        setUpdating(false);
      }
    },
    [baseUrl, invalidate, onSuccess, onError],
  );

  const updateItemAsync = useCallback(
    async (id: number, item: Partial<T>): Promise<T> => {
      setUpdating(true);
      try {
        const response = await apiClient.put<T>(`${baseUrl}/${id}`, item);
        invalidate();
        onSuccess?.("update", response.data);
        return response.data;
      } catch (err) {
        onError?.("update", err);
        throw err;
      } finally {
        setUpdating(false);
      }
    },
    [baseUrl, invalidate, onSuccess, onError],
  );

  // Delete functions (use direct API calls for dynamic URLs)
  const removeItem = useCallback(
    async (id: number): Promise<void> => {
      setDeleting(true);
      try {
        await apiClient.delete(`${baseUrl}/${id}`);
        invalidate();
      } catch (err) {
        onError?.("delete", err);
        throw err;
      } finally {
        setDeleting(false);
      }
    },
    [baseUrl, invalidate, onError],
  );

  const removeItemAsync = useCallback(
    async (id: number): Promise<void> => {
      await removeItem(id);
    },
    [removeItem],
  );

  return {
    items,
    loading,
    error,
    refetch,
    invalidate,
    create: createItem,
    createAsync: createItemAsync,
    update: updateItem,
    updateAsync: updateItemAsync,
    remove: removeItem,
    removeAsync: removeItemAsync,
    creating,
    updating,
    deleting,
  };
}

