/**
 * Recipes React Query hooks
 * Data fetching and caching layer for recipe management
 * All hooks properly handle tenant-dependent operations
 */

import {
  useMutation,
  useQuery,
  useQueryClient,
  UseQueryOptions,
  UseMutationOptions,
  useInfiniteQuery,
  UseInfiniteQueryOptions
} from '@tanstack/react-query';
import { recipesService } from '../services/recipes';
import { ApiError } from '../client/apiClient';
import type {
  RecipeResponse,
  RecipeCreate,
  RecipeUpdate,
  RecipeDuplicateRequest,
  RecipeFeasibilityResponse,
  RecipeStatisticsResponse,
  RecipeCategoriesResponse,
  RecipeDeletionSummary,
} from '../types/recipes';

// Query Keys Factory
export const recipesKeys = {
  all: ['recipes'] as const,
  tenant: (tenantId: string) => [...recipesKeys.all, 'tenant', tenantId] as const,
  lists: (tenantId: string) => [...recipesKeys.tenant(tenantId), 'list'] as const,
  list: (tenantId: string, filters: any) => [...recipesKeys.lists(tenantId), { filters }] as const,
  details: (tenantId: string) => [...recipesKeys.tenant(tenantId), 'detail'] as const,
  detail: (tenantId: string, id: string) => [...recipesKeys.details(tenantId), id] as const,
  statistics: (tenantId: string) => [...recipesKeys.tenant(tenantId), 'statistics'] as const,
  categories: (tenantId: string) => [...recipesKeys.tenant(tenantId), 'categories'] as const,
  feasibility: (tenantId: string, id: string, batchMultiplier: number) => [...recipesKeys.tenant(tenantId), 'feasibility', id, batchMultiplier] as const,
} as const;

// Recipe Queries

/**
 * Fetch a single recipe by ID
 */
export const useRecipe = (
  tenantId: string,
  recipeId: string,
  options?: Omit<UseQueryOptions<RecipeResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<RecipeResponse, ApiError>({
    queryKey: recipesKeys.detail(tenantId, recipeId),
    queryFn: () => recipesService.getRecipe(tenantId, recipeId),
    enabled: !!(tenantId && recipeId),
    staleTime: 5 * 60 * 1000, // 5 minutes
    ...options,
  });
};

/**
 * Search/list recipes with filters
 */
export const useRecipes = (
  tenantId: string,
  filters: any = {},
  options?: Omit<UseQueryOptions<RecipeResponse[], ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<RecipeResponse[], ApiError>({
    queryKey: recipesKeys.list(tenantId, filters),
    queryFn: () => recipesService.searchRecipes(tenantId, filters),
    staleTime: 2 * 60 * 1000, // 2 minutes
    enabled: !!tenantId,
    ...options,
  });
};

/**
 * Infinite query for recipes (pagination)
 */
export const useInfiniteRecipes = (
  tenantId: string,
  filters: Omit<any, 'offset'> = {},
  options?: Omit<UseInfiniteQueryOptions<RecipeResponse[], ApiError>, 'queryKey' | 'queryFn' | 'getNextPageParam' | 'initialPageParam'>
) => {
  return useInfiniteQuery<RecipeResponse[], ApiError>({
    queryKey: recipesKeys.list(tenantId, filters),
    queryFn: ({ pageParam = 0 }) =>
      recipesService.searchRecipes(tenantId, { ...filters, offset: pageParam }),
    initialPageParam: 0,
    getNextPageParam: (lastPage, allPages) => {
      const limit = filters.limit || 100;
      if (lastPage.length < limit) return undefined;
      return allPages.length * limit;
    },
    enabled: !!tenantId,
    staleTime: 2 * 60 * 1000, // 2 minutes
    ...options,
  });
};

/**
 * Get recipe statistics
 */
export const useRecipeStatistics = (
  tenantId: string,
  options?: Omit<UseQueryOptions<RecipeStatisticsResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<RecipeStatisticsResponse, ApiError>({
    queryKey: recipesKeys.statistics(tenantId),
    queryFn: () => recipesService.getRecipeStatistics(tenantId),
    staleTime: 5 * 60 * 1000, // 5 minutes
    enabled: !!tenantId,
    ...options,
  });
};

/**
 * Get recipe categories
 */
export const useRecipeCategories = (
  tenantId: string,
  options?: Omit<UseQueryOptions<RecipeCategoriesResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<RecipeCategoriesResponse, ApiError>({
    queryKey: recipesKeys.categories(tenantId),
    queryFn: () => recipesService.getRecipeCategories(tenantId),
    staleTime: 10 * 60 * 1000, // 10 minutes
    enabled: !!tenantId,
    ...options,
  });
};

/**
 * Check recipe feasibility
 */
export const useRecipeFeasibility = (
  tenantId: string,
  recipeId: string,
  batchMultiplier: number = 1.0,
  options?: Omit<UseQueryOptions<RecipeFeasibilityResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<RecipeFeasibilityResponse, ApiError>({
    queryKey: recipesKeys.feasibility(tenantId, recipeId, batchMultiplier),
    queryFn: () => recipesService.checkRecipeFeasibility(tenantId, recipeId, batchMultiplier),
    enabled: !!(tenantId && recipeId),
    staleTime: 1 * 60 * 1000, // 1 minute (fresher data for inventory checks)
    ...options,
  });
};

// Recipe Mutations

/**
 * Create a new recipe
 */
