import { useCallback } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { supabase } from '@/integrations/supabase/client';
import { useToast } from '@/hooks/use-toast';
import { logger } from '@/lib/logger';
import { getErrorMessage } 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>;
}

/**
 * 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!item_data_id(*),
                ride_submission:ride_submissions!item_data_id(*)
              `)
              .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) {
              // Transform to include item_data
              const itemsWithData = fullItems.map(item => {
                let itemData = {};
                switch (item.item_type) {
                  case 'park':
                    itemData = item.park_submission || {};
                    break;
                  case 'ride':
                    itemData = item.ride_submission || {};
                    break;
                  default:
                    itemData = {};
                }
                return {
                  id: item.id,
                  item_type: item.item_type,
                  item_data: itemData
                };
              });
              
              // Run validation on all items
              const validationResults = await validateMultipleItems(itemsWithData);
              
              // 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) {
                const errorDetails = itemsWithBlockingErrors.map(item => {
                  const result = validationResults.get(item.id);
                  return `${item.item_type}: ${result?.blockingErrors[0]?.message || 'Unknown error'}`;
                }).join(', ');
                
                toast({
                  title: 'Cannot Approve - Validation Errors',
                  description: `${itemsWithBlockingErrors.length} item(s) have blocking errors that must be fixed first. ${errorDetails}`,
                  variant: 'destructive',
                });
                
                // Return early - do NOT proceed with approval
                return;
              }
              
              // 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
                });
              }
            }

            const { data, error, requestId } = await invokeWithTracking(
              'process-selective-approval',
              {
                itemIds: submissionItems.map((i) => i.id),
                submissionId: item.id,
              },
              config.user?.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) {
            logger.error('Failed to log review moderation audit', { error: auditError });
          }
        }

        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, variables, context) => {
      // Rollback on error
      if (context?.previousData) {
        queryClient.setQueryData(['moderation-queue'], context.previousData);
      }
      
      logger.error('❌ Error performing action:', { error: getErrorMessage(error) });
      toast({
        title: 'Action Failed',
        description: getErrorMessage(error) || `Failed to ${variables.action} content`,
        variant: 'destructive',
      });
    },
    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 for performAction mutation to maintain API compatibility
   */
  const performAction = useCallback(
    async (item: ModerationItem, action: 'approved' | 'rejected', moderatorNotes?: string) => {
      onActionStart(item.id);
      await performActionMutation.mutateAsync({ item, action, moderatorNotes });
    },
    [onActionStart, performActionMutation]
  );

  /**
   * 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) {
            logger.error('Failed to log submission deletion audit', { error: auditError });
          }
        }

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

        logger.log(`✅ Submission ${item.id} deleted`);
      } catch (error: unknown) {
        logger.error('❌ Error deleting submission:', { error: getErrorMessage(error) });
        toast({
          title: 'Error',
          description: getErrorMessage(error),
          variant: 'destructive',
        });
        throw error;
      } 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) {
            logger.error('Failed to log submission reset audit', { error: auditError });
          }
        }

        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) {
        logger.error('❌ Error resetting submission:', { error: getErrorMessage(error) });
        toast({
          title: 'Reset Failed',
          description: getErrorMessage(error),
          variant: 'destructive',
        });
      } finally {
        onActionComplete();
      }
    },
    [toast, onActionStart, onActionComplete]
  );

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

      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;
        }

        const { data, error, requestId } = await invokeWithTracking(
          'process-selective-approval',
          {
            itemIds: failedItems.map((i) => i.id),
            submissionId: item.id,
          },
          config.user?.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) {
            logger.error('Failed to log submission retry audit', { error: auditError });
          }
        }

        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) {
        logger.error('❌ Error retrying items:', { error: getErrorMessage(error) });
        toast({
          title: 'Retry Failed',
          description: getErrorMessage(error) || 'Failed to retry items',
          variant: 'destructive',
        });
      } finally {
        onActionComplete();
      }
    },
    [toast, onActionStart, onActionComplete]
  );

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