import { useState, useEffect, useCallback, useRef } from 'react';
import { fetchAPI } from '../services/api';

export interface ProgressState {
  percentage: number;
  message: string;
  status: 'pending' | 'processing' | 'completed' | 'error';
  details?: {
    current: number;
    total: number;
    completed: number;
    currentItem?: string;
    phase?: string;
  };
}

export interface ImageQueueItem {
  image_id: number;
  index: number;
  label: string;
  content_title: string;
  status: 'pending' | 'processing' | 'completed' | 'failed';
  progress: number;
  image_url: string | null;
  error: string | null;
}

export interface UseProgressModalReturn {
  progress: ProgressState;
  isOpen: boolean;
  title: string;
  taskId: string | null;
  openModal: (taskId: string, title: string, functionId?: string) => void;
  updateTaskId: (taskId: string) => void;
  closeModal: () => void;
  setError: (errorMessage: string) => void;
  reset: () => void;
  functionId?: string; // AI function ID for tracking
  stepLogs: Array<{
    stepNumber: number;
    stepName: string;
    status: string;
    message: string;
    timestamp?: number;
  }>; // Step logs for debugging
  imageQueue?: ImageQueueItem[]; // Image queue for image generation
}

export function useProgressModal(): UseProgressModalReturn {
  const [isOpen, setIsOpen] = useState(false);
  const [taskId, setTaskId] = useState<string | null>(null);
  const [title, setTitle] = useState('');
  const [functionId, setFunctionId] = useState<string | undefined>(undefined);
  const [progress, setProgress] = useState<ProgressState>({
    percentage: 0,
    message: 'Initializing...',
    status: 'pending',
  });
  
  // Step logs state for debugging
  const [stepLogs, setStepLogs] = useState<Array<{
    stepNumber: number;
    stepName: string;
    status: string;
    message: string;
    timestamp?: number;
  }>>([]);
  
  // Image queue state for image generation
  const [imageQueue, setImageQueue] = useState<ImageQueueItem[] | undefined>(undefined);
  
  // Track displayed percentage and current step for step-based progress
  const displayedPercentageRef = useRef(0);
  const currentStepRef = useRef<string | null>(null);
  const stepTransitionTimeoutRef = useRef<NodeJS.Timeout | null>(null);
  const autoIncrementIntervalRef = useRef<NodeJS.Timeout | null>(null);
  
  // Step mapping with user-friendly messages and percentages
  const getStepInfo = (stepName: string, message: string = '', allSteps: any[] = []): { percentage: number; friendlyMessage: string } => {
    const stepUpper = stepName?.toUpperCase() || '';
    const messageLower = message.toLowerCase();
    
    // Extract values from message and step messages
    const extractNumber = (pattern: RegExp, text: string): string => {
      const match = text.match(pattern);
      return match && match[1] ? match[1] : '';
    };
    
    // Check message first, then all step messages
    let keywordCount = extractNumber(/(\d+)\s+keyword/i, message);
    let clusterCount = extractNumber(/(\d+)\s+cluster/i, message);
    let taskCount = extractNumber(/(\d+)\s+task/i, message);
    let itemCount = extractNumber(/(\d+)\s+item/i, message);
    
    // Also check for "Loaded X items" or "Created X clusters" patterns
    if (!keywordCount && !taskCount && !itemCount) {
      const loadedMatch = extractNumber(/loaded\s+(\d+)\s+items?/i, message);
      if (loadedMatch) itemCount = loadedMatch;
    }
    if (!clusterCount) {
      const createdMatch = extractNumber(/created\s+(\d+)\s+clusters?/i, message);
      if (createdMatch) clusterCount = createdMatch;
    }
    
    // Check all steps if not found in message
    if (!keywordCount && !taskCount && !itemCount) {
      for (const step of allSteps) {
        const stepMsg = step.message || '';
        if (!keywordCount) {
          keywordCount = extractNumber(/(\d+)\s+keyword/i, stepMsg);
        }
        if (!taskCount) {
          taskCount = extractNumber(/(\d+)\s+task/i, stepMsg);
        }
        if (!itemCount) {
          itemCount = extractNumber(/loaded\s+(\d+)\s+items?/i, stepMsg);
        }
        if (!clusterCount) {
          clusterCount = extractNumber(/(\d+)\s+cluster/i, stepMsg) || extractNumber(/created\s+(\d+)\s+clusters?/i, stepMsg);
        }
        if ((keywordCount || taskCount || itemCount) && clusterCount) break;
      }
    }
    
    const finalKeywordCount = keywordCount;
    const finalClusterCount = clusterCount;
    const finalTaskCount = taskCount || itemCount;
    
    // Determine function type from message/title context
    const isContentGeneration = messageLower.includes('content') || messageLower.includes('generating content') || messageLower.includes('article');
    const isClustering = messageLower.includes('cluster') && !messageLower.includes('content');
    const isIdeas = messageLower.includes('idea');
    
    // Map steps to percentages and user-friendly messages
    if (stepUpper.includes('INIT') || stepUpper.includes('INITIALIZ')) {
      return { percentage: 0, friendlyMessage: 'Getting started...' };
    }
    if (stepUpper.includes('PREP') || stepUpper.includes('PREPAR')) {
      if (isContentGeneration) {
        const msg = finalTaskCount ? `Preparing ${finalTaskCount} task${finalTaskCount !== '1' ? 's' : ''}...` : 'Preparing content generation...';
        return { percentage: 10, friendlyMessage: msg };
      } else if (isClustering) {
        const msg = finalKeywordCount ? `Preparing ${finalKeywordCount} keyword${finalKeywordCount !== '1' ? 's' : ''}...` : 'Preparing your keywords...';
        return { percentage: 16, friendlyMessage: msg };
      } else if (isIdeas) {
        const msg = finalClusterCount ? `Preparing ${finalClusterCount} cluster${finalClusterCount !== '1' ? 's' : ''}...` : 'Preparing clusters...';
        return { percentage: 10, friendlyMessage: msg };
      }
      return { percentage: 10, friendlyMessage: 'Preparing...' };
    }
    if (stepUpper.includes('AI_CALL') || stepUpper.includes('CALLING')) {
      if (isContentGeneration) {
        return { percentage: 50, friendlyMessage: 'Writing article with Igny8 Semantic AI...' };
      } else if (isClustering) {
        return { percentage: 50, friendlyMessage: 'Generating clusters with Igny8 Semantic SEO Model...' };
      } else if (isIdeas) {
        return { percentage: 50, friendlyMessage: 'Generating ideas with Igny8 Semantic AI...' };
      }
      return { percentage: 50, friendlyMessage: 'Processing with Igny8 Semantic AI...' };
    }
    if (stepUpper.includes('PARSE') || stepUpper.includes('PARSING')) {
      if (isContentGeneration) {
        return { percentage: 70, friendlyMessage: 'Processing content...' };
      } else if (isClustering) {
        return { percentage: 70, friendlyMessage: 'Organizing results...' };
      } else if (isIdeas) {
        return { percentage: 70, friendlyMessage: 'Processing ideas...' };
      }
      return { percentage: 70, friendlyMessage: 'Processing results...' };
    }
    if (stepUpper.includes('SAVE') || stepUpper.includes('SAVING') || (stepUpper.includes('CREAT') && !stepUpper.includes('CONTENT'))) {
      if (isContentGeneration) {
        const msg = finalTaskCount ? `Saving content for ${finalTaskCount} task${finalTaskCount !== '1' ? 's' : ''}...` : 'Saving content...';
        return { percentage: 85, friendlyMessage: msg };
      } else if (isClustering) {
        const msg = finalClusterCount ? `Saving ${finalClusterCount} cluster${finalClusterCount !== '1' ? 's' : ''}...` : 'Saving clusters...';
        return { percentage: 85, friendlyMessage: msg };
      } else if (isIdeas) {
        const msg = finalTaskCount ? `Saving ${finalTaskCount} idea${finalTaskCount !== '1' ? 's' : ''}...` : 'Saving ideas...';
        return { percentage: 85, friendlyMessage: msg };
      }
      return { percentage: 85, friendlyMessage: 'Saving results...' };
    }
    if (stepUpper.includes('DONE') || stepUpper.includes('COMPLETE')) {
      if (isContentGeneration) {
        const finalMsg = finalTaskCount 
          ? `Done! Generated content for ${finalTaskCount} task${finalTaskCount !== '1' ? 's' : ''}`
          : 'Done! Content generation complete';
        return { percentage: 100, friendlyMessage: finalMsg };
      } else if (isClustering) {
        const finalMsg = finalKeywordCount && finalClusterCount 
          ? `Done! Created ${finalClusterCount} cluster${finalClusterCount !== '1' ? 's' : ''} from ${finalKeywordCount} keyword${finalKeywordCount !== '1' ? 's' : ''}`
          : finalKeywordCount
          ? `Done! Processed ${finalKeywordCount} keyword${finalKeywordCount !== '1' ? 's' : ''}`
          : finalClusterCount
          ? `Done! Created ${finalClusterCount} cluster${finalClusterCount !== '1' ? 's' : ''}`
          : 'Done! Clustering complete';
        return { percentage: 100, friendlyMessage: finalMsg };
      } else if (isIdeas) {
        const finalMsg = finalTaskCount 
          ? `Done! Generated ${finalTaskCount} idea${finalTaskCount !== '1' ? 's' : ''}`
          : 'Done! Ideas generation complete';
        return { percentage: 100, friendlyMessage: finalMsg };
      }
      return { percentage: 100, friendlyMessage: 'Done! Task complete' };
    }
    
    // Default fallback
    return { percentage: displayedPercentageRef.current, friendlyMessage: message || 'Processing...' };
  };

  // Poll task status
  useEffect(() => {
    if (!taskId || !isOpen) return;
    
    // Don't poll for temporary task IDs (they start with "temp-")
    if (taskId.startsWith('temp-')) return;

    let intervalId: NodeJS.Timeout | null = null;
    let pollCount = 0;
    let isStopped = false; // Flag to prevent multiple stops
    const maxPolls = 300; // 10 minutes max (2 seconds * 300)

    const pollTaskStatus = async () => {
      // Don't poll if already stopped
      if (isStopped) return;
      
      try {
        pollCount++;
        
        // Check if we've exceeded max polls
        if (pollCount > maxPolls) {
          setProgress({
            percentage: 0,
            message: 'Task is taking longer than expected. Please check manually.',
            status: 'error',
          });
          isStopped = true;
          if (intervalId) {
            clearInterval(intervalId);
            intervalId = null;
          }
          return;
        }

        const response = await fetchAPI(
          `/v1/system/settings/task_progress/${taskId}/`
        );

        // Helper function to start auto-increment progress (1% every 350ms until 80%)
        // Only runs when no backend updates are coming (smooth fill-in animation)
        const startAutoIncrement = () => {
          // Clear any existing auto-increment interval
          if (autoIncrementIntervalRef.current) {
            clearInterval(autoIncrementIntervalRef.current);
            autoIncrementIntervalRef.current = null;
          }
          
          // Only start if we're below 80% and status is processing
          const current = displayedPercentageRef.current;
          if (current < 80) {
            // Use a slightly longer interval to avoid conflicts with backend updates
            autoIncrementIntervalRef.current = setInterval(() => {
              setProgress(prev => {
                // Check current status - stop if not processing
                if (prev.status !== 'processing') {
                  if (autoIncrementIntervalRef.current) {
                    clearInterval(autoIncrementIntervalRef.current);
                    autoIncrementIntervalRef.current = null;
                  }
                  return prev;
                }
                
                const currentPercent = displayedPercentageRef.current;
                // Only increment if still below 80%
                if (currentPercent < 80) {
                  const newPercentage = Math.min(currentPercent + 1, 80);
                  displayedPercentageRef.current = newPercentage;
                  
                  // Stop if we've reached 80%
                  if (newPercentage >= 80) {
                    if (autoIncrementIntervalRef.current) {
                      clearInterval(autoIncrementIntervalRef.current);
                      autoIncrementIntervalRef.current = null;
                    }
                  }
                  
                  return {
                    ...prev,
                    percentage: newPercentage,
                  };
                } else {
                  // Stop if we've reached 80%
                  if (autoIncrementIntervalRef.current) {
                    clearInterval(autoIncrementIntervalRef.current);
                    autoIncrementIntervalRef.current = null;
                  }
                  return prev;
                }
              });
            }, 350); // Slightly longer interval to reduce conflicts
          }
        };

        if (response.state === 'PROGRESS') {
          const meta = response.meta || {};
          
          // Determine current step from request_steps/response_steps first (most accurate)
          let currentStep: string | null = null;
          const allSteps = [...(meta.request_steps || []), ...(meta.response_steps || [])];
          
          // Get the latest step name from steps array
          if (allSteps.length > 0) {
            // Sort by stepNumber to get the latest
            const sortedSteps = [...allSteps].sort((a: any, b: any) => (b.stepNumber || 0) - (a.stepNumber || 0));
            const latestStep = sortedSteps[0];
            if (latestStep && latestStep.stepName) {
              const stepNameUpper = latestStep.stepName.toUpperCase();
              // Map step names to standard step names
              if (stepNameUpper.includes('INIT')) {
                currentStep = 'INIT';
              } else if (stepNameUpper.includes('PREP')) {
                currentStep = 'PREP';
              } else if (stepNameUpper.includes('AI_CALL') || stepNameUpper.includes('CALL')) {
                currentStep = 'AI_CALL';
              } else if (stepNameUpper.includes('PARSE')) {
                currentStep = 'PARSE';
              } else if (stepNameUpper.includes('SAVE') || stepNameUpper.includes('CREAT')) {
                currentStep = 'SAVE';
              } else if (stepNameUpper.includes('DONE') || stepNameUpper.includes('COMPLETE')) {
                currentStep = 'DONE';
              } else {
                currentStep = stepNameUpper;
              }
            }
          }
          
          // Fallback to phase or message if no step found
          if (!currentStep) {
            const currentPhase = (meta.phase || '').toUpperCase();
            const currentMessage = (meta.message || '').toLowerCase();
            
            // Check exact phase match first (backend now sends uppercase phase names)
            if (currentPhase === 'INIT' || currentPhase.includes('INIT')) {
              currentStep = 'INIT';
            } else if (currentPhase === 'PREP' || currentPhase.includes('PREP')) {
              currentStep = 'PREP';
            } else if (currentPhase === 'AI_CALL' || currentPhase.includes('AI_CALL') || currentPhase.includes('CALL')) {
              currentStep = 'AI_CALL';
            } else if (currentPhase === 'PARSE' || currentPhase.includes('PARSE')) {
              currentStep = 'PARSE';
            } else if (currentPhase === 'SAVE' || currentPhase.includes('SAVE') || currentPhase.includes('CREAT')) {
              currentStep = 'SAVE';
            } else if (currentPhase === 'DONE' || currentPhase.includes('DONE') || currentPhase.includes('COMPLETE')) {
              currentStep = 'DONE';
            } else {
              // Fallback to message-based detection
              if (currentMessage.includes('initializ') || currentMessage.includes('getting started')) {
                currentStep = 'INIT';
              } else if (currentMessage.includes('prepar') || currentMessage.includes('loading')) {
                currentStep = 'PREP';
              } else if (currentMessage.includes('generating') || currentMessage.includes('analyzing') || currentMessage.includes('finding related')) {
                currentStep = 'AI_CALL';
              } else if (currentMessage.includes('pars') || currentMessage.includes('organizing') || currentMessage.includes('processing content')) {
                currentStep = 'PARSE';
              } else if (currentMessage.includes('sav') || currentMessage.includes('creat') || (currentMessage.includes('cluster') && !currentMessage.includes('content'))) {
                currentStep = 'SAVE';
              } else if (currentMessage.includes('done') || currentMessage.includes('complet')) {
                currentStep = 'DONE';
              }
            }
          }
          
          // Get step info with user-friendly message (use original message and all steps for value extraction)
          const originalMessage = meta.message || '';
          // Include title in message for better function type detection
          const messageWithContext = `${title} ${originalMessage}`;
          const stepInfo = getStepInfo(currentStep || '', messageWithContext, allSteps);
          // Use backend percentage if available, otherwise use step-based percentage
          const backendPercentage = meta.percentage !== undefined ? meta.percentage : null;
          const targetPercentage = backendPercentage !== null ? backendPercentage : stepInfo.percentage;
          const friendlyMessage = stepInfo.friendlyMessage;
          
          // Check if we're transitioning to a new step
          const isNewStep = currentStepRef.current !== currentStep;
          const currentDisplayedPercentage = displayedPercentageRef.current;
          
          // Stop auto-increment when backend sends an update (prevents conflicts)
          if (autoIncrementIntervalRef.current) {
            clearInterval(autoIncrementIntervalRef.current);
            autoIncrementIntervalRef.current = null;
          }
          
          // Clear any existing transition timeout or animation interval
          if (stepTransitionTimeoutRef.current) {
            clearTimeout(stepTransitionTimeoutRef.current);
            stepTransitionTimeoutRef.current = null;
          }
          
          // Improved progress logic: Only allow progress to increase, never decrease
          // This prevents jumping back and forth between percentages
          const safeTargetPercentage = Math.max(targetPercentage, currentDisplayedPercentage);
          
          // Smooth progress animation: increment gradually until reaching target
          // Use smaller increments and faster updates for smoother animation
          if (safeTargetPercentage > currentDisplayedPercentage) {
            // Start smooth animation
            let animatedPercentage = currentDisplayedPercentage;
            const animateProgress = () => {
              if (animatedPercentage < safeTargetPercentage) {
                // Calculate increment based on distance for smooth animation
                const diff = safeTargetPercentage - animatedPercentage;
                // Use smaller increments for smoother feel
                // If close (< 5%), increment by 1, otherwise by 2
                const increment = diff <= 5 ? 1 : Math.min(2, Math.ceil(diff / 10));
                animatedPercentage = Math.min(animatedPercentage + increment, safeTargetPercentage);
                displayedPercentageRef.current = animatedPercentage;
                setProgress({
                  percentage: animatedPercentage,
                  message: friendlyMessage,
                  status: 'processing',
                  details: {
                    current: meta.current || 0,
                    total: meta.total || 0,
                    completed: meta.completed || 0,
                    currentItem: meta.current_item,
                    phase: meta.phase,
                  },
                });
                
                if (animatedPercentage < safeTargetPercentage) {
                  // Smooth updates: 150ms for better UX
                  stepTransitionTimeoutRef.current = setTimeout(animateProgress, 150);
                } else {
                  stepTransitionTimeoutRef.current = null;
                  // After reaching target, start auto-increment if below 80% and no backend update pending
                  if (safeTargetPercentage < 80) {
                    startAutoIncrement();
                  }
                }
              }
            };
            
            // If it's a new step, add small delay before starting animation
            if (isNewStep && currentStepRef.current !== null) {
              stepTransitionTimeoutRef.current = setTimeout(() => {
                currentStepRef.current = currentStep;
                animateProgress();
              }, 200);
            } else {
              // Same step or first step - start animation immediately
              currentStepRef.current = currentStep;
              animateProgress();
            }
          } else {
            // Target is same or less than current - just update message and details
            // Don't decrease percentage (prevents jumping back)
            currentStepRef.current = currentStep;
            setProgress(prev => ({
              ...prev,
              message: friendlyMessage,
              details: {
                current: meta.current || 0,
                total: meta.total || 0,
                completed: meta.completed || 0,
                currentItem: meta.current_item,
                phase: meta.phase,
              },
            }));
            // Start auto-increment if below 80% and no backend update
            if (currentDisplayedPercentage < 80 && safeTargetPercentage === currentDisplayedPercentage) {
              startAutoIncrement();
            }
          }
          
          // Extract image queue if available (for image generation)
          if (meta.image_queue && Array.isArray(meta.image_queue)) {
            setImageQueue(meta.image_queue as ImageQueueItem[]);
          }
          
          // Update step logs if available
          if (meta.request_steps || meta.response_steps) {
            // Collect all steps for display in modal
            const allSteps: Array<{
              stepNumber: number;
              stepName: string;
              status: string;
              message: string;
              timestamp?: number;
            }> = [];
            
            if (meta.request_steps && Array.isArray(meta.request_steps)) {
              meta.request_steps.forEach((step: any) => {
                allSteps.push({
                  stepNumber: step.stepNumber || 0,
                  stepName: step.stepName || 'Unknown',
                  status: step.status || 'success',
                  message: step.message || '',
                  timestamp: step.timestamp,
                });
              });
            }
            
            if (meta.response_steps && Array.isArray(meta.response_steps)) {
              meta.response_steps.forEach((step: any) => {
                allSteps.push({
                  stepNumber: step.stepNumber || 0,
                  stepName: step.stepName || 'Unknown',
                  status: step.status || 'success',
                  message: step.message || '',
                  timestamp: step.timestamp,
                });
              });
            }
            
            // Sort by step number and update state
            allSteps.sort((a, b) => a.stepNumber - b.stepNumber);
            setStepLogs(allSteps);
          }
        } else if (response.state === 'SUCCESS') {
          const meta = response.meta || {};
          
          // Clear any existing transition timeout
          if (stepTransitionTimeoutRef.current) {
            clearTimeout(stepTransitionTimeoutRef.current);
            stepTransitionTimeoutRef.current = null;
          }
          
          // Get completion message with extracted values
          const completionMessage = meta.message || '';
          const allSteps = [...(meta.request_steps || []), ...(meta.response_steps || [])];
          const stepInfo = getStepInfo('DONE', completionMessage, allSteps);
          
          // Update to 100% with user-friendly completion message
          currentStepRef.current = 'DONE';
          displayedPercentageRef.current = 100;
          setProgress({
            percentage: 100,
            message: stepInfo.friendlyMessage,
            status: 'completed',
            details: meta.details,
          });
          
          // Update final step logs
          if (meta.request_steps || meta.response_steps) {
            // Collect all steps for display in modal
            const allSteps: Array<{
              stepNumber: number;
              stepName: string;
              status: string;
              message: string;
              timestamp?: number;
            }> = [];
            
            if (meta.request_steps && Array.isArray(meta.request_steps)) {
              meta.request_steps.forEach((step: any) => {
                allSteps.push({
                  stepNumber: step.stepNumber || 0,
                  stepName: step.stepName || 'Unknown',
                  status: step.status || 'success',
                  message: step.message || '',
                  timestamp: step.timestamp,
                });
              });
            }
            
            if (meta.response_steps && Array.isArray(meta.response_steps)) {
              meta.response_steps.forEach((step: any) => {
                allSteps.push({
                  stepNumber: step.stepNumber || 0,
                  stepName: step.stepName || 'Unknown',
                  status: step.status || 'success',
                  message: step.message || '',
                  timestamp: step.timestamp,
                });
              });
            }
            
            // Sort by step number and update state
            allSteps.sort((a, b) => a.stepNumber - b.stepNumber);
            setStepLogs(allSteps);
          }
          
          // Stop polling on SUCCESS
          isStopped = true;
          if (intervalId) {
            clearInterval(intervalId);
            intervalId = null;
          }
        } else if (response.state === 'FAILURE') {
          const meta = response.meta || {};
          // Try multiple error message sources
          const errorMsg = meta.error || meta.message || response.error || 'Task failed - exception details unavailable';
          const errorType = meta.error_type || 'Error';
          setProgress({
            percentage: 0,
            message: errorMsg.includes('exception details unavailable') ? errorMsg : `Error: ${errorMsg}`,
            status: 'error',
            details: meta.error_type ? `${errorType}: ${errorMsg}` : errorMsg,
          });
          
          // Update step logs from failure response
          if (meta.request_steps || meta.response_steps) {
            const allSteps: Array<{
              stepNumber: number;
              stepName: string;
              status: string;
              message: string;
              timestamp?: number;
            }> = [];
            
            if (meta.request_steps && Array.isArray(meta.request_steps)) {
              meta.request_steps.forEach((step: any) => {
                allSteps.push({
                  stepNumber: step.stepNumber || 0,
                  stepName: step.stepName || 'Unknown',
                  status: step.status || 'error',
                  message: step.message || '',
                  timestamp: step.timestamp,
                });
              });
            }
            
            if (meta.response_steps && Array.isArray(meta.response_steps)) {
              meta.response_steps.forEach((step: any) => {
                allSteps.push({
                  stepNumber: step.stepNumber || 0,
                  stepName: step.stepName || 'Unknown',
                  status: step.status || 'error',
                  message: step.message || '',
                  timestamp: step.timestamp,
                });
              });
            }
            
            allSteps.sort((a, b) => a.stepNumber - b.stepNumber);
            setStepLogs(allSteps);
          }
          
          // Stop polling on FAILURE
          isStopped = true;
          if (intervalId) {
            clearInterval(intervalId);
            intervalId = null;
          }
        } else {
          // PENDING or other states
          setProgress({
            percentage: 0,
            message: 'Task is starting...',
            status: 'pending',
          });
        }
      } catch (error: any) {
        console.error('Error polling task status:', error);
        // Continue polling on error (might be temporary)
        // Only show error after multiple consecutive failures
        if (pollCount > 5) {
          // Extract clean error message
          let errorMsg = error.message || 'Unknown error';
          if (errorMsg.includes('HTTP_ERROR')) {
            // Try to extract the actual error from the response
            errorMsg = errorMsg.replace(/^API Error \(\d+\): HTTP_ERROR - /, '').trim() || 'Server error';
          }
          setProgress({
            percentage: 0,
            message: `Error checking task status: ${errorMsg}`,
            status: 'error',
          });
          // Stop polling after showing error
          isStopped = true;
          if (intervalId) {
            clearInterval(intervalId);
            intervalId = null;
          }
        }
      }
    };

    // Start polling immediately, then every 2 seconds
    pollTaskStatus();
    intervalId = setInterval(() => {
      if (!isStopped) {
        pollTaskStatus();
      }
    }, 2000);

    return () => {
      isStopped = true;
      if (intervalId) {
        clearInterval(intervalId);
        intervalId = null;
      }
      // Clear step transition timeout and animation on cleanup
      if (stepTransitionTimeoutRef.current) {
        clearTimeout(stepTransitionTimeoutRef.current);
        stepTransitionTimeoutRef.current = null;
      }
      // Clear auto-increment interval
      if (autoIncrementIntervalRef.current) {
        clearInterval(autoIncrementIntervalRef.current);
        autoIncrementIntervalRef.current = null;
      }
      // Reset displayed percentage
      displayedPercentageRef.current = 0;
      currentStepRef.current = null;
    };
  }, [taskId, isOpen]);

  const openModal = useCallback((newTaskId: string, newTitle: string, newFunctionId?: string) => {
    // Clear any existing transition timeout
    if (stepTransitionTimeoutRef.current) {
      clearTimeout(stepTransitionTimeoutRef.current);
      stepTransitionTimeoutRef.current = null;
    }
    // Clear auto-increment interval
    if (autoIncrementIntervalRef.current) {
      clearInterval(autoIncrementIntervalRef.current);
      autoIncrementIntervalRef.current = null;
    }
    displayedPercentageRef.current = 0;
    currentStepRef.current = null;
    setStepLogs([]); // Reset step logs when opening modal
    setTaskId(newTaskId);
    setTitle(newTitle);
    setFunctionId(newFunctionId);
    setIsOpen(true);
    setProgress({
      percentage: 0,
      message: 'Getting started...',
      status: 'pending',
    });
  }, []);

  const updateTaskId = useCallback((newTaskId: string) => {
    setTaskId(newTaskId);
    // Reset progress when updating to real task ID
    setProgress({
      percentage: 0,
      message: 'Initializing...',
      status: 'pending',
    });
  }, []);

  const closeModal = useCallback(() => {
    // Clear any existing transition timeout
    if (stepTransitionTimeoutRef.current) {
      clearTimeout(stepTransitionTimeoutRef.current);
      stepTransitionTimeoutRef.current = null;
    }
    // Clear auto-increment interval
    if (autoIncrementIntervalRef.current) {
      clearInterval(autoIncrementIntervalRef.current);
      autoIncrementIntervalRef.current = null;
    }
    displayedPercentageRef.current = 0;
    currentStepRef.current = null;
    setStepLogs([]); // Clear step logs when closing modal
    setImageQueue(undefined); // Clear image queue when closing modal
    setIsOpen(false);
    // Clear taskId to stop polling when modal closes
    setTaskId(null);
    setTitle('');
  }, []);

  const setError = useCallback((errorMessage: string) => {
    setProgress({
      percentage: 0,
      message: errorMessage,
      status: 'error',
    });
  }, []);

  const reset = useCallback(() => {
    // Clear any existing transition timeout
    if (stepTransitionTimeoutRef.current) {
      clearTimeout(stepTransitionTimeoutRef.current);
      stepTransitionTimeoutRef.current = null;
    }
    // Clear auto-increment interval
    if (autoIncrementIntervalRef.current) {
      clearInterval(autoIncrementIntervalRef.current);
      autoIncrementIntervalRef.current = null;
    }
    displayedPercentageRef.current = 0;
    currentStepRef.current = null;
    setProgress({
      percentage: 0,
      message: 'Getting started...',
      status: 'pending',
    });
    setStepLogs([]);
    setImageQueue(undefined);
    setTaskId(null);
    setTitle('');
    setIsOpen(false);
  }, []);

  return {
    progress,
    isOpen,
    openModal,
    updateTaskId,
    closeModal,
    setError,
    reset,
    title, // Expose title for use in component
    taskId, // Expose taskId for use in ProgressModal
    functionId, // Expose functionId for use in ProgressModal
    stepLogs, // Expose step logs for debugging
    imageQueue, // Expose image queue for image generation
  };
}

