/**
 * POS React Query hooks
 * Provides data fetching and mutation hooks for POS operations
 */

import { useMutation, useQuery, useQueryClient, UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
import { posService } from '../services/pos';
import type {
  POSConfiguration,
  POSTransaction,
  POSSyncLog,
  POSWebhookLog,
  GetPOSConfigurationsRequest,
  GetPOSConfigurationsResponse,
  CreatePOSConfigurationRequest,
  CreatePOSConfigurationResponse,
  GetPOSConfigurationRequest,
  GetPOSConfigurationResponse,
  UpdatePOSConfigurationRequest,
  UpdatePOSConfigurationResponse,
  DeletePOSConfigurationRequest,
  DeletePOSConfigurationResponse,
  TestPOSConnectionRequest,
  TestPOSConnectionResponse,
  GetSupportedPOSSystemsResponse,
  POSSystem,
} from '../types/pos';
import { ApiError } from '../client';

// ============================================================================
// QUERY KEYS
// ============================================================================

export const posKeys = {
  all: ['pos'] as const,
  
  // Configurations
  configurations: () => [...posKeys.all, 'configurations'] as const,
  configurationsList: (tenantId: string, filters?: { pos_system?: POSSystem; is_active?: boolean }) => 
    [...posKeys.configurations(), 'list', tenantId, filters] as const,
  configuration: (tenantId: string, configId: string) => 
    [...posKeys.configurations(), 'detail', tenantId, configId] as const,
  
  // Supported Systems
  supportedSystems: () => [...posKeys.all, 'supported-systems'] as const,
  
  // Transactions
  transactions: () => [...posKeys.all, 'transactions'] as const,
  transactionsList: (tenantId: string, filters?: any) => 
    [...posKeys.transactions(), 'list', tenantId, filters] as const,
  transaction: (tenantId: string, transactionId: string) => 
    [...posKeys.transactions(), 'detail', tenantId, transactionId] as const,
  
  // Sync Logs
  syncLogs: () => [...posKeys.all, 'sync-logs'] as const,
  syncLogsList: (tenantId: string, filters?: any) => 
    [...posKeys.syncLogs(), 'list', tenantId, filters] as const,
  
  // Webhook Logs
  webhookLogs: () => [...posKeys.all, 'webhook-logs'] as const,
  webhookLogsList: (tenantId: string, filters?: any) => 
    [...posKeys.webhookLogs(), 'list', tenantId, filters] as const,
} as const;

// ============================================================================
// CONFIGURATION QUERIES
// ============================================================================

/**
 * Get POS configurations for a tenant
 */
export const usePOSConfigurations = (
  params: GetPOSConfigurationsRequest,
  options?: Omit<UseQueryOptions<GetPOSConfigurationsResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<GetPOSConfigurationsResponse, ApiError>({
    queryKey: posKeys.configurationsList(params.tenant_id, { 
      pos_system: params.pos_system, 
      is_active: params.is_active 
    }),
    queryFn: () => posService.getPOSConfigurations(params),
    enabled: !!params.tenant_id,
    staleTime: 2 * 60 * 1000, // 2 minutes
    ...options,
  });
};

/**
 * Get a specific POS configuration
 */
export const usePOSConfiguration = (
  params: GetPOSConfigurationRequest,
  options?: Omit<UseQueryOptions<GetPOSConfigurationResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<GetPOSConfigurationResponse, ApiError>({
    queryKey: posKeys.configuration(params.tenant_id, params.config_id),
    queryFn: () => posService.getPOSConfiguration(params),
    enabled: !!params.tenant_id && !!params.config_id,
    staleTime: 5 * 60 * 1000, // 5 minutes
    ...options,
  });
};

/**
 * Get supported POS systems
 */
export const useSupportedPOSSystems = (
  options?: Omit<UseQueryOptions<GetSupportedPOSSystemsResponse, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery<GetSupportedPOSSystemsResponse, ApiError>({
    queryKey: posKeys.supportedSystems(),
    queryFn: () => posService.getSupportedPOSSystems(),
    staleTime: 30 * 60 * 1000, // 30 minutes - this data rarely changes
    ...options,
  });
};

// ============================================================================
// CONFIGURATION MUTATIONS
// ============================================================================

/**
 * Create a new POS configuration
 */
export const useCreatePOSConfiguration = (
  options?: UseMutationOptions<CreatePOSConfigurationResponse, ApiError, CreatePOSConfigurationRequest>
) => {
  const queryClient = useQueryClient();
  
  return useMutation<CreatePOSConfigurationResponse, ApiError, CreatePOSConfigurationRequest>({
    mutationFn: (params) => posService.createPOSConfiguration(params),
    onSuccess: (data, variables) => {
      // Invalidate and refetch configurations list
      queryClient.invalidateQueries({ 
        queryKey: posKeys.configurationsList(variables.tenant_id) 
      });
      
      // If we have the created configuration, add it to the cache
      if (data.configuration) {
        queryClient.setQueryData(
          posKeys.configuration(variables.tenant_id, data.id),
          { configuration: data.configuration }
        );
      }
    },
    ...options,
  });
};

/**
 * Update a POS configuration
 */
export const useUpdatePOSConfiguration = (
  options?: UseMutationOptions<UpdatePOSConfigurationResponse, ApiError, UpdatePOSConfigurationRequest>
) => {
  const queryClient = useQueryClient();
  
  return useMutation<UpdatePOSConfigurationResponse, ApiError, UpdatePOSConfigurationRequest>({
    mutationFn: (params) => posService.updatePOSConfiguration(params),
    onSuccess: (data, variables) => {
      // Invalidate and refetch configurations list
      queryClient.invalidateQueries({ 
        queryKey: posKeys.configurationsList(variables.tenant_id) 
      });
      
      // Update the specific configuration cache if we have the updated data
      if (data.configuration) {
        queryClient.setQueryData(
          posKeys.configuration(variables.tenant_id, variables.config_id),
          { configuration: data.configuration }
        );
      } else {
        // Invalidate the specific configuration to refetch
        queryClient.invalidateQueries({
          queryKey: posKeys.configuration(variables.tenant_id, variables.config_id)
        });
      }
    },
    ...options,
  });
};

/**
 * Delete a POS configuration
 */
export const useDeletePOSConfiguration = (
  options?: UseMutationOptions<DeletePOSConfigurationResponse, ApiError, DeletePOSConfigurationRequest>
) => {
  const queryClient = useQueryClient();
  
  return useMutation<DeletePOSConfigurationResponse, ApiError, DeletePOSConfigurationRequest>({
    mutationFn: (params) => posService.deletePOSConfiguration(params),
    onSuccess: (data, variables) => {
      // Remove from configurations list cache
      queryClient.invalidateQueries({ 
        queryKey: posKeys.configurationsList(variables.tenant_id) 
      });
      
      // Remove the specific configuration from cache
      queryClient.removeQueries({
        queryKey: posKeys.configuration(variables.tenant_id, variables.config_id)
      });
    },
    ...options,
  });
};

/**
 * Test POS connection
 */
export const useTestPOSConnection = (
  options?: UseMutationOptions<TestPOSConnectionResponse, ApiError, TestPOSConnectionRequest>
) => {
  const queryClient = useQueryClient();
  
  return useMutation<TestPOSConnectionResponse, ApiError, TestPOSConnectionRequest>({
    mutationFn: (params) => posService.testPOSConnection(params),
    onSuccess: (data, variables) => {
      // Invalidate the configurations list to refresh connection status
      queryClient.invalidateQueries({ 
        queryKey: posKeys.configurationsList(variables.tenant_id) 
      });
      
      // Invalidate the specific configuration to refresh connection status
      queryClient.invalidateQueries({
        queryKey: posKeys.configuration(variables.tenant_id, variables.config_id)
      });
    },
    ...options,
  });
};

// ============================================================================
// TRANSACTION QUERIES
// ============================================================================

/**
 * Get POS transactions for a tenant (Updated to match backend)
 */
export const usePOSTransactions = (
  params: {
    tenant_id: string;
    pos_system?: string;
    start_date?: string;
    end_date?: string;
    status?: string;
    is_synced?: boolean;
    limit?: number;
    offset?: number;
  },
  options?: Omit<UseQueryOptions<{
    transactions: POSTransaction[];
    total: number;
    has_more: boolean;
    summary: {
      total_amount: number;
      transaction_count: number;
      sync_status: {
        synced: number;
        pending: number;
        failed: number;
      };
    };
  }, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery({
    queryKey: posKeys.transactionsList(params.tenant_id, params),
    queryFn: () => posService.getPOSTransactions(params),
    enabled: !!params.tenant_id,
    staleTime: 30 * 1000, // 30 seconds - transaction data should be fresh
    ...options,
  });
};

/**
 * Get a specific POS transaction
 */
export const usePOSTransaction = (
  params: {
    tenant_id: string;
    transaction_id: string;
  },
  options?: Omit<UseQueryOptions<POSTransaction, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery({
    queryKey: posKeys.transaction(params.tenant_id, params.transaction_id),
    queryFn: () => posService.getPOSTransaction(params),
    enabled: !!params.tenant_id && !!params.transaction_id,
    staleTime: 5 * 60 * 1000, // 5 minutes
    ...options,
  });
};

/**
 * Get POS transactions dashboard summary
 */
export const usePOSTransactionsDashboard = (
  params: {
    tenant_id: string;
  },
  options?: Omit<UseQueryOptions<{
    total_transactions_today: number;
    total_transactions_this_week: number;
    total_transactions_this_month: number;
    revenue_today: number;
    revenue_this_week: number;
    revenue_this_month: number;
    average_transaction_value: number;
    status_breakdown: Record<string, number>;
    payment_method_breakdown: Record<string, number>;
    sync_status: {
      synced: number;
      pending: number;
      failed: number;
      last_sync_at?: string;
    };
  }, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery({
    queryKey: [...posKeys.transactions(), 'dashboard', params.tenant_id],
    queryFn: () => posService.getPOSTransactionsDashboard(params),
    enabled: !!params.tenant_id,
    staleTime: 30 * 1000, // 30 seconds
    ...options,
  });
};

// ============================================================================
// SYNC OPERATIONS
// ============================================================================

/**
 * Trigger manual sync
 */
export const useTriggerManualSync = (
  options?: UseMutationOptions<
    { 
      sync_id: string; 
      message: string; 
      status: string; 
      sync_type: string; 
      data_types: string[]; 
      estimated_duration: string; 
    },
    ApiError,
    { 
      tenant_id: string; 
      config_id: string; 
      sync_type?: 'full' | 'incremental'; 
      data_types?: string[];
      from_date?: string;
      to_date?: string;
    }
  >
) => {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: (params) => posService.triggerManualSync(params),
    onSuccess: (data, variables) => {
      // Invalidate sync logs to show the new sync
      queryClient.invalidateQueries({
        queryKey: posKeys.syncLogsList(variables.tenant_id)
      });
      
      // Invalidate configurations to update last sync info
      queryClient.invalidateQueries({
        queryKey: posKeys.configurationsList(variables.tenant_id)
      });
    },
    ...options,
  });
};

