import { useState, useEffect, useCallback, useRef } from 'react';
import { supabase } from '@/integrations/supabase/client';
import { useAuth } from './useAuth';
import { useToast } from './use-toast';
import { getErrorMessage } from '@/lib/errorHandler';
import { getSubmissionTypeLabel } from '@/lib/moderation/entities';

interface QueuedSubmission {
  submission_id: string;
  submission_type: string;
  waiting_time: string; // PostgreSQL interval format
}

interface LockState {
  submissionId: string;
  expiresAt: Date;
  autoReleaseTimer?: NodeJS.Timeout;
}

interface QueueStats {
  pendingCount: number;
  assignedToMe: number;
  avgWaitHours: number;
}

interface UseModerationQueueConfig {
  onLockStateChange?: () => void;
}

export const useModerationQueue = (config?: UseModerationQueueConfig) => {
  const { onLockStateChange } = config || {};
  const [currentLock, setCurrentLock] = useState<LockState | null>(null);
  const [queueStats, setQueueStats] = useState<QueueStats | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const lockTimerRef = useRef<NodeJS.Timeout | null>(null);
  const { user } = useAuth();
  const { toast } = useToast();

  // Auto-release expired locks periodically
  useEffect(() => {
    if (!user) return;

    // Call release_expired_locks every 2 minutes
    const releaseInterval = setInterval(async () => {
      try {
        await supabase.rpc('release_expired_locks');
      } catch (error: unknown) {
        // Silent failure - lock release happens periodically
      }
    }, 120000); // 2 minutes

    return () => clearInterval(releaseInterval);
  }, [user]);

  // Fetch queue statistics
  const fetchStats = useCallback(async () => {
    if (!user) return;

    try {
      const { data: slaData } = await supabase
        .from('moderation_sla_metrics')
        .select('pending_count, avg_wait_hours');

      const { count: assignedCount } = await supabase
        .from('content_submissions')
        .select('id', { count: 'exact', head: true })
        .eq('assigned_to', user.id)
        .gt('locked_until', new Date().toISOString());

      if (slaData) {
        const totals = slaData.reduce(
          (acc, row) => ({
            pendingCount: acc.pendingCount + (row.pending_count || 0),
            avgWaitHours: acc.avgWaitHours + (row.avg_wait_hours || 0),
          }),
          { pendingCount: 0, avgWaitHours: 0 }
        );

        setQueueStats({
          pendingCount: totals.pendingCount,
          assignedToMe: assignedCount || 0,
          avgWaitHours: slaData.length > 0 ? totals.avgWaitHours / slaData.length : 0,
        });
      }
    } catch (error: unknown) {
      // Silent failure - stats are refreshed periodically
    }
  }, [user]);

  // Start countdown timer for lock expiry with improved memory leak prevention
  const startLockTimer = useCallback((expiresAt: Date) => {
    // Track if component is still mounted
    let isMounted = true;
    
    // Clear any existing timer first to prevent leaks
    if (lockTimerRef.current) {
      clearInterval(lockTimerRef.current);
      lockTimerRef.current = null;
    }

    lockTimerRef.current = setInterval(() => {
      // Prevent timer execution if component unmounted
      if (!isMounted) {
        if (lockTimerRef.current) {
          clearInterval(lockTimerRef.current);
          lockTimerRef.current = null;
        }
        return;
      }

      const now = new Date();
      const timeLeft = expiresAt.getTime() - now.getTime();

      if (timeLeft <= 0) {
        // Clear timer before showing toast to prevent double-firing
        if (lockTimerRef.current) {
          clearInterval(lockTimerRef.current);
          lockTimerRef.current = null;
        }

        setCurrentLock(null);
        
        toast({
          title: 'Lock Expired',
          description: 'Your review lock has expired. Claim another submission to continue.',
          variant: 'destructive',
        });

        if (onLockStateChange) {
          onLockStateChange();
        }
      }
    }, 1000);

    // Return cleanup function
    return () => {
      isMounted = false;
      if (lockTimerRef.current) {
        clearInterval(lockTimerRef.current);
        lockTimerRef.current = null;
      }
    };
  }, [toast, onLockStateChange]);

  // Clean up timer on unmount
  useEffect(() => {
    return () => {
      // Comprehensive cleanup on unmount
      if (lockTimerRef.current) {
        clearInterval(lockTimerRef.current);
        lockTimerRef.current = null;
      }
    };
  }, []);

  // Claim a specific submission (CRM-style claim any)
  const extendLock = useCallback(async (submissionId: string): Promise<boolean> => {
    if (!user?.id) return false;

    setIsLoading(true);
    try {
      const { data, error } = await supabase.rpc('extend_submission_lock', {
        submission_id: submissionId,
        moderator_id: user.id,
        extension_duration: '15 minutes',
      });

      if (error) throw error;

      if (data) {
        const newExpiresAt = new Date(data);
        setCurrentLock((prev) =>
          prev?.submissionId === submissionId
            ? { ...prev, expiresAt: newExpiresAt }
            : prev
        );
        startLockTimer(newExpiresAt);

        toast({
          title: 'Lock Extended',
          description: 'Lock extended for 15 more minutes',
        });

        return true;
      }

      return false;
    } catch (error: unknown) {
      toast({
        title: 'Error',
        description: getErrorMessage(error),
        variant: 'destructive',
      });
      return false;
    } finally {
      setIsLoading(false);
    }
  }, [user, toast, startLockTimer]);

  // Release lock (manual or on completion)
  const releaseLock = useCallback(async (
    submissionId: string,
    silent: boolean = false
  ): Promise<boolean> => {
    if (!user?.id) return false;

    setIsLoading(true);
    
    try {
      const { data, error } = await supabase.rpc('release_submission_lock', {
        submission_id: submissionId,
        moderator_id: user.id,
      });

      if (error) throw error;

      // Always clear local state and refresh stats if no error
      setCurrentLock((prev) =>
        prev?.submissionId === submissionId ? null : prev
      );

      if (lockTimerRef.current) {
        clearInterval(lockTimerRef.current);
        lockTimerRef.current = null; // Explicitly null it out
      }

      fetchStats();
      
      // Show appropriate toast based on result (unless silent)
      if (!silent) {
        if (data === true) {
          toast({
            title: 'Lock Released',
            description: 'You can now claim another submission',
          });
        } else {
          toast({
            title: 'Lock Already Released',
            description: 'This submission was already unlocked',
          });
        }
      }
      
      // Trigger refresh callback
      if (onLockStateChange) {
        onLockStateChange();
      }
      
      return data;
    } catch (error: unknown) {
      // Always show error toasts even in silent mode
      toast({
        title: 'Failed to Release Lock',
        description: getErrorMessage(error),
        variant: 'destructive',
      });
      return false;
    } finally {
      setIsLoading(false);
    }
  }, [user, fetchStats, toast, onLockStateChange]);

  // Get time remaining on current lock
  const getTimeRemaining = useCallback((): number | null => {
    if (!currentLock) return null;
    return Math.max(0, currentLock.expiresAt.getTime() - Date.now());
  }, [currentLock]);

  // Escalate submission
  const escalateSubmission = useCallback(async (submissionId: string, reason: string): Promise<boolean> => {
    if (!user?.id) return false;

    setIsLoading(true);
    try {
      const { error } = await supabase
        .from('content_submissions')
        .update({
          escalated: true,
          escalated_at: new Date().toISOString(),
          escalated_by: user.id,
          escalation_reason: reason,
        })
        .eq('id', submissionId);

      if (error) throw error;

      toast({
        title: 'Submission Escalated',
        description: 'This submission has been marked as high priority',
      });

      fetchStats();
      return true;
    } catch (error: unknown) {
      toast({
        title: 'Error',
        description: getErrorMessage(error),
        variant: 'destructive',
      });
      return false;
    } finally {
      setIsLoading(false);
    }
  }, [user, toast, fetchStats]);

  // Claim a specific submission (CRM-style claim any)
  const claimSubmission = useCallback(async (submissionId: string): Promise<boolean> => {
    if (!user?.id) {
      toast({
        title: 'Authentication Required',
        description: 'You must be logged in to claim submissions',
        variant: 'destructive',
      });
      return false;
    }

    setIsLoading(true);
    try {
      // Get submission details FIRST for better toast message
      const { data: submission } = await supabase
        .from('content_submissions')
        .select('id, submission_type')
        .eq('id', submissionId)
        .single();

      const expiresAt = new Date(Date.now() + 15 * 60 * 1000);
      
      const { error } = await supabase
        .from('content_submissions')
        .update({
          assigned_to: user.id,
          assigned_at: new Date().toISOString(),
          locked_until: expiresAt.toISOString(),
        })
        .eq('id', submissionId)
        .or(`assigned_to.is.null,locked_until.lt.${new Date().toISOString()}`); // Only if unclaimed or lock expired

      if (error) throw error;

      setCurrentLock({
        submissionId,
        expiresAt,
      });

      startLockTimer(expiresAt);

      // Enhanced toast with submission type
      const submissionType = submission?.submission_type || 'submission';
      const formattedType = getSubmissionTypeLabel(submissionType);
      toast({
        title: '✅ Submission Claimed',
        description: `${formattedType} locked for 15 minutes. Start reviewing now.`,
        duration: 4000,
      });

      // Force UI refresh to update queue
      fetchStats();
      if (onLockStateChange) {
        onLockStateChange();
      }

      return true;
    } catch (error: unknown) {
      toast({
        title: 'Failed to Claim Submission',
        description: getErrorMessage(error),
        variant: 'destructive',
      });
      return false;
    } finally {
      setIsLoading(false); // Always clear loading state
    }
  }, [user, toast, startLockTimer, fetchStats, onLockStateChange]);

  // Reassign submission
  const reassignSubmission = useCallback(async (submissionId: string, newModeratorId: string): Promise<boolean> => {
    if (!user?.id) return false;

    setIsLoading(true);
    try {
      const { error } = await supabase
        .from('content_submissions')
        .update({
          assigned_to: newModeratorId,
          assigned_at: new Date().toISOString(),
          locked_until: new Date(Date.now() + 15 * 60 * 1000).toISOString(),
        })
        .eq('id', submissionId);

      if (error) throw error;

      // If this was our lock, clear it
      if (currentLock?.submissionId === submissionId) {
        setCurrentLock(null);
        if (lockTimerRef.current) {
          clearInterval(lockTimerRef.current);
        }
      }

      toast({
        title: 'Submission Reassigned',
        description: 'The submission has been assigned to another moderator',
      });

      fetchStats();
      return true;
    } catch (error: unknown) {
      toast({
        title: 'Error',
        description: getErrorMessage(error),
        variant: 'destructive',
      });
      return false;
    } finally {
      setIsLoading(false);
    }
  }, [user, currentLock, toast, fetchStats]);

  // Check if submission is locked by current user
  const isLockedByMe = useCallback((submissionId: string, assignedTo?: string | null, lockedUntil?: string | null): boolean => {
    // Check local state first (optimistic UI - immediate feedback)
    if (currentLock?.submissionId === submissionId) return true;
    
    // Also check database state (source of truth)
    if (assignedTo && lockedUntil && user?.id) {
      const isAssignedToMe = assignedTo === user.id;
      const isLockActive = new Date(lockedUntil) > new Date();
      return isAssignedToMe && isLockActive;
    }
    
    return false;
  }, [currentLock, user]);

  // Check if submission is locked by another moderator
  const isLockedByOther = useCallback((submissionId: string, assignedTo: string | null, lockedUntil: string | null): boolean => {
    if (!assignedTo || !lockedUntil) return false;
    if (user?.id === assignedTo) return false; // It's our lock
    return new Date(lockedUntil) > new Date(); // Lock is still active
  }, [user]);

  // Get lock progress percentage (0-100)
  const getLockProgress = useCallback((): number => {
    const timeLeft = getTimeRemaining();
    if (timeLeft === null) return 0;
    const totalTime = 15 * 60 * 1000; // 15 minutes in ms
    return Math.max(0, Math.min(100, (timeLeft / totalTime) * 100));
  }, [getTimeRemaining]);

  // Auto-release lock after moderation action
  const releaseAfterAction = useCallback(async (submissionId: string, action: 'approved' | 'rejected'): Promise<void> => {
    if (currentLock?.submissionId === submissionId) {
      await releaseLock(submissionId, true); // Silent release
    }
  }, [currentLock, releaseLock]);

  return {
    currentLock,  // Exposed for reactive UI updates
    queueStats,
    isLoading,
    claimSubmission,
    extendLock,
    releaseLock,
    getTimeRemaining,
    escalateSubmission,
    reassignSubmission,
    refreshStats: fetchStats,
    // New helpers
    isLockedByMe,
    isLockedByOther,
    getLockProgress,
    releaseAfterAction,
  };
};

// Helper to format PostgreSQL interval
function formatInterval(interval: string): string {
  const match = interval.match(/(\d+):(\d+):(\d+)/);
  if (!match) return interval;

  const hours = parseInt(match[1]);
  const minutes = parseInt(match[2]);

  if (hours > 24) {
    const days = Math.floor(hours / 24);
    return `${days}d ${hours % 24}h`;
  } else if (hours > 0) {
    return `${hours}h ${minutes}m`;
  } else {
    return `${minutes}m`;
  }
}
