/**
 * ImageQueueModal - Displays image generation queue with individual progress bars
 * Similar to WP plugin's image-queue-processor.js modal
 * Stage 1: Shows all progress bars immediately when Generate button is clicked
 */

import React, { useEffect, useState, useRef } from 'react';
import { Modal } from '../ui/modal';
import { FileIcon, TimeIcon, CheckCircleIcon, ErrorIcon } from '../../icons';
import { fetchAPI } from '../../services/api';

export interface ImageQueueItem {
  imageId: number | null;
  index: number;
  label: string;
  type: 'featured' | 'in_article';
  position?: number;
  contentTitle: string;
  prompt?: string; // Image prompt text
  status: 'pending' | 'processing' | 'completed' | 'failed';
  progress: number;
  imageUrl: string | null;
  error: string | null;
}

interface ImageQueueModalProps {
  isOpen: boolean;
  onClose: () => void;
  queue: ImageQueueItem[];
  totalImages: number;
  taskId?: string | null;
  model?: string;
  provider?: string;
  onUpdateQueue?: (queue: ImageQueueItem[]) => void;
  onLog?: (log: {
    timestamp: string;
    type: 'request' | 'success' | 'error' | 'step';
    action: string;
    data: any;
    stepName?: string;
    percentage?: number;
  }) => void;
}