/**
 * Get sync status for a configuration
 */
export const usePOSSyncStatus = (
  params: {
    tenant_id: string;
    config_id: string;
    limit?: number;
  },
  options?: Omit<UseQueryOptions<{
    current_sync: any;
    last_successful_sync: any;
    recent_syncs: any[];
    sync_health: {
      status: string;
      success_rate: number;
      average_duration_minutes: number;
      last_error?: string;
    };
  }, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery({
    queryKey: [...posKeys.configurations(), 'sync-status', params.tenant_id, params.config_id],
    queryFn: () => posService.getSyncStatus(params),
    enabled: !!params.tenant_id && !!params.config_id,
    staleTime: 30 * 1000, // 30 seconds - sync status should be fresh
    ...options,
  });
};

/**
 * Get detailed sync logs for a configuration
 */
export const useDetailedSyncLogs = (
  params: {
    tenant_id: string;
    config_id: string;
    limit?: number;
    offset?: number;
    status?: string;
    sync_type?: string;
    data_type?: string;
  },
  options?: Omit<UseQueryOptions<{
    logs: any[];
    total: number;
    has_more: boolean;
  }, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery({
    queryKey: [...posKeys.syncLogs(), 'detailed', params.tenant_id, params.config_id, params],
    queryFn: () => posService.getDetailedSyncLogs(params),
    enabled: !!params.tenant_id && !!params.config_id,
    staleTime: 30 * 1000, // 30 seconds
    ...options,
  });
};

