/**
 * Suppliers React Query hooks
 * Provides data fetching, caching, and state management for supplier operations
 */

import { useMutation, useQuery, useQueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
import { suppliersService } from '../services/suppliers';
import { ApiError } from '../client/apiClient';
import type {
  SupplierCreate,
  SupplierUpdate,
  SupplierResponse,
  SupplierSummary,
  SupplierApproval,
  SupplierQueryParams,
  SupplierStatistics,
  TopSuppliersResponse,
  PurchaseOrderCreate,
  PurchaseOrderUpdate,
  PurchaseOrderResponse,
  PurchaseOrderApproval,
  PurchaseOrderQueryParams,
  DeliveryCreate,
  DeliveryUpdate,
  DeliveryResponse,
  DeliveryReceiptConfirmation,
  DeliveryQueryParams,
  PerformanceCalculationRequest,
  PerformanceMetrics,
  PerformanceAlert,
  PaginatedResponse,
} from '../types/suppliers';

// Query Keys Factory
export const suppliersKeys = {
  all: ['suppliers'] as const,
  suppliers: {
    all: () => [...suppliersKeys.all, 'suppliers'] as const,
    lists: () => [...suppliersKeys.suppliers.all(), 'list'] as const,
    list: (tenantId: string, params?: SupplierQueryParams) => 
      [...suppliersKeys.suppliers.lists(), tenantId, params] as const,
    details: () => [...suppliersKeys.suppliers.all(), 'detail'] as const,
    detail: (tenantId: string, supplierId: string) => 
      [...suppliersKeys.suppliers.details(), tenantId, supplierId] as const,
    statistics: (tenantId: string) => 
      [...suppliersKeys.suppliers.all(), 'statistics', tenantId] as const,
    top: (tenantId: string) => 
      [...suppliersKeys.suppliers.all(), 'top', tenantId] as const,
    byType: (tenantId: string, supplierType: string) => 
      [...suppliersKeys.suppliers.all(), 'by-type', tenantId, supplierType] as const,
  },
  purchaseOrders: {
    all: () => [...suppliersKeys.all, 'purchase-orders'] as const,
    lists: () => [...suppliersKeys.purchaseOrders.all(), 'list'] as const,
    list: (params?: PurchaseOrderQueryParams) => 
      [...suppliersKeys.purchaseOrders.lists(), params] as const,
    details: () => [...suppliersKeys.purchaseOrders.all(), 'detail'] as const,
    detail: (orderId: string) => 
      [...suppliersKeys.purchaseOrders.details(), orderId] as const,
  },
  deliveries: {
    all: () => [...suppliersKeys.all, 'deliveries'] as const,
    lists: () => [...suppliersKeys.deliveries.all(), 'list'] as const,
    list: (params?: DeliveryQueryParams) => 
      [...suppliersKeys.deliveries.lists(), params] as const,
    details: () => [...suppliersKeys.deliveries.all(), 'detail'] as const,
    detail: (deliveryId: string) => 
      [...suppliersKeys.deliveries.details(), deliveryId] as const,
  },
  performance: {
    all: () => [...suppliersKeys.all, 'performance'] as const,
    metrics: (tenantId: string, supplierId: string) => 
      [...suppliersKeys.performance.all(), 'metrics', tenantId, supplierId] as const,
    alerts: (tenantId: string, supplierId?: string) => 
      [...suppliersKeys.performance.all(), 'alerts', tenantId, supplierId] as const,
  },
} as const;

// Supplier Queries
export const useSuppliers = (
  tenantId: string,
  queryParams?: SupplierQueryParams,
  options?: Omit<UseQueryOptions<PaginatedResponse<SupplierSummary>, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<PaginatedResponse<SupplierSummary>, ApiError>({
    queryKey: suppliersKeys.suppliers.list(tenantId, queryParams),
    queryFn: () => suppliersService.getSuppliers(tenantId, queryParams),
    enabled: !!tenantId,
    staleTime: 2 * 60 * 1000, // 2 minutes
    ...options,
  });
};

export const useSupplier = (
  tenantId: string,
  supplierId: string,
  options?: Omit<UseQueryOptions<SupplierResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<SupplierResponse, ApiError>({
    queryKey: suppliersKeys.suppliers.detail(tenantId, supplierId),
    queryFn: () => suppliersService.getSupplier(tenantId, supplierId),
    enabled: !!tenantId && !!supplierId,
    staleTime: 5 * 60 * 1000, // 5 minutes
    ...options,
  });
};

export const useSupplierStatistics = (
  tenantId: string,
  options?: Omit<UseQueryOptions<SupplierStatistics, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<SupplierStatistics, ApiError>({
    queryKey: suppliersKeys.suppliers.statistics(tenantId),
    queryFn: () => suppliersService.getSupplierStatistics(tenantId),
    enabled: !!tenantId,
    staleTime: 5 * 60 * 1000, // 5 minutes
    ...options,
  });
};

export const useActiveSuppliers = (
  tenantId: string,
  queryParams?: Omit<SupplierQueryParams, 'status'>,
  options?: Omit<UseQueryOptions<PaginatedResponse<SupplierSummary>, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<PaginatedResponse<SupplierSummary>, ApiError>({
    queryKey: suppliersKeys.suppliers.list(tenantId, { ...queryParams, status: 'active' }),
    queryFn: () => suppliersService.getActiveSuppliers(tenantId, queryParams),
    enabled: !!tenantId,
    staleTime: 2 * 60 * 1000, // 2 minutes
    ...options,
  });
};

export const useTopSuppliers = (
  tenantId: string,
  options?: Omit<UseQueryOptions<TopSuppliersResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<TopSuppliersResponse, ApiError>({
    queryKey: suppliersKeys.suppliers.top(tenantId),
    queryFn: () => suppliersService.getTopSuppliers(tenantId),
    enabled: !!tenantId,
    staleTime: 10 * 60 * 1000, // 10 minutes
    ...options,
  });
};

export const usePendingApprovalSuppliers = (
  tenantId: string,
  options?: Omit<UseQueryOptions<PaginatedResponse<SupplierSummary>, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<PaginatedResponse<SupplierSummary>, ApiError>({
    queryKey: suppliersKeys.suppliers.list(tenantId, { status: 'pending_approval' }),
    queryFn: () => suppliersService.getPendingApprovalSuppliers(tenantId),
    enabled: !!tenantId,
    staleTime: 1 * 60 * 1000, // 1 minute
    ...options,
  });
};

export const useSuppliersByType = (
  tenantId: string,
  supplierType: string,
  queryParams?: Omit<SupplierQueryParams, 'supplier_type'>,
  options?: Omit<UseQueryOptions<PaginatedResponse<SupplierSummary>, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<PaginatedResponse<SupplierSummary>, ApiError>({
    queryKey: suppliersKeys.suppliers.byType(tenantId, supplierType),
    queryFn: () => suppliersService.getSuppliersByType(tenantId, supplierType, queryParams),
    enabled: !!tenantId && !!supplierType,
    staleTime: 2 * 60 * 1000, // 2 minutes
    ...options,
  });
};

// Purchase Order Queries
export const usePurchaseOrders = (
  queryParams?: PurchaseOrderQueryParams,
  options?: Omit<UseQueryOptions<PaginatedResponse<PurchaseOrderResponse>, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<PaginatedResponse<PurchaseOrderResponse>, ApiError>({
    queryKey: suppliersKeys.purchaseOrders.list(queryParams),
    queryFn: () => suppliersService.getPurchaseOrders(queryParams),
    staleTime: 1 * 60 * 1000, // 1 minute
    ...options,
  });
};

export const usePurchaseOrder = (
  orderId: string,
  options?: Omit<UseQueryOptions<PurchaseOrderResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<PurchaseOrderResponse, ApiError>({
    queryKey: suppliersKeys.purchaseOrders.detail(orderId),
    queryFn: () => suppliersService.getPurchaseOrder(orderId),
    enabled: !!orderId,
    staleTime: 2 * 60 * 1000, // 2 minutes
    ...options,
  });
};

// Delivery Queries
export const useDeliveries = (
  queryParams?: DeliveryQueryParams,
  options?: Omit<UseQueryOptions<PaginatedResponse<DeliveryResponse>, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<PaginatedResponse<DeliveryResponse>, ApiError>({
    queryKey: suppliersKeys.deliveries.list(queryParams),
    queryFn: () => suppliersService.getDeliveries(queryParams),
    staleTime: 1 * 60 * 1000, // 1 minute
    ...options,
  });
};

export const useDelivery = (
  deliveryId: string,
  options?: Omit<UseQueryOptions<DeliveryResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<DeliveryResponse, ApiError>({
    queryKey: suppliersKeys.deliveries.detail(deliveryId),
    queryFn: () => suppliersService.getDelivery(deliveryId),
    enabled: !!deliveryId,
    staleTime: 30 * 1000, // 30 seconds
    ...options,
  });
};

// Performance Queries
export const useSupplierPerformanceMetrics = (
  tenantId: string,
  supplierId: string,
  options?: Omit<UseQueryOptions<PerformanceMetrics, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<PerformanceMetrics, ApiError>({
    queryKey: suppliersKeys.performance.metrics(tenantId, supplierId),
    queryFn: () => suppliersService.getSupplierPerformanceMetrics(tenantId, supplierId),
    enabled: !!tenantId && !!supplierId,
    staleTime: 10 * 60 * 1000, // 10 minutes
    ...options,
  });
};

export const usePerformanceAlerts = (
  tenantId: string,
  supplierId?: string,
  options?: Omit<UseQueryOptions<PerformanceAlert[], ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<PerformanceAlert[], ApiError>({
    queryKey: suppliersKeys.performance.alerts(tenantId, supplierId),
    queryFn: () => suppliersService.getPerformanceAlerts(tenantId, supplierId),
    enabled: !!tenantId,
    staleTime: 2 * 60 * 1000, // 2 minutes
    ...options,
  });
};

// Supplier Mutations
export const useCreateSupplier = (
  options?: UseMutationOptions<
    SupplierResponse,
    ApiError,
    { tenantId: string; supplierData: SupplierCreate }
  >
) => {
  const queryClient = useQueryClient();

  return useMutation<
    SupplierResponse,
    ApiError,
    { tenantId: string; supplierData: SupplierCreate }
  >({
    mutationFn: ({ tenantId, supplierData }) =>
      suppliersService.createSupplier(tenantId, supplierData),
    onSuccess: (data, { tenantId }) => {
      // Add to cache
      queryClient.setQueryData(
        suppliersKeys.suppliers.detail(tenantId, data.id),
        data
      );
      
      // Invalidate lists and statistics
      queryClient.invalidateQueries({
        queryKey: suppliersKeys.suppliers.lists()
      });
      queryClient.invalidateQueries({
        queryKey: suppliersKeys.suppliers.statistics(tenantId)
      });
    },
    ...options,
  });
};

export const useUpdateSupplier = (
  options?: UseMutationOptions<
    SupplierResponse,
    ApiError,
    { tenantId: string; supplierId: string; updateData: SupplierUpdate }
  >
) => {
  const queryClient = useQueryClient();

  return useMutation<
    SupplierResponse,
    ApiError,
    { tenantId: string; supplierId: string; updateData: SupplierUpdate }
  >({
    mutationFn: ({ tenantId, supplierId, updateData }) =>
      suppliersService.updateSupplier(tenantId, supplierId, updateData),
    onSuccess: (data, { tenantId, supplierId }) => {
      // Update cache
      queryClient.setQueryData(
        suppliersKeys.suppliers.detail(tenantId, supplierId),
        data
      );
      
      // Invalidate lists
      queryClient.invalidateQueries({
        queryKey: suppliersKeys.suppliers.lists()
      });
    },
    ...options,
  });
};

export const useDeleteSupplier = (
  options?: UseMutationOptions<
    { message: string },
    ApiError,
    { tenantId: string; supplierId: string }
  >
) => {
  const queryClient = useQueryClient();

  return useMutation<
    { message: string },
    ApiError,
    { tenantId: string; supplierId: string }
  >({
    mutationFn: ({ tenantId, supplierId }) =>
      suppliersService.deleteSupplier(tenantId, supplierId),
    onSuccess: (_, { tenantId, supplierId }) => {
      // Remove from cache
      queryClient.removeQueries({
        queryKey: suppliersKeys.suppliers.detail(tenantId, supplierId)
      });
      
      // Invalidate lists and statistics
      queryClient.invalidateQueries({
        queryKey: suppliersKeys.suppliers.lists()
      });
      queryClient.invalidateQueries({
        queryKey: suppliersKeys.suppliers.statistics(tenantId)
      });
    },
    ...options,
  });
};

export const useApproveSupplier = (
  options?: UseMutationOptions<
    SupplierResponse,
    ApiError,
    { tenantId: string; supplierId: string; approval: SupplierApproval }
  >
) => {
  const queryClient = useQueryClient();

  return useMutation<
    SupplierResponse,
    ApiError,
    { tenantId: string; supplierId: string; approval: SupplierApproval }
  >({
    mutationFn: ({ tenantId, supplierId, approval }) =>
      suppliersService.approveSupplier(tenantId, supplierId, approval),
    onSuccess: (data, { tenantId, supplierId }) => {
      // Update cache
      queryClient.setQueryData(
        suppliersKeys.suppliers.detail(tenantId, supplierId),
        data
      );
      
      // Invalidate lists and statistics
      queryClient.invalidateQueries({
        queryKey: suppliersKeys.suppliers.lists()
      });
      queryClient.invalidateQueries({
        queryKey: suppliersKeys.suppliers.statistics(tenantId)
      });
    },
    ...options,
  });
};

// Purchase Order Mutations
export const useCreatePurchaseOrder = (
  options?: UseMutationOptions<PurchaseOrderResponse, ApiError, PurchaseOrderCreate>
) => {
  const queryClient = useQueryClient();

  return useMutation<PurchaseOrderResponse, ApiError, PurchaseOrderCreate>({
    mutationFn: (orderData) => suppliersService.createPurchaseOrder(orderData),
    onSuccess: (data) => {
      // Add to cache
      queryClient.setQueryData(
        suppliersKeys.purchaseOrders.detail(data.id),
        data
      );
      
      // Invalidate lists
      queryClient.invalidateQueries({
        queryKey: suppliersKeys.purchaseOrders.lists()
      });
    },
    ...options,
  });
};

export const useUpdatePurchaseOrder = (
  options?: UseMutationOptions<
    PurchaseOrderResponse,
    ApiError,
    { orderId: string; updateData: PurchaseOrderUpdate }
  >
) => {
  const queryClient = useQueryClient();

  return useMutation<
    PurchaseOrderResponse,
    ApiError,
    { orderId: string; updateData: PurchaseOrderUpdate }
  >({
    mutationFn: ({ orderId, updateData }) =>
      suppliersService.updatePurchaseOrder(orderId, updateData),
    onSuccess: (data, { orderId }) => {
      // Update cache
      queryClient.setQueryData(
        suppliersKeys.purchaseOrders.detail(orderId),
        data
      );
      
      // Invalidate lists
      queryClient.invalidateQueries({
        queryKey: suppliersKeys.purchaseOrders.lists()
      });
    },
    ...options,
  });
};

export const useApprovePurchaseOrder = (
  options?: UseMutationOptions<
    PurchaseOrderResponse,
    ApiError,
    { orderId: string; approval: PurchaseOrderApproval }
  >
) => {
  const queryClient = useQueryClient();

  return useMutation<
    PurchaseOrderResponse,
    ApiError,
    { orderId: string; approval: PurchaseOrderApproval }
  >({
    mutationFn: ({ orderId, approval }) =>
      suppliersService.approvePurchaseOrder(orderId, approval),
    onSuccess: (data, { orderId }) => {
      // Update cache
      queryClient.setQueryData(
        suppliersKeys.purchaseOrders.detail(orderId),
        data
      );
      
      // Invalidate lists
      queryClient.invalidateQueries({
        queryKey: suppliersKeys.purchaseOrders.lists()
      });
    },
    ...options,
  });
};

// Delivery Mutations
export const useCreateDelivery = (
  options?: UseMutationOptions<DeliveryResponse, ApiError, DeliveryCreate>
) => {
  const queryClient = useQueryClient();

  return useMutation<DeliveryResponse, ApiError, DeliveryCreate>({
    mutationFn: (deliveryData) => suppliersService.createDelivery(deliveryData),
    onSuccess: (data) => {
      // Add to cache
      queryClient.setQueryData(
        suppliersKeys.deliveries.detail(data.id),
        data
      );
      
      // Invalidate lists
      queryClient.invalidateQueries({
        queryKey: suppliersKeys.deliveries.lists()
      });
    },
    ...options,
  });
};

export const useUpdateDelivery = (
  options?: UseMutationOptions<
    DeliveryResponse,
    ApiError,
    { deliveryId: string; updateData: DeliveryUpdate }
  >
) => {
  const queryClient = useQueryClient();

  return useMutation<
    DeliveryResponse,
    ApiError,
    { deliveryId: string; updateData: DeliveryUpdate }
  >({
    mutationFn: ({ deliveryId, updateData }) =>
      suppliersService.updateDelivery(deliveryId, updateData),
    onSuccess: (data, { deliveryId }) => {
      // Update cache
      queryClient.setQueryData(
        suppliersKeys.deliveries.detail(deliveryId),
        data
      );
      
      // Invalidate lists
      queryClient.invalidateQueries({
        queryKey: suppliersKeys.deliveries.lists()
      });
    },
    ...options,
  });
};

export const useConfirmDeliveryReceipt = (
  options?: UseMutationOptions<
    DeliveryResponse,
    ApiError,
    { deliveryId: string; confirmation: DeliveryReceiptConfirmation }
  >
) => {
  const queryClient = useQueryClient();

  return useMutation<
    DeliveryResponse,
    ApiError,
    { deliveryId: string; confirmation: DeliveryReceiptConfirmation }
  >({
    mutationFn: ({ deliveryId, confirmation }) =>
      suppliersService.confirmDeliveryReceipt(deliveryId, confirmation),
    onSuccess: (data, { deliveryId }) => {
      // Update cache
      queryClient.setQueryData(
        suppliersKeys.deliveries.detail(deliveryId),
        data
      );
      
      // Invalidate lists and performance metrics
      queryClient.invalidateQueries({
        queryKey: suppliersKeys.deliveries.lists()
      });
      queryClient.invalidateQueries({
        queryKey: suppliersKeys.performance.all()
      });
    },
    ...options,
  });
};

// Performance Mutations
export const useCalculateSupplierPerformance = (
  options?: UseMutationOptions<
    { message: string; calculation_id: string },
    ApiError,
    { tenantId: string; supplierId: string; request?: PerformanceCalculationRequest }
  >
) => {
  const queryClient = useQueryClient();

  return useMutation<
    { message: string; calculation_id: string },
    ApiError,
    { tenantId: string; supplierId: string; request?: PerformanceCalculationRequest }
  >({
    mutationFn: ({ tenantId, supplierId, request }) =>
      suppliersService.calculateSupplierPerformance(tenantId, supplierId, request),
    onSuccess: (_, { tenantId, supplierId }) => {
      // Invalidate performance metrics after calculation
      queryClient.invalidateQueries({
        queryKey: suppliersKeys.performance.metrics(tenantId, supplierId)
      });
      queryClient.invalidateQueries({
        queryKey: suppliersKeys.performance.alerts(tenantId)
      });
    },
    ...options,
  });
};

export const useEvaluatePerformanceAlerts = (
  options?: UseMutationOptions<
    { alerts_generated: number; message: string },
    ApiError,
    { tenantId: string }
  >
) => {
  const queryClient = useQueryClient();

  return useMutation<
    { alerts_generated: number; message: string },
    ApiError,
    { tenantId: string }
  >({
    mutationFn: ({ tenantId }) => suppliersService.evaluatePerformanceAlerts(tenantId),
    onSuccess: (_, { tenantId }) => {
      // Invalidate performance alerts
      queryClient.invalidateQueries({
        queryKey: suppliersKeys.performance.alerts(tenantId)
      });
    },
    ...options,
  });
};

// Utility Hooks
export const useSuppliersByStatus = (tenantId: string, status: string) => {
  return useSuppliers(tenantId, { status: status as any });
};

export const useSuppliersCount = (tenantId: string) => {
  const { data: statistics } = useSupplierStatistics(tenantId);
  return statistics?.total_suppliers || 0;
};

export const useActiveSuppliersCount = (tenantId: string) => {
  const { data: statistics } = useSupplierStatistics(tenantId);
  return statistics?.active_suppliers || 0;
};

export const usePendingOrdersCount = (supplierId?: string) => {
  const { data: orders } = usePurchaseOrders({
    supplier_id: supplierId,
    status: 'pending_approval',
    limit: 1000
  });
  return orders?.data?.length || 0;
};