export default function ImageQueueModal({
  isOpen,
  onClose,
  queue,
  totalImages,
  taskId,
  model,
  provider,
  onUpdateQueue,
  onLog,
}: ImageQueueModalProps) {
  const [localQueue, setLocalQueue] = useState<ImageQueueItem[]>(queue);
  // Track smooth progress animation for each item
  const [smoothProgress, setSmoothProgress] = useState<Record<number, number>>({});
  const progressIntervalsRef = useRef<Record<number, ReturnType<typeof setInterval>>>({});

  useEffect(() => {
    setLocalQueue(queue);
  }, [queue]);

  useEffect(() => {
    if (onUpdateQueue) {
      onUpdateQueue(localQueue);
    }
  }, [localQueue, onUpdateQueue]);

  // Time-based progress: 1% → 50% in 5s, then 2% every 200ms until 80%, then event-based to 100%
  useEffect(() => {
    // Helper function for Phase 2: 2% every 200ms until 80%
    const startPhase2Animation = (index: number, startProgress: number) => {
      if (progressIntervalsRef.current[index]) {
        clearInterval(progressIntervalsRef.current[index]);
        delete progressIntervalsRef.current[index];
      }
      
      let currentPercent = Math.max(startProgress, 50);
      
      const interval = setInterval(() => {
        setSmoothProgress(prev => {
          const current = prev[index] ?? currentPercent;
          
          // Only increment if still below 80% and item is actively processing
          const item = localQueue.find(item => item.index === index);
          if (current < 80 && item?.status === 'processing') {
            const newPercentage = Math.min(current + 2, 80); // 2% every 200ms
            currentPercent = newPercentage;
            
            // Stop if we've reached 80%
            if (newPercentage >= 80) {
              clearInterval(interval);
              delete progressIntervalsRef.current[index];
            }
            
            return {
              ...prev,
              [index]: newPercentage
            };
          } else {
            // Stop if status changed or reached 80%
            clearInterval(interval);
            delete progressIntervalsRef.current[index];
            return prev;
          }
        });
      }, 200); // 2% every 200ms
      
      progressIntervalsRef.current[index] = interval;
    };
    
    const indicesToClear: number[] = [];

    localQueue.forEach((item) => {
      if (item.status === 'processing') {
        const currentProgress = smoothProgress[item.index] ?? (item.progress > 0 ? item.progress : 1);

        if (currentProgress < 50 && !progressIntervalsRef.current[item.index]) {
          let currentPercent = Math.max(currentProgress, 1);

          const interval = setInterval(() => {
            setSmoothProgress(prev => {
              const current = prev[item.index] ?? currentPercent;

              if (current < 50 && item.status === 'processing') {
                const newPercentage = Math.min(current + 1, 50);
                currentPercent = newPercentage;

                if (newPercentage >= 50) {
                  clearInterval(interval);
                  delete progressIntervalsRef.current[item.index];

                  if (newPercentage < 80) {
                    startPhase2Animation(item.index, newPercentage);
                  }
                }

                return {
                  ...prev,
                  [item.index]: newPercentage
                };
              } else {
                clearInterval(interval);
                delete progressIntervalsRef.current[item.index];
                return prev;
              }
            });
          }, 200);

          progressIntervalsRef.current[item.index] = interval;
        } else if (currentProgress >= 50 && currentProgress < 80 && !progressIntervalsRef.current[item.index]) {
          startPhase2Animation(item.index, currentProgress);
        } else if (item.imageUrl && currentProgress < 100 && !progressIntervalsRef.current[item.index]) {
          if (progressIntervalsRef.current[item.index]) {
            clearInterval(progressIntervalsRef.current[item.index]);
            delete progressIntervalsRef.current[item.index];
          }

          let animatingProgress = Math.max(currentProgress, 80);
          const startProgress = animatingProgress;
          const endProgress = 100;
          const duration = 800;
          const startTime = Date.now();

          const interval = setInterval(() => {
            const elapsed = Date.now() - startTime;
            const progress = Math.min(1, elapsed / duration);

            const eased = 1 - Math.pow(1 - progress, 2);
            animatingProgress = startProgress + ((endProgress - startProgress) * eased);

            if (animatingProgress >= 100 || elapsed >= duration) {
              animatingProgress = 100;
              clearInterval(interval);
              delete progressIntervalsRef.current[item.index];
            }

            setSmoothProgress(prev => ({
              ...prev,
              [item.index]: Math.round(animatingProgress)
            }));
          }, 16);

          progressIntervalsRef.current[item.index] = interval;
        }
      } else {
        if (progressIntervalsRef.current[item.index]) {
          clearInterval(progressIntervalsRef.current[item.index]);
          delete progressIntervalsRef.current[item.index];
        }

        if (smoothProgress[item.index] !== undefined) {
          indicesToClear.push(item.index);
        }
      }
    });

    if (indicesToClear.length > 0) {
      setSmoothProgress(prev => {
        const next = { ...prev };
        indicesToClear.forEach(idx => {
          delete next[idx];
        });
        return next;
      });
    }
    
    // Cleanup on unmount
    return () => {
      Object.values(progressIntervalsRef.current).forEach(interval => clearInterval(interval));
      progressIntervalsRef.current = {};
    };
  }, [localQueue, smoothProgress]);

  // Polling for task status updates
  useEffect(() => {
    if (!isOpen || !taskId) return;

    let pollAttempts = 0;
    const maxPollAttempts = 300; // 5 minutes max (300 * 1 second)
    
    const pollInterval = setInterval(async () => {
      pollAttempts++;
      
      // Stop polling after max attempts
      if (pollAttempts > maxPollAttempts) {
        console.warn('Polling timeout reached, stopping');
        clearInterval(pollInterval);
        return;
      }
      
      try {
        console.log(`[ImageQueueModal] Polling task status (attempt ${pollAttempts}):`, taskId);
        const data = await fetchAPI(`/v1/system/settings/task_progress/${taskId}/`);
        console.log(`[ImageQueueModal] Task status response:`, data);

        // Check if data is valid (not HTML error page)
        if (!data || typeof data !== 'object') {
          console.warn('Invalid task status response:', data);
          return;
        }

        // Check state (task_progress returns 'state', not 'status')
        const taskState = data.state || data.status;
        console.log(`[ImageQueueModal] Task state:`, taskState);
        
        if (taskState === 'SUCCESS' || taskState === 'FAILURE') {
          console.log(`[ImageQueueModal] Task completed with state:`, taskState);
          clearInterval(pollInterval);
          
          // Log completion status
          if (onLog) {
            if (taskState === 'SUCCESS') {
              const result = data.result || (data.meta && data.meta.result);
              const completed = result?.completed || 0;
              const failed = result?.failed || 0;
              const total = result?.total_images || totalImages;
              
              onLog({
                timestamp: new Date().toISOString(),
                type: failed > 0 ? 'error' : 'success',
                action: 'generate_images',
                stepName: 'Task Completed',
                data: {
                  state: 'SUCCESS',
                  completed,
                  failed,
                  total,
                  results: result?.results || []
                }
              });
            } else {
              // FAILURE
              onLog({
                timestamp: new Date().toISOString(),
                type: 'error',
                action: 'generate_images',
                stepName: 'Task Failed',
                data: {
                  state: 'FAILURE',
                  error: data.error || data.meta?.error || 'Task failed',
                  meta: data.meta
                }
              });
            }
          }
          
          // Update final state
          if (taskState === 'SUCCESS' && data.result) {
            console.log(`[ImageQueueModal] Updating queue from result:`, data.result);
            updateQueueFromTaskResult(data.result);
          } else if (taskState === 'SUCCESS' && data.meta && data.meta.result) {
            // Some responses have result in meta
            console.log(`[ImageQueueModal] Updating queue from meta result:`, data.meta.result);
            updateQueueFromTaskResult(data.meta.result);
          }
          return;
        }

        // Update progress from task meta
        if (data.meta) {
          console.log(`[ImageQueueModal] Updating queue from meta:`, data.meta);
          updateQueueFromTaskMeta(data.meta);
        } else {
          console.log(`[ImageQueueModal] No meta data in response`);
        }
      } catch (error: any) {
        // Check if it's a JSON parse error (HTML response) or API error
        if (error.message && (error.message.includes('JSON') || error.message.includes('API Error'))) {
          console.error('Task status endpoint error:', {
            message: error.message,
            status: error.status,
            taskId: taskId,
            endpoint: `/v1/system/settings/task_progress/${taskId}/`,
            error: error
          });
          // If it's a 404, the endpoint might not exist - stop polling after a few attempts
          if (error.status === 404) {
            console.error('Task progress endpoint not found (404). Stopping polling.');
            clearInterval(pollInterval);
            return;
          }
          // Don't stop polling for other errors, but log them
        } else {
          console.error('Error polling task status:', error);
        }
      }
    }, 1000); // Poll every second

    return () => clearInterval(pollInterval);
  }, [isOpen, taskId]);

  // Helper function to convert image_path to frontend-accessible URL
  const getImageUrlFromPath = (imagePath: string | null | undefined): string | null => {
    if (!imagePath) return null;
    
    // If path contains 'ai-images', extract filename and convert to web URL
    if (imagePath.includes('ai-images')) {
      const filename = imagePath.split('ai-images/')[1] || imagePath.split('ai-images\\')[1];
      if (filename) {
        return `/images/ai-images/${filename}`;
      }
    }
    
    // If path is already a web path, return as-is
    if (imagePath.startsWith('/images/')) {
      return imagePath;
    }
    
    // Otherwise, try to extract filename and use ai-images path
    const filename = imagePath.split('/').pop() || imagePath.split('\\').pop();
    return filename ? `/images/ai-images/${filename}` : null;
  };

  const updateQueueFromTaskMeta = (meta: any) => {
    const { current_image, total_images, completed, failed, results, current_image_progress, current_image_id } = meta;

    setLocalQueue(prevQueue => {
      return prevQueue.map((item, index) => {
        const result = results?.find((r: any) => r.image_id === item.imageId);

        if (result) {
          // Stop smooth animation for completed/failed items
          if (result.status === 'completed' || result.status === 'failed') {
            if (progressIntervalsRef.current[item.index]) {
              clearInterval(progressIntervalsRef.current[item.index]);
              delete progressIntervalsRef.current[item.index];
            }
          }
          
          // Only set imageUrl if image is completed AND image_path exists (image is saved)
          const imageUrl = (result.status === 'completed' && result.image_path) 
            ? getImageUrlFromPath(result.image_path)
            : null;
          
          // Use backend progress as target (0%, 50%, 75%, 90%, 100%)
          // This works for both featured and in-article images
          const backendProgress = (current_image_id === item.imageId && current_image_progress !== undefined) 
            ? current_image_progress 
            : (result.status === 'completed' ? 100 : 
               result.status === 'failed' ? 0 : 
               item.progress);
          
          return {
            ...item,
            status: result.status === 'completed' ? 'completed' :
                    result.status === 'failed' ? 'failed' : 'processing',
            progress: backendProgress, // Use backend progress as target for smooth animation
            imageUrl: imageUrl || item.imageUrl, // Only update if we have a new URL, otherwise keep existing
            error: result.error || null
          };
        }

        // Update based on current_image index and progress
        if (index + 1 < current_image) {
          // Already completed - stop animation
          if (progressIntervalsRef.current[item.index]) {
            clearInterval(progressIntervalsRef.current[item.index]);
            delete progressIntervalsRef.current[item.index];
          }
          return { ...item, status: 'completed', progress: 100 };
        } 
        // SAFE: Only change to 'processing' when backend confirms with actual image ID
        // This ensures progress bar only moves when actual processing starts
        // Works consistently for both featured and in-article images
        else if (current_image_id === item.imageId) {
          // Currently processing - use backend progress if available
          const backendProgress = (current_image_progress !== undefined) 
            ? current_image_progress 
            : (smoothProgress[item.index] ?? 0);
          return { ...item, status: 'processing', progress: backendProgress };
        }

        // Keep as 'pending' until backend confirms processing with image ID
        return item;
      });
    });
  };

  const updateQueueFromTaskResult = (result: any) => {
    const { results } = result;

    setLocalQueue(prevQueue => {
      return prevQueue.map((item) => {
        const taskResult = results?.find((r: any) => r.image_id === item.imageId);

        if (taskResult) {
          // Stop smooth animation
          if (progressIntervalsRef.current[item.index]) {
            clearInterval(progressIntervalsRef.current[item.index]);
            delete progressIntervalsRef.current[item.index];
          }
          
          // Only set imageUrl if image is completed AND image_path exists (image is saved)
          const imageUrl = (taskResult.status === 'completed' && taskResult.image_path) 
            ? getImageUrlFromPath(taskResult.image_path)
            : null;
          
          return {
            ...item,
            status: taskResult.status === 'completed' ? 'completed' : 'failed',
            progress: taskResult.status === 'completed' ? 100 : 0,
            imageUrl: imageUrl || item.imageUrl, // Only update if we have a new URL, otherwise keep existing
            error: taskResult.error || null
          };
        }

        return item;
      });
    });
  };

  if (!isOpen) return null;

  const getStatusIcon = (status: string) => {
    switch (status) {
      case 'pending':
        return <TimeIcon className="w-4 h-4" />;
      case 'processing':
        return (
          <svg className="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24">
            <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
            <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
          </svg>
        );
      case 'completed':
        return <CheckCircleIcon className="w-4 h-4" />;
      case 'failed':
        return <ErrorIcon className="w-4 h-4" />;
      default:
        return <TimeIcon className="w-4 h-4" />;
    }
  };

  const getStatusText = (status: string) => {
    switch (status) {
      case 'pending':
        return 'Pending';
      case 'processing':
        return 'Generating...';
      case 'completed':
        return 'Complete';
      case 'failed':
        return 'Failed';
      default:
        return 'Pending';
    }
  };

  const getProgressColor = (status: string) => {
    switch (status) {
      case 'completed':
        return 'bg-green-500';
      case 'failed':
        return 'bg-red-500';
      case 'processing':
        return 'bg-blue-500';
      default:
        return 'bg-gray-300';
    }
  };

  const isProcessing = localQueue.some(item => item.status === 'processing');
  const completedCount = localQueue.filter(item => item.status === 'completed').length;
  const failedCount = localQueue.filter(item => item.status === 'failed').length;
  const allDone = localQueue.every(item => item.status === 'completed' || item.status === 'failed');

  return (
    <Modal
      isOpen={isOpen}
      onClose={onClose}
      className="max-w-4xl w-full max-h-[80vh] overflow-hidden flex flex-col"
      showCloseButton={!isProcessing}
    >
      {/* Header */}
      <div className="px-6 py-4 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between">
        <div className="flex items-center gap-3">
          <FileIcon className="w-6 h-6 text-blue-500" />
          <div>
            <h3 className="text-lg font-semibold text-gray-900 dark:text-white">
              Generating Images
            </h3>
            <p className="text-sm text-gray-500 dark:text-gray-400 mt-1">
              Total: {totalImages} image{totalImages !== 1 ? 's' : ''} in queue
            </p>
            {model && (
              <p className="text-xs text-gray-400 dark:text-gray-500 mt-1">
                Model: {provider === 'openai' ? 'OpenAI' : provider === 'runware' ? 'Runware' : provider || 'Unknown'} {model === 'dall-e-2' ? 'DALL·E 2' : model === 'dall-e-3' ? 'DALL·E 3' : model}
              </p>
            )}
          </div>
        </div>
      </div>

        {/* Queue List */}
        <div className="flex-1 overflow-y-auto px-6 py-4">
          <div className="space-y-3">
            {localQueue.map((item) => (
              <div
                key={item.index}
                className={`p-4 rounded-lg border-2 transition-colors ${
                  item.status === 'processing'
                    ? 'bg-blue-50 dark:bg-blue-900/20 border-blue-500'
                    : item.status === 'completed'
                    ? 'bg-green-50 dark:bg-green-900/20 border-green-500'
                    : item.status === 'failed'
                    ? 'bg-red-50 dark:bg-red-900/20 border-red-500'
                    : 'bg-gray-50 dark:bg-gray-700/50 border-gray-300 dark:border-gray-600'
                }`}
              >
                <div className="flex items-center gap-4">
                  {/* Left: Queue Info */}
                  <div className="flex-1">
                    {/* Header Row */}
                    <div className="flex items-center gap-3 mb-2">
                      <span className="flex items-center justify-center w-6 h-6 rounded-full bg-blue-500 text-white text-xs font-bold">
                        {item.index}
                      </span>
                      <span className="font-semibold text-sm text-gray-900 dark:text-white">
                        {item.label}
                      </span>
                      <span className="flex-1 text-xs text-gray-500 dark:text-gray-400 truncate">
                        {item.prompt 
                          ? (() => {
                              const words = item.prompt.split(' ');
                              const firstTenWords = words.slice(0, 10).join(' ');
                              return words.length > 10 ? `${firstTenWords}...` : item.prompt;
                            })()
                          : item.contentTitle}
                      </span>
                      <span className="text-xs font-semibold text-gray-600 dark:text-gray-300 whitespace-nowrap flex items-center gap-1">
                        {getStatusIcon(item.status)}
                        <span>{getStatusText(item.status)}</span>
                      </span>
                    </div>

                    {/* Progress Bar - Use smooth progress for visual display */}
                    <div className="relative h-5 bg-gray-200 dark:bg-gray-600 rounded-full overflow-hidden">
                      <div
                        className={`h-full ${getProgressColor(item.status)} transition-all duration-150 ease-out`}
                        style={{ width: `${smoothProgress[item.index] ?? item.progress ?? 0}%` }}
                      />
                      <div className="absolute inset-0 flex items-center justify-center">
                        <span
                          className={`text-xs font-bold ${
                            (smoothProgress[item.index] ?? item.progress ?? 0) >= 50
                              ? 'text-white'
                              : 'text-gray-700 dark:text-gray-200'
                          }`}
                        >
                          {smoothProgress[item.index] ?? item.progress ?? 0}%
                        </span>
                      </div>
                    </div>

                    {/* Error Message */}
                    {item.error && (
                      <div className="mt-2 p-2 bg-red-100 dark:bg-red-900/30 border-l-4 border-red-500 rounded text-xs text-red-700 dark:text-red-300">
                        {item.error}
                      </div>
                    )}
                  </div>

                  {/* Right: Thumbnail - Only show if image is completed and saved */}
                  <div className="w-20 h-20 bg-gray-100 dark:bg-gray-700 rounded-lg overflow-hidden flex-shrink-0 flex items-center justify-center">
                    {item.status === 'completed' && item.imageUrl ? (
                      <img
                        src={item.imageUrl}
                        alt={item.label}
                        className="w-full h-full object-cover"
                        onError={(e) => {
                          // Hide image if it fails to load (not yet available)
                          const target = e.target as HTMLImageElement;
                          target.style.display = 'none';
                          const parent = target.parentElement;
                          if (parent) {
                            parent.innerHTML = '<span class="text-xs text-gray-400 dark:text-gray-500">No image</span>';
                          }
                        }}
                      />
                    ) : (
                      <span className="text-xs text-gray-400 dark:text-gray-500">
                        No image
                      </span>
                    )}
                  </div>
                </div>
              </div>
            ))}
          </div>
        </div>

        {/* Footer */}
        <div className="px-6 py-4 border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800">
          <div className="flex items-center justify-between">
            <div className="text-sm text-gray-600 dark:text-gray-400">
              {completedCount} completed{failedCount > 0 ? `, ${failedCount} failed` : ''} of {totalImages} total
            </div>
            {allDone && (
              <button
                onClick={onClose}
                className="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors"
              >
                Close
              </button>
            )}
          </div>
        </div>
    </Modal>
  );
}