/**
 * Sync single transaction
 */
export const useSyncSingleTransaction = (
  options?: UseMutationOptions<
    { message: string; transaction_id: string; sync_status: string; sales_record_id: string },
    ApiError,
    { tenant_id: string; transaction_id: string; force?: boolean }
  >
) => {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: (params) => posService.syncSingleTransaction(params),
    onSuccess: (data, variables) => {
      // Invalidate transactions list to update sync status
      queryClient.invalidateQueries({
        queryKey: posKeys.transactionsList(variables.tenant_id)
      });
      
      // Invalidate specific transaction
      queryClient.invalidateQueries({
        queryKey: posKeys.transaction(variables.tenant_id, variables.transaction_id)
      });
    },
    ...options,
  });
};

/**
 * Get sync performance analytics
 */
export const usePOSSyncAnalytics = (
  params: {
    tenant_id: string;
    days?: number;
  },
  options?: Omit<UseQueryOptions<{
    period_days: number;
    total_syncs: number;
    successful_syncs: number;
    failed_syncs: number;
    success_rate: number;
    average_duration_minutes: number;
    total_transactions_synced: number;
    total_revenue_synced: number;
    sync_frequency: {
      daily_average: number;
      peak_day?: string;
      peak_count: number;
    };
    error_analysis: {
      common_errors: any[];
      error_trends: any[];
    };
  }, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery({
    queryKey: [...posKeys.all, 'analytics', params.tenant_id, params.days],
    queryFn: () => posService.getSyncAnalytics(params),
    enabled: !!params.tenant_id,
    staleTime: 5 * 60 * 1000, // 5 minutes - analytics don't change frequently
    ...options,
  });
};