export const useCreateRecipe = (
  tenantId: string,
  options?: UseMutationOptions<RecipeResponse, ApiError, RecipeCreate>
) => {
  const queryClient = useQueryClient();

  return useMutation<RecipeResponse, ApiError, RecipeCreate>({
    mutationFn: (recipeData: RecipeCreate) => recipesService.createRecipe(tenantId, recipeData),
    onSuccess: (data) => {
      // Add to lists cache
      queryClient.invalidateQueries({ queryKey: recipesKeys.lists(tenantId) });
      // Set individual recipe cache
      queryClient.setQueryData(recipesKeys.detail(tenantId, data.id), data);
      // Invalidate statistics
      queryClient.invalidateQueries({ queryKey: recipesKeys.statistics(tenantId) });
      // Invalidate categories (new category might be added)
      queryClient.invalidateQueries({ queryKey: recipesKeys.categories(tenantId) });
    },
    ...options,
  });
};

/**
 * Update an existing recipe
 */
export const useUpdateRecipe = (
  tenantId: string,
  options?: UseMutationOptions<RecipeResponse, ApiError, { id: string; data: RecipeUpdate }>
) => {
  const queryClient = useQueryClient();

  return useMutation<RecipeResponse, ApiError, { id: string; data: RecipeUpdate }>({
    mutationFn: ({ id, data }) => recipesService.updateRecipe(tenantId, id, data),
    onSuccess: (data) => {
      // Update individual recipe cache
      queryClient.setQueryData(recipesKeys.detail(tenantId, data.id), data);
      // Invalidate lists (recipe might move in search results)
      queryClient.invalidateQueries({ queryKey: recipesKeys.lists(tenantId) });
      // Invalidate statistics
      queryClient.invalidateQueries({ queryKey: recipesKeys.statistics(tenantId) });
      // Invalidate categories
      queryClient.invalidateQueries({ queryKey: recipesKeys.categories(tenantId) });
    },
    ...options,
  });
};

/**
 * Delete a recipe
 */
export const useDeleteRecipe = (
  tenantId: string,
  options?: UseMutationOptions<{ message: string }, ApiError, string>
) => {
  const queryClient = useQueryClient();

  return useMutation<{ message: string }, ApiError, string>({
    mutationFn: (recipeId: string) => recipesService.deleteRecipe(tenantId, recipeId),
    onSuccess: (_, recipeId) => {
      // Remove from individual cache
      queryClient.removeQueries({ queryKey: recipesKeys.detail(tenantId, recipeId) });
      // Invalidate lists
      queryClient.invalidateQueries({ queryKey: recipesKeys.lists(tenantId) });
      // Invalidate statistics
      queryClient.invalidateQueries({ queryKey: recipesKeys.statistics(tenantId) });
      // Invalidate categories
      queryClient.invalidateQueries({ queryKey: recipesKeys.categories(tenantId) });
    },
    ...options,
  });
};

/**
 * Archive a recipe (soft delete)
 */
export const useArchiveRecipe = (
  tenantId: string,
  options?: UseMutationOptions<RecipeResponse, ApiError, string>
) => {
  const queryClient = useQueryClient();

  return useMutation<RecipeResponse, ApiError, string>({
    mutationFn: (recipeId: string) => recipesService.archiveRecipe(tenantId, recipeId),
    onSuccess: (data) => {
      // Update individual recipe cache
      queryClient.setQueryData(recipesKeys.detail(tenantId, data.id), data);
      // Invalidate lists
      queryClient.invalidateQueries({ queryKey: recipesKeys.lists(tenantId) });
      // Invalidate statistics
      queryClient.invalidateQueries({ queryKey: recipesKeys.statistics(tenantId) });
    },
    ...options,
  });
};

/**
 * Get deletion summary for a recipe
 */
export const useRecipeDeletionSummary = (
  tenantId: string,
  recipeId: string,
  options?: Omit<UseQueryOptions<RecipeDeletionSummary, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<RecipeDeletionSummary, ApiError>({
    queryKey: [...recipesKeys.detail(tenantId, recipeId), 'deletion-summary'],
    queryFn: () => recipesService.getRecipeDeletionSummary(tenantId, recipeId),
    enabled: !!(tenantId && recipeId),
    staleTime: 0, // Always fetch fresh data
    ...options,
  });
};

/**
 * Duplicate a recipe
 */
export const useDuplicateRecipe = (
  tenantId: string,
  options?: UseMutationOptions<RecipeResponse, ApiError, { id: string; data: RecipeDuplicateRequest }>
) => {
  const queryClient = useQueryClient();

  return useMutation<RecipeResponse, ApiError, { id: string; data: RecipeDuplicateRequest }>({
    mutationFn: ({ id, data }) => recipesService.duplicateRecipe(tenantId, id, data),
    onSuccess: (data) => {
      // Add to lists cache
      queryClient.invalidateQueries({ queryKey: recipesKeys.lists(tenantId) });
      // Set individual recipe cache
      queryClient.setQueryData(recipesKeys.detail(tenantId, data.id), data);
      // Invalidate statistics
      queryClient.invalidateQueries({ queryKey: recipesKeys.statistics(tenantId) });
    },
    ...options,
  });
};

/**
 * Activate a recipe
 */
export const useActivateRecipe = (
  tenantId: string,
  options?: UseMutationOptions<RecipeResponse, ApiError, string>
) => {
  const queryClient = useQueryClient();

  return useMutation<RecipeResponse, ApiError, string>({
    mutationFn: (recipeId: string) => recipesService.activateRecipe(tenantId, recipeId),
    onSuccess: (data) => {
      // Update individual recipe cache
      queryClient.setQueryData(recipesKeys.detail(tenantId, data.id), data);
      // Invalidate lists
      queryClient.invalidateQueries({ queryKey: recipesKeys.lists(tenantId) });
      // Invalidate statistics
      queryClient.invalidateQueries({ queryKey: recipesKeys.statistics(tenantId) });
    },
    ...options,
  });
};