import { useCallback } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { supabase } from '@/lib/supabaseClient';
import { useToast } from '@/hooks/use-toast';
import { logger } from '@/lib/logger';
import { getErrorMessage, handleError, isSupabaseConnectionError } from '@/lib/errorHandler';
import { validateMultipleItems } from '@/lib/entityValidationSchemas';
import { invokeWithTracking } from '@/lib/edgeFunctionTracking';
import type { User } from '@supabase/supabase-js';
import type { ModerationItem } from '@/types/moderation';

/**
 * Configuration for moderation actions
 */
export interface ModerationActionsConfig {
  user: User | null;
  onActionStart: (itemId: string) => void;
  onActionComplete: () => void;
  currentLockSubmissionId?: string | null;
}

/**
 * Return type for useModerationActions
 */
export interface ModerationActions {
  performAction: (item: ModerationItem, action: 'approved' | 'rejected', moderatorNotes?: string) => Promise<void>;
  deleteSubmission: (item: ModerationItem) => Promise<void>;
  resetToPending: (item: ModerationItem) => Promise<void>;
  retryFailedItems: (item: ModerationItem) => Promise<void>;
  escalateSubmission: (item: ModerationItem, reason: string) => Promise<void>;
}

/**
 * Hook for moderation action handlers
 * Extracted from useModerationQueueManager for better separation of concerns
 * 
 * @param config - Configuration object with user, callbacks, and dependencies
 * @returns Object with action handler functions
 */