/**
 * Resync failed transactions
 */
export const useResyncFailedTransactions = (
  options?: UseMutationOptions<
    { message: string; job_id: string; scope: string; estimated_transactions: number },
    ApiError,
    { tenant_id: string; days_back?: number }
  >
) => {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: (params) => posService.resyncFailedTransactions(params),
    onSuccess: (data, variables) => {
      // Invalidate sync logs and analytics
      queryClient.invalidateQueries({
        queryKey: posKeys.syncLogsList(variables.tenant_id)
      });
      queryClient.invalidateQueries({
        queryKey: [...posKeys.all, 'analytics', variables.tenant_id]
      });
    },
    ...options,
  });
};

/**
 * Get sync logs
 */
export const usePOSSyncLogs = (
  params: {
    tenant_id: string;
    config_id?: string;
    status?: string;
    limit?: number;
    offset?: number;
  },
  options?: Omit<UseQueryOptions<{
    sync_logs: POSSyncLog[];
    total: number;
    has_more: boolean;
  }, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery({
    queryKey: posKeys.syncLogsList(params.tenant_id, params),
    queryFn: () => posService.getSyncLogs(params),
    enabled: !!params.tenant_id,
    staleTime: 30 * 1000, // 30 seconds
    ...options,
  });
};

// ============================================================================
// WEBHOOK LOGS
// ============================================================================

