/**
 * Orders React Query hooks
 */
import { useMutation, useQuery, useQueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
import { OrdersService } from '../services/orders';
import {
  OrderResponse,
  OrderCreate,
  OrderUpdate,
  CustomerResponse,
  CustomerCreate,
  CustomerUpdate,
  OrdersDashboardSummary,
  DemandRequirements,
  BusinessModelDetection,
  ServiceStatus,
  GetOrdersParams,
  GetCustomersParams,
  UpdateOrderStatusParams,
  GetDemandRequirementsParams,
} from '../types/orders';
import { ApiError } from '../client/apiClient';

// Query Keys
export const ordersKeys = {
  all: ['orders'] as const,
  
  // Orders
  orders: () => [...ordersKeys.all, 'orders'] as const,
  ordersList: (params: GetOrdersParams) => [...ordersKeys.orders(), 'list', params] as const,
  order: (tenantId: string, orderId: string) => [...ordersKeys.orders(), 'detail', tenantId, orderId] as const,
  
  // Customers
  customers: () => [...ordersKeys.all, 'customers'] as const,
  customersList: (params: GetCustomersParams) => [...ordersKeys.customers(), 'list', params] as const,
  customer: (tenantId: string, customerId: string) => [...ordersKeys.customers(), 'detail', tenantId, customerId] as const,
  
  // Dashboard & Analytics
  dashboard: (tenantId: string) => [...ordersKeys.all, 'dashboard', tenantId] as const,
  demandRequirements: (params: GetDemandRequirementsParams) => [...ordersKeys.all, 'demand', params] as const,
  businessModel: (tenantId: string) => [...ordersKeys.all, 'business-model', tenantId] as const,
  
  // Status
  status: (tenantId: string) => [...ordersKeys.all, 'status', tenantId] as const,
} as const;

// ===== Order Queries =====

export const useOrders = (
  params: GetOrdersParams,
  options?: Omit<UseQueryOptions<OrderResponse[], ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<OrderResponse[], ApiError>({
    queryKey: ordersKeys.ordersList(params),
    queryFn: () => OrdersService.getOrders(params),
    staleTime: 2 * 60 * 1000, // 2 minutes
    ...options,
  });
};

export const useOrder = (
  tenantId: string,
  orderId: string,
  options?: Omit<UseQueryOptions<OrderResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<OrderResponse, ApiError>({
    queryKey: ordersKeys.order(tenantId, orderId),
    queryFn: () => OrdersService.getOrder(tenantId, orderId),
    staleTime: 1 * 60 * 1000, // 1 minute
    enabled: !!tenantId && !!orderId,
    ...options,
  });
};

// ===== Customer Queries =====

export const useCustomers = (
  params: GetCustomersParams,
  options?: Omit<UseQueryOptions<CustomerResponse[], ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<CustomerResponse[], ApiError>({
    queryKey: ordersKeys.customersList(params),
    queryFn: () => OrdersService.getCustomers(params),
    staleTime: 5 * 60 * 1000, // 5 minutes
    ...options,
  });
};

export const useCustomer = (
  tenantId: string,
  customerId: string,
  options?: Omit<UseQueryOptions<CustomerResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<CustomerResponse, ApiError>({
    queryKey: ordersKeys.customer(tenantId, customerId),
    queryFn: () => OrdersService.getCustomer(tenantId, customerId),
    staleTime: 5 * 60 * 1000, // 5 minutes
    enabled: !!tenantId && !!customerId,
    ...options,
  });
};

// ===== Dashboard & Analytics Queries =====

export const useOrdersDashboard = (
  tenantId: string,
  options?: Omit<UseQueryOptions<OrdersDashboardSummary, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<OrdersDashboardSummary, ApiError>({
    queryKey: ordersKeys.dashboard(tenantId),
    queryFn: () => OrdersService.getDashboardSummary(tenantId),
    staleTime: 1 * 60 * 1000, // 1 minute
    enabled: !!tenantId,
    ...options,
  });
};

export const useDemandRequirements = (
  params: GetDemandRequirementsParams,
  options?: Omit<UseQueryOptions<DemandRequirements, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<DemandRequirements, ApiError>({
    queryKey: ordersKeys.demandRequirements(params),
    queryFn: () => OrdersService.getDemandRequirements(params),
    staleTime: 30 * 60 * 1000, // 30 minutes
    enabled: !!params.tenant_id && !!params.target_date,
    ...options,
  });
};

export const useBusinessModelDetection = (
  tenantId: string,
  options?: Omit<UseQueryOptions<BusinessModelDetection, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<BusinessModelDetection, ApiError>({
    queryKey: ordersKeys.businessModel(tenantId),
    queryFn: () => OrdersService.detectBusinessModel(tenantId),
    staleTime: 60 * 60 * 1000, // 1 hour
    enabled: !!tenantId,
    ...options,
  });
};

export const useOrdersServiceStatus = (
  tenantId: string,
  options?: Omit<UseQueryOptions<ServiceStatus, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<ServiceStatus, ApiError>({
    queryKey: ordersKeys.status(tenantId),
    queryFn: () => OrdersService.getServiceStatus(tenantId),
    staleTime: 30 * 1000, // 30 seconds
    enabled: !!tenantId,
    ...options,
  });
};

// ===== Order Mutations =====

export const useCreateOrder = (
  options?: UseMutationOptions<OrderResponse, ApiError, OrderCreate>
) => {
  const queryClient = useQueryClient();

  return useMutation<OrderResponse, ApiError, OrderCreate>({
    mutationFn: (orderData: OrderCreate) => OrdersService.createOrder(orderData),
    onSuccess: (data, variables) => {
      // Invalidate orders list for this tenant
      queryClient.invalidateQueries({
        queryKey: ordersKeys.orders(),
        predicate: (query) => {
          const queryKey = query.queryKey as string[];
          return queryKey.includes('list') &&
                 JSON.stringify(queryKey).includes(variables.tenant_id);
        },
      });

      // Invalidate dashboard
      queryClient.invalidateQueries({
        queryKey: ordersKeys.dashboard(variables.tenant_id),
      });

      // Add the new order to cache
      queryClient.setQueryData(
        ordersKeys.order(variables.tenant_id, data.id),
        data
      );
    },
    ...options,
  });
};

export const useUpdateOrder = (
  options?: UseMutationOptions<OrderResponse, ApiError, { tenantId: string; orderId: string; data: OrderUpdate }>
) => {
  const queryClient = useQueryClient();

  return useMutation<OrderResponse, ApiError, { tenantId: string; orderId: string; data: OrderUpdate }>({
    mutationFn: ({ tenantId, orderId, data }) => OrdersService.updateOrder(tenantId, orderId, data),
    onSuccess: (data, variables) => {
      // Update the specific order in cache
      queryClient.setQueryData(
        ordersKeys.order(variables.tenantId, variables.orderId),
        data
      );

      // Invalidate orders list for this tenant
      queryClient.invalidateQueries({
        queryKey: ordersKeys.orders(),
        predicate: (query) => {
          const queryKey = query.queryKey as string[];
          return queryKey.includes('list') &&
                 JSON.stringify(queryKey).includes(variables.tenantId);
        },
      });

      // Invalidate dashboard
      queryClient.invalidateQueries({
        queryKey: ordersKeys.dashboard(variables.tenantId),
      });
    },
    ...options,
  });
};

export const useUpdateOrderStatus = (
  options?: UseMutationOptions<OrderResponse, ApiError, UpdateOrderStatusParams>
) => {
  const queryClient = useQueryClient();

  return useMutation<OrderResponse, ApiError, UpdateOrderStatusParams>({
    mutationFn: (params: UpdateOrderStatusParams) => OrdersService.updateOrderStatus(params),
    onSuccess: (data, variables) => {
      // Update the specific order in cache
      queryClient.setQueryData(
        ordersKeys.order(variables.tenant_id, variables.order_id),
        data
      );

      // Invalidate orders list for this tenant
      queryClient.invalidateQueries({
        queryKey: ordersKeys.orders(),
        predicate: (query) => {
          const queryKey = query.queryKey as string[];
          return queryKey.includes('list') && 
                 JSON.stringify(queryKey).includes(variables.tenant_id);
        },
      });

      // Invalidate dashboard
      queryClient.invalidateQueries({
        queryKey: ordersKeys.dashboard(variables.tenant_id),
      });
    },
    ...options,
  });
};

// ===== Customer Mutations =====

export const useCreateCustomer = (
  options?: UseMutationOptions<CustomerResponse, ApiError, CustomerCreate>
) => {
  const queryClient = useQueryClient();

  return useMutation<CustomerResponse, ApiError, CustomerCreate>({
    mutationFn: (customerData: CustomerCreate) => OrdersService.createCustomer(customerData),
    onSuccess: (data, variables) => {
      // Invalidate all customer list queries for this tenant
      // This will match any query with ['orders', 'customers', 'list', ...]
      // refetchType: 'active' forces immediate refetch of mounted queries
      queryClient.invalidateQueries({
        queryKey: ordersKeys.customers(),
        refetchType: 'active',
      });

      // Add the new customer to cache
      queryClient.setQueryData(
        ordersKeys.customer(variables.tenant_id, data.id),
        data
      );

      // Invalidate dashboard (for customer metrics)
      queryClient.invalidateQueries({
        queryKey: ordersKeys.dashboard(variables.tenant_id),
        refetchType: 'active',
      });
    },
    ...options,
  });
};

export const useUpdateCustomer = (
  options?: UseMutationOptions<CustomerResponse, ApiError, { tenantId: string; customerId: string; data: CustomerUpdate }>
) => {
  const queryClient = useQueryClient();

  return useMutation<CustomerResponse, ApiError, { tenantId: string; customerId: string; data: CustomerUpdate }>({
    mutationFn: ({ tenantId, customerId, data }) => OrdersService.updateCustomer(tenantId, customerId, data),
    onSuccess: (data, variables) => {
      // Update the specific customer in cache
      queryClient.setQueryData(
        ordersKeys.customer(variables.tenantId, variables.customerId),
        data
      );

      // Invalidate all customer list queries
      // This will match any query with ['orders', 'customers', 'list', ...]
      // refetchType: 'active' forces immediate refetch of mounted queries
      queryClient.invalidateQueries({
        queryKey: ordersKeys.customers(),
        refetchType: 'active',
      });

      // Invalidate dashboard (for customer metrics)
      queryClient.invalidateQueries({
        queryKey: ordersKeys.dashboard(variables.tenantId),
        refetchType: 'active',
      });
    },
    ...options,
  });
};

// ===== Utility Functions =====

export const useInvalidateOrders = () => {
  const queryClient = useQueryClient();

  return {
    invalidateAllOrders: (tenantId?: string) => {
      if (tenantId) {
        queryClient.invalidateQueries({
          queryKey: ordersKeys.all,
          predicate: (query) => {
            return JSON.stringify(query.queryKey).includes(tenantId);
          },
        });
      } else {
        queryClient.invalidateQueries({ queryKey: ordersKeys.all });
      }
    },
    invalidateOrdersList: (tenantId: string) => {
      queryClient.invalidateQueries({
        queryKey: ordersKeys.orders(),
        predicate: (query) => {
          const queryKey = query.queryKey as string[];
          return queryKey.includes('list') && 
                 JSON.stringify(queryKey).includes(tenantId);
        },
      });
    },
    invalidateCustomersList: (tenantId: string) => {
      queryClient.invalidateQueries({
        queryKey: ordersKeys.customers(),
        predicate: (query) => {
          const queryKey = query.queryKey as string[];
          return queryKey.includes('list') && 
                 JSON.stringify(queryKey).includes(tenantId);
        },
      });
    },
    invalidateDashboard: (tenantId: string) => {
      queryClient.invalidateQueries({
        queryKey: ordersKeys.dashboard(tenantId),
      });
    },
  };
};