export function useModerationActions(config: ModerationActionsConfig): ModerationActions {
  const { user, onActionStart, onActionComplete } = config;
  const { toast } = useToast();
  const queryClient = useQueryClient();

  /**
   * Perform moderation action (approve/reject) with optimistic updates
   */
  const performActionMutation = useMutation({
    mutationFn: async ({ 
      item, 
      action, 
      moderatorNotes 
    }: { 
      item: ModerationItem; 
      action: 'approved' | 'rejected'; 
      moderatorNotes?: string;
    }) => {
        // Handle photo submissions
        if (action === 'approved' && item.submission_type === 'photo') {
          const { data: photoSubmission, error: fetchError } = await supabase
            .from('photo_submissions')
            .select(`
              *,
              items:photo_submission_items(*),
              submission:content_submissions!inner(user_id)
            `)
            .eq('submission_id', item.id)
            .single();

          // Add explicit error handling
          if (fetchError) {
            throw new Error(`Failed to fetch photo submission: ${fetchError.message}`);
          }

          if (!photoSubmission) {
            throw new Error('Photo submission not found');
          }

          // Type assertion with validation
          const typedPhotoSubmission = photoSubmission as {
            id: string;
            entity_id: string;
            entity_type: string;
            items: Array<{
              id: string;
              cloudflare_image_id: string;
              cloudflare_image_url: string;
              caption?: string;
              title?: string;
              date_taken?: string;
              date_taken_precision?: string;
              order_index: number;
            }>;
            submission: { user_id: string };
          };

          // Validate required fields
          if (!typedPhotoSubmission.items || typedPhotoSubmission.items.length === 0) {
            throw new Error('No photo items found in submission');
          }

          const { data: existingPhotos } = await supabase
            .from('photos')
            .select('id')
            .eq('submission_id', item.id);

          if (!existingPhotos || existingPhotos.length === 0) {
            const photoRecords = typedPhotoSubmission.items.map((photoItem) => ({
              entity_id: typedPhotoSubmission.entity_id,
              entity_type: typedPhotoSubmission.entity_type,
              cloudflare_image_id: photoItem.cloudflare_image_id,
              cloudflare_image_url: photoItem.cloudflare_image_url,
              title: photoItem.title || null,
              caption: photoItem.caption || null,
              date_taken: photoItem.date_taken || null,
              order_index: photoItem.order_index,
              submission_id: item.id,
              submitted_by: typedPhotoSubmission.submission?.user_id,
              approved_by: user?.id,
              approved_at: new Date().toISOString(),
            }));

            await supabase.from('photos').insert(photoRecords);
          }
        }

        // Check for submission items
        const { data: submissionItems } = await supabase
          .from('submission_items')
          .select('id, status')
          .eq('submission_id', item.id)
          .in('status', ['pending', 'rejected']);

        if (submissionItems && submissionItems.length > 0) {
          if (action === 'approved') {
            // Fetch full item data for validation with relational joins
            const { data: fullItems, error: itemError } = await supabase
              .from('submission_items')
              .select(`
                id,
                item_type,
                park_submission:park_submissions!submission_items_park_submission_id_fkey(*),
                ride_submission:ride_submissions!submission_items_ride_submission_id_fkey(*),
                company_submission:company_submissions!submission_items_company_submission_id_fkey(*),
                ride_model_submission:ride_model_submissions!submission_items_ride_model_submission_id_fkey(*),
                timeline_event_submission:timeline_event_submissions!submission_items_timeline_event_submission_id_fkey(*),
                photo_submission:photo_submissions!submission_items_photo_submission_id_fkey(*)
              `)
              .eq('submission_id', item.id)
              .in('status', ['pending', 'rejected']);
            
            if (itemError) {
              throw new Error(`Failed to fetch submission items: ${itemError.message}`);
            }
            
            if (fullItems && fullItems.length > 0) {
              console.info('[Submission Flow] Preparing items for validation', {
                submissionId: item.id,
                itemCount: fullItems.length,
                itemTypes: fullItems.map(i => i.item_type),
                timestamp: new Date().toISOString()
              });

              // Transform to include item_data
              const itemsWithData = fullItems.map(item => {
                let itemData = {};
                switch (item.item_type) {
                  case 'park': {
                    const parkSub = (item.park_submission as any) || {};
                    itemData = {
                      ...parkSub,
                      // Transform temp_location_data → location for validation
                      location: parkSub.temp_location_data || undefined,
                      temp_location_data: undefined
                    };
                    
                    console.info('[Submission Flow] Transformed park data for validation', {
                      itemId: item.id,
                      hasLocation: !!parkSub.temp_location_data,
                      locationData: parkSub.temp_location_data,
                      transformedHasLocation: !!(itemData as any).location,
                      timestamp: new Date().toISOString()
                    });
                    break;
                  }
                  case 'ride':
                    itemData = item.ride_submission || {};
                    break;
                  case 'operator':
                  case 'manufacturer':
                  case 'designer':
                  case 'property_owner':
                    itemData = {
                      ...(item.company_submission || {}),
                      company_id: item.company_submission?.id // Use company_submission ID for validation
                    };
                    break;
                  case 'ride_model':
                    itemData = {
                      ...(item.ride_model_submission || {}),
                      ride_model_id: item.ride_model_submission?.id // Use ride_model_submission ID for validation
                    };
                    break;
                  case 'milestone':
                  case 'timeline_event':
                    itemData = item.timeline_event_submission || {};
                    break;
                  case 'photo':
                  case 'photo_edit':
                  case 'photo_delete':
                    itemData = item.photo_submission || {};
                    break;
                  default:
                    logger.warn(`Unknown item_type in validation: ${item.item_type}`);
                    itemData = {};
                }
                return {
                  id: item.id,
                  item_type: item.item_type,
                  item_data: itemData
                };
              });
              
              // Run validation on all items
              try {
                console.info('[Submission Flow] Starting validation', {
                  submissionId: item.id,
                  itemCount: itemsWithData.length,
                  itemTypes: itemsWithData.map(i => i.item_type),
                  timestamp: new Date().toISOString()
                });

                const validationResults = await validateMultipleItems(itemsWithData);
                
                console.info('[Submission Flow] Validation completed', {
                  submissionId: item.id,
                  resultsCount: validationResults.size,
                  timestamp: new Date().toISOString()
                });

                // Check for blocking errors
                const itemsWithBlockingErrors = itemsWithData.filter(item => {
                  const result = validationResults.get(item.id);
                  return result && result.blockingErrors.length > 0;
                });
                
                // CRITICAL: Block approval if any item has blocking errors
                if (itemsWithBlockingErrors.length > 0) {
                  console.warn('[Submission Flow] Validation found blocking errors', {
                    submissionId: item.id,
                    itemsWithErrors: itemsWithBlockingErrors.map(i => ({
                      itemId: i.id,
                      itemType: i.item_type,
                      errors: validationResults.get(i.id)?.blockingErrors
                    })),
                    timestamp: new Date().toISOString()
                  });

                  // Log detailed blocking errors
                  itemsWithBlockingErrors.forEach(item => {
                    const result = validationResults.get(item.id);
                    logger.error('Validation blocking approval', {
                      submissionId: item.id,
                      itemId: item.id,
                      itemType: item.item_type,
                      blockingErrors: result?.blockingErrors
                    });
                  });
                  
                  const errorDetails = itemsWithBlockingErrors.map(item => {
                    const result = validationResults.get(item.id);
                    const itemName = (item.item_data as any)?.name || item.item_type;
                    const errors = result?.blockingErrors.map(e => `${e.field}: ${e.message}`).join(', ');
                    return `${itemName} - ${errors}`;
                  }).join('; ');
                  
                  throw new Error(`Validation failed: ${errorDetails}`);
                }
                
                // Check for warnings (optional - can proceed but inform user)
                const itemsWithWarnings = itemsWithData.filter(item => {
                  const result = validationResults.get(item.id);
                  return result && result.warnings.length > 0;
                });
                
                if (itemsWithWarnings.length > 0) {
                  logger.info('Approval proceeding with warnings', {
                    submissionId: item.id,
                    warningCount: itemsWithWarnings.length
                  });
                }
              } catch (error) {
                // Check if this is a validation error or system error
                if (getErrorMessage(error).includes('Validation failed:')) {
                  // This is expected - validation rules preventing approval
                  handleError(error, {
                    action: 'Validation Blocked Approval',
                    userId: user?.id,
                    metadata: {
                      submissionId: item.id,
                      submissionType: item.submission_type,
                      selectedItemCount: itemsWithData.length
                    }
                  });
                  
                  toast({
                    title: 'Cannot Approve - Validation Errors',
                    description: getErrorMessage(error),
                    variant: 'destructive',
                  });
                  
                  // Return early - do NOT proceed with approval
                  return;
                } else {
                  // Unexpected validation system error
                  const errorId = handleError(error, {
                    action: 'Validation System Failure',
                    userId: user?.id,
                    metadata: {
                      submissionId: item.id,
                      submissionType: item.submission_type,
                      phase: 'validation'
                    }
                  });
                  
                  toast({
                    title: 'Validation System Error',
                    description: `Unable to validate submission (ref: ${errorId.slice(0, 8)})`,
                    variant: 'destructive',
                  });
                  
                  // Return early - do NOT proceed with approval
                  return;
                }
              }
            }

            const { data, error, requestId, attempts } = await invokeWithTracking(
              'process-selective-approval',
              {
                itemIds: submissionItems.map((i) => i.id),
                submissionId: item.id,
              },
              config.user?.id,
              undefined,
              undefined,
              30000, // 30s timeout
              { maxAttempts: 3, baseDelay: 1500 } // Critical operation - retry config
            );
            
            // Log if retries were needed
            if (attempts && attempts > 1) {
              logger.log(`Approval succeeded after ${attempts} attempts for ${item.id}`);
            }

            if (error) throw error;

            toast({
              title: 'Submission Approved',
              description: `Successfully processed ${submissionItems.length} item(s)${requestId ? ` (Request: ${requestId.substring(0, 8)})` : ''}`,
            });
            return;
          } else if (action === 'rejected') {
            await supabase
              .from('submission_items')
              .update({
                status: 'rejected',
                rejection_reason: moderatorNotes || 'Parent submission rejected',
                updated_at: new Date().toISOString(),
              })
              .eq('submission_id', item.id)
              .eq('status', 'pending');
          }
        }

        // Standard update
        const table = item.type === 'review' ? 'reviews' : 'content_submissions';
        const statusField = item.type === 'review' ? 'moderation_status' : 'status';
        const timestampField = item.type === 'review' ? 'moderated_at' : 'reviewed_at';
        const reviewerField = item.type === 'review' ? 'moderated_by' : 'reviewer_id';

        const updateData: any = {
          [statusField]: action,
          [timestampField]: new Date().toISOString(),
        };

        if (user) {
          updateData[reviewerField] = user.id;
        }

        if (moderatorNotes) {
          updateData.reviewer_notes = moderatorNotes;
        }

        const { error } = await supabase.from(table).update(updateData).eq('id', item.id);

        if (error) throw error;

        // Log audit trail for review moderation
        if (table === 'reviews' && user) {
          try {
            // Extract entity information from item content
            const entityType = item.content?.ride_id ? 'ride' : item.content?.park_id ? 'park' : 'unknown';
            const entityId = item.content?.ride_id || item.content?.park_id || null;
            
            await supabase.rpc('log_admin_action', {
              _admin_user_id: user.id,
              _target_user_id: item.user_id,
              _action: `review_${action}`,
              _details: {
                review_id: item.id,
                entity_type: entityType,
                entity_id: entityId,
                moderator_notes: moderatorNotes
              }
            });
          } catch (auditError) {
            // Silent - audit logging is non-critical
          }
        }

        toast({
          title: `Content ${action}`,
          description: `The ${item.type} has been ${action}`,
        });

      logger.log(`✅ Action ${action} completed for ${item.id}`);
      return { item, action };
    },
    onMutate: async ({ item, action }) => {
      // Cancel outgoing refetches
      await queryClient.cancelQueries({ queryKey: ['moderation-queue'] });
      
      // Snapshot previous value
      const previousData = queryClient.getQueryData(['moderation-queue']);
      
      // Optimistically update cache
      queryClient.setQueriesData({ queryKey: ['moderation-queue'] }, (old: any) => {
        if (!old?.submissions) return old;
        
        return {
          ...old,
          submissions: old.submissions.map((i: ModerationItem) =>
            i.id === item.id 
              ? { 
                  ...i, 
                  status: action, 
                  _optimistic: true,
                  reviewed_at: new Date().toISOString(),
                  reviewer_id: user?.id,
                } 
              : i
          ),
        };
      });
      
      return { previousData };
    },
    onError: (error: any, variables, context) => {
      // Rollback optimistic update
      if (context?.previousData) {
        queryClient.setQueryData(['moderation-queue'], context.previousData);
      }

      // Enhanced error handling with reference ID and network detection
      const isNetworkError = isSupabaseConnectionError(error);
      const errorMessage = getErrorMessage(error) || `Failed to ${variables.action} content`;
      
      toast({
        title: isNetworkError ? 'Connection Error' : 'Action Failed',
        description: errorMessage,
        variant: 'destructive',
      });

      logger.error('Moderation action failed', {
        itemId: variables.item.id,
        action: variables.action,
        error: errorMessage,
        errorId: error.errorId,
        isNetworkError,
      });
    },
    onSuccess: (data) => {
      if (data) {
        toast({
          title: `Content ${data.action}`,
          description: `The ${data.item.type} has been ${data.action}`,
        });
      }
    },
    onSettled: () => {
      // Always refetch to ensure consistency
      queryClient.invalidateQueries({ queryKey: ['moderation-queue'] });
      onActionComplete();
    },
  });

  /**
   * Wrapper function that handles loading states and error tracking
   */
  const performAction = useCallback(
    async (item: ModerationItem, action: 'approved' | 'rejected', moderatorNotes?: string) => {
      onActionStart(item.id);
      try {
        await performActionMutation.mutateAsync({ item, action, moderatorNotes });
      } catch (error) {
        const errorId = handleError(error, {
          action: `Moderation ${action}`,
          userId: user?.id,
          metadata: {
            submissionId: item.id,
            submissionType: item.submission_type,
            itemType: item.type,
            hasSubmissionItems: item.submission_items?.length ?? 0,
            moderatorNotes: moderatorNotes?.substring(0, 100),
          },
        });
        
        // Attach error ID for UI display
        const enhancedError = error instanceof Error 
          ? Object.assign(error, { errorId })
          : { message: getErrorMessage(error), errorId };
        throw enhancedError;
      }
    },
    [onActionStart, performActionMutation, user]
  );

  /**
   * Delete a submission permanently
   */
  const deleteSubmission = useCallback(
    async (item: ModerationItem) => {
      if (item.type !== 'content_submission') return;

      onActionStart(item.id);

      try {
        // Fetch submission details for audit log
        const { data: submission } = await supabase
          .from('content_submissions')
          .select('user_id, submission_type, status')
          .eq('id', item.id)
          .single();

        const { error } = await supabase.from('content_submissions').delete().eq('id', item.id);

        if (error) throw error;

        // Log audit trail for deletion
        if (user && submission) {
          try {
            await supabase.rpc('log_admin_action', {
              _admin_user_id: user.id,
              _target_user_id: submission.user_id,
              _action: 'submission_deleted',
              _details: {
                submission_id: item.id,
                submission_type: submission.submission_type,
                status_when_deleted: submission.status
              }
            });
          } catch (auditError) {
            // Silent - audit logging is non-critical
          }
        }

        toast({
          title: 'Submission deleted',
          description: 'The submission has been permanently deleted',
        });

        logger.log(`✅ Submission ${item.id} deleted`);
      } catch (error: unknown) {
        const errorId = handleError(error, {
          action: 'Delete Submission',
          userId: user?.id,
          metadata: {
            submissionId: item.id,
            submissionType: item.submission_type,
          },
        });
        
        logger.error('Failed to delete submission', { 
          submissionId: item.id,
          errorId,
        });
        const enhancedError = error instanceof Error 
          ? Object.assign(error, { errorId })
          : { message: getErrorMessage(error), errorId };
        throw enhancedError;
      } finally {
        onActionComplete();
      }
    },
    [toast, onActionStart, onActionComplete]
  );

  /**
   * Reset submission to pending status
   */
  const resetToPending = useCallback(
    async (item: ModerationItem) => {
      onActionStart(item.id);

      try {
        const { resetRejectedItemsToPending } = await import('@/lib/submissionItemsService');
        await resetRejectedItemsToPending(item.id);

        // Log audit trail for reset
        if (user) {
          try {
            await supabase.rpc('log_admin_action', {
              _admin_user_id: user.id,
              _target_user_id: item.user_id,
              _action: 'submission_reset',
              _details: {
                submission_id: item.id,
                submission_type: item.submission_type
              }
            });
          } catch (auditError) {
            // Silent - audit logging is non-critical
          }
        }

        toast({
          title: 'Reset Complete',
          description: 'Submission and all items have been reset to pending status',
        });

        logger.log(`✅ Submission ${item.id} reset to pending`);
      } catch (error: unknown) {
        const errorId = handleError(error, {
          action: 'Reset to Pending',
          userId: user?.id,
          metadata: {
            submissionId: item.id,
            submissionType: item.submission_type,
          },
        });
        
        logger.error('Failed to reset status', { 
          submissionId: item.id,
          errorId,
        });
        const enhancedError = error instanceof Error 
          ? Object.assign(error, { errorId })
          : { message: getErrorMessage(error), errorId };
        throw enhancedError;
      } finally {
        onActionComplete();
      }
    },
    [toast, onActionStart, onActionComplete]
  );

  /**
   * Retry failed items in a submission
   */
  const retryFailedItems = useCallback(
    async (item: ModerationItem) => {
      onActionStart(item.id);
      let failedItemsCount = 0;

      try {
        const { data: failedItems } = await supabase
          .from('submission_items')
          .select('id')
          .eq('submission_id', item.id)
          .eq('status', 'rejected');

        if (!failedItems || failedItems.length === 0) {
          toast({
            title: 'No Failed Items',
            description: 'All items have been processed successfully',
          });
          return;
        }

        failedItemsCount = failedItems.length;

        const { data, error, requestId, attempts } = await invokeWithTracking(
          'process-selective-approval',
          {
            itemIds: failedItems.map((i) => i.id),
            submissionId: item.id,
          },
          config.user?.id,
          undefined,
          undefined,
          30000,
          { maxAttempts: 3, baseDelay: 1500 } // Retry for failed items
        );
        
        if (attempts && attempts > 1) {
          logger.log(`Retry succeeded after ${attempts} attempts for ${item.id}`);
        }

        if (error) throw error;

        // Log audit trail for retry
        if (user) {
          try {
            await supabase.rpc('log_admin_action', {
              _admin_user_id: user.id,
              _target_user_id: item.user_id,
              _action: 'submission_retried',
              _details: {
                submission_id: item.id,
                submission_type: item.submission_type,
                items_retried: failedItems.length,
                request_id: requestId
              }
            });
          } catch (auditError) {
            // Silent - audit logging is non-critical
          }
        }

        toast({
          title: 'Items Retried',
          description: `Successfully retried ${failedItems.length} failed item(s)${requestId ? ` (Request: ${requestId.substring(0, 8)})` : ''}`,
        });

        logger.log(`✅ Retried ${failedItems.length} failed items for ${item.id}`);
      } catch (error: unknown) {
        const errorId = handleError(error, {
          action: 'Retry Failed Items',
          userId: user?.id,
          metadata: {
            submissionId: item.id,
            failedItemsCount,
          },
        });
        
        logger.error('Failed to retry items', { 
          submissionId: item.id,
          errorId,
        });
        const enhancedError = error instanceof Error 
          ? Object.assign(error, { errorId })
          : { message: getErrorMessage(error), errorId };
        throw enhancedError;
      } finally {
        onActionComplete();
      }
    },
    [toast, onActionStart, onActionComplete, user]
  );

  /**
   * Escalate submission for admin review
   * Consolidates escalation logic with comprehensive error handling
   */
  const escalateSubmission = useCallback(
    async (item: ModerationItem, reason: string) => {
      if (!user?.id) {
        toast({
          title: 'Authentication Required',
          description: 'You must be logged in to escalate submissions',
          variant: 'destructive',
        });
        return;
      }

      onActionStart(item.id);

      try {
        // Call edge function for email notification with retry
        const { error: edgeFunctionError, requestId, attempts } = await invokeWithTracking(
          'send-escalation-notification',
          {
            submissionId: item.id,
            escalationReason: reason,
            escalatedBy: user.id,
          },
          user.id,
          undefined,
          undefined,
          45000, // Longer timeout for email sending
          { maxAttempts: 3, baseDelay: 2000 } // Retry for email delivery
        );
        
        if (attempts && attempts > 1) {
          logger.log(`Escalation email sent after ${attempts} attempts`);
        }

        if (edgeFunctionError) {
          // Edge function failed - log and show fallback toast
          handleError(edgeFunctionError, {
            action: 'Send escalation notification',
            userId: user.id,
            metadata: {
              submissionId: item.id,
              reason: reason.substring(0, 100),
              fallbackUsed: true,
            },
          });

          toast({
            title: 'Escalated (Email Failed)',
            description: 'Submission escalated but notification email could not be sent',
          });
        } else {
          toast({
            title: 'Escalated Successfully',
            description: `Submission escalated and admin notified${requestId ? ` (${requestId.substring(0, 8)})` : ''}`,
          });
        }

        // Invalidate cache
        queryClient.invalidateQueries({ queryKey: ['moderation-queue'] });

        logger.log(`✅ Submission ${item.id} escalated`);
      } catch (error: unknown) {
        const errorId = handleError(error, {
          action: 'Escalate Submission',
          userId: user.id,
          metadata: {
            submissionId: item.id,
            submissionType: item.submission_type,
            reason: reason.substring(0, 100),
          },
        });

        logger.error('Escalation failed', {
          submissionId: item.id,
          errorId,
        });
        
        // Re-throw to allow UI to show retry option
        const enhancedError = error instanceof Error 
          ? Object.assign(error, { errorId })
          : { message: getErrorMessage(error), errorId };
        throw enhancedError;
      } finally {
        onActionComplete();
      }
    },
    [user, toast, onActionStart, onActionComplete, queryClient]
  );

  return {
    performAction,
    deleteSubmission,
    resetToPending,
    retryFailedItems,
    escalateSubmission,
  };
}