/**
 * Get webhook logs
 */
export const usePOSWebhookLogs = (
  params: {
    tenant_id: string;
    pos_system?: POSSystem;
    status?: string;
    limit?: number;
    offset?: number;
  },
  options?: Omit<UseQueryOptions<{
    webhook_logs: POSWebhookLog[];
    total: number;
    has_more: boolean;
  }, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery({
    queryKey: posKeys.webhookLogsList(params.tenant_id, params),
    queryFn: () => posService.getWebhookLogs(params),
    enabled: !!params.tenant_id,
    staleTime: 30 * 1000, // 30 seconds
    ...options,
  });
};

/**
 * Get webhook status for a POS system
 */
export const useWebhookStatus = (
  pos_system: POSSystem,
  options?: Omit<UseQueryOptions<{
    pos_system: string;
    status: string;
    endpoint: string;
    supported_events: {
      events: string[];
      format: string;
      authentication: string;
    };
    last_received?: string;
    total_received: number;
  }, ApiError>, 'queryKey' | 'queryFn'>
) => {
  return useQuery({
    queryKey: [...posKeys.webhookLogs(), 'status', pos_system],
    queryFn: () => posService.getWebhookStatus(pos_system),
    enabled: !!pos_system,
    staleTime: 5 * 60 * 1000, // 5 minutes - webhook status doesn't change often
    ...options,
  });
};

// ============================================================================
// UTILITY HOOKS
// ============================================================================

/**
 * Hook to get POS service utility functions
 */
export const usePOSUtils = () => {
  return {
    formatPrice: posService.formatPrice,
    getPOSSystemDisplayName: posService.getPOSSystemDisplayName,
    getConnectionStatusColor: posService.getConnectionStatusColor,
    getSyncStatusColor: posService.getSyncStatusColor,
    formatSyncInterval: posService.formatSyncInterval,
    validateCredentials: posService.validateCredentials,
  };
};

// ============================================================================
// COMPOSITE HOOKS (Convenience)
// ============================================================================

/**
 * Hook that combines configurations and supported systems for the configuration UI
 */
export const usePOSConfigurationData = (tenantId: string) => {
  const configurationsQuery = usePOSConfigurations(
    { tenant_id: tenantId },
    { enabled: !!tenantId }
  );
  
  const supportedSystemsQuery = useSupportedPOSSystems();
  
  return {
    configurations: configurationsQuery.data?.configurations || [],
    supportedSystems: supportedSystemsQuery.data?.systems || [],
    isLoading: configurationsQuery.isLoading || supportedSystemsQuery.isLoading,
    error: configurationsQuery.error || supportedSystemsQuery.error,
    refetch: () => {
      configurationsQuery.refetch();
      supportedSystemsQuery.refetch();
    },
  };
};

/**
 * Hook for POS configuration management with all CRUD operations
 */
export const usePOSConfigurationManager = (tenantId: string) => {
  const utils = usePOSUtils();
  
  const createMutation = useCreatePOSConfiguration();
  const updateMutation = useUpdatePOSConfiguration();
  const deleteMutation = useDeletePOSConfiguration();
  const testConnectionMutation = useTestPOSConnection();
  
  return {
    // Utility functions
    ...utils,
    
    // Mutations
    createConfiguration: createMutation.mutateAsync,
    updateConfiguration: updateMutation.mutateAsync,
    deleteConfiguration: deleteMutation.mutateAsync,
    testConnection: testConnectionMutation.mutateAsync,
    
    // Mutation states
    isCreating: createMutation.isPending,
    isUpdating: updateMutation.isPending,
    isDeleting: deleteMutation.isPending,
    isTesting: testConnectionMutation.isPending,
    
    // Errors
    createError: createMutation.error,
    updateError: updateMutation.error,
    deleteError: deleteMutation.error,
    testError: testConnectionMutation.error,
  };
};