import React, { useState, useCallback, useRef, useEffect } from 'react';
import { useDropzone } from 'react-dropzone';
import { Upload, FileText, X, CheckCircle, AlertCircle, Cloud } from 'lucide-react';
import { cn } from '../utils/cn';
import { documentService, GCSErrorHandler, GCSError } from '../services/documentService';
import { useAuth } from '../contexts/AuthContext';

interface UploadedFile {
  id: string;
  name: string;
  size: number;
  type: string;
  status: 'uploading' | 'uploaded' | 'processing' | 'completed' | 'error';
  progress: number;
  error?: string;
  documentId?: string; // Real document ID from backend
  // Firebase Storage specific fields
  storageError?: boolean;
  storageType?: 'firebase' | 'local';
  storageUrl?: string;
}

interface DocumentUploadProps {
  onUploadComplete?: (documentId: string) => void;
  onUploadError?: (error: string) => void;
}

const DocumentUpload: React.FC<DocumentUploadProps> = ({
  onUploadComplete,
  onUploadError,
}) => {
  const { token } = useAuth();
  const [uploadedFiles, setUploadedFiles] = useState<UploadedFile[]>([]);
  const [isUploading, setIsUploading] = useState(false);
  const abortControllers = useRef<Map<string, AbortController>>(new Map());

  // Cleanup function to cancel ongoing uploads when component unmounts
  useEffect(() => {
    return () => {
      // Cancel all ongoing uploads when component unmounts
      abortControllers.current.forEach((controller, fileId) => {
        controller.abort();
        console.log(`Cancelled upload for file: ${fileId}`);
      });
      abortControllers.current.clear();
    };
  }, []);

  // Handle page visibility changes (tab switching, minimizing)
  useEffect(() => {
    const handleVisibilityChange = () => {
      if (document.hidden && isUploading && abortControllers.current.size > 0) {
        console.warn('Page hidden during upload - uploads may be cancelled');
        // Optionally show a notification to the user
        if ('Notification' in window && Notification.permission === 'granted') {
          new Notification('Upload in Progress', {
            body: 'Please return to the tab to continue uploads',
            icon: '/favicon.ico',
          });
        }
      }
    };

    document.addEventListener('visibilitychange', handleVisibilityChange);
    return () => {
      document.removeEventListener('visibilitychange', handleVisibilityChange);
    };
  }, [isUploading]);

  const onDrop = useCallback(async (acceptedFiles: File[]) => {
    setIsUploading(true);
    
    const newFiles: UploadedFile[] = acceptedFiles.map(file => ({
      id: Math.random().toString(36).substr(2, 9),
      name: file.name,
      size: file.size,
      type: file.type,
      status: 'uploading',
      progress: 0,
    }));

    setUploadedFiles(prev => [...prev, ...newFiles]);

    // Upload files using the document service
    for (let i = 0; i < acceptedFiles.length; i++) {
      const file = acceptedFiles[i];
      const uploadedFile = newFiles[i];
      
      // Create AbortController for this upload
      const abortController = new AbortController();
      abortControllers.current.set(uploadedFile.id, abortController);
      
      try {
        // Upload the document with optimized agentic RAG processing (no strategy selection needed)
        const result = await documentService.uploadDocument(
          file,
          (progress) => {
            setUploadedFiles(prev =>
              prev.map(f =>
                f.id === uploadedFile.id ? { ...f, progress } : f
              )
            );
          },
          abortController.signal
        );

        // Upload completed - update status to "processing" immediately
        setUploadedFiles(prev =>
          prev.map(f =>
            f.id === uploadedFile.id
              ? { 
                  ...f, 
                  id: result.id,
                  documentId: result.id,
                  status: 'processing', // Changed from 'uploaded' to 'processing'
                  progress: 100 
                }
              : f
          )
        );

        // Call the completion callback with the document ID
        onUploadComplete?.(result.id);

        // Start monitoring processing progress immediately
        monitorProcessingProgress(result.id, uploadedFile.id);

      } catch (error) {
        // Check if this was an abort error
        if (error instanceof Error && error.name === 'AbortError') {
          console.log(`Upload cancelled for file: ${uploadedFile.name}`);
          setUploadedFiles(prev =>
            prev.map(f =>
              f.id === uploadedFile.id
                ? { ...f, status: 'error', error: 'Upload cancelled' }
                : f
            )
          );
        } else {
          console.error('Upload failed:', error);
          
          // Handle storage-specific errors
          let errorMessage = 'Upload failed';
          let isStorageError = false;
          
          if (GCSErrorHandler.isGCSError(error)) {
            errorMessage = GCSErrorHandler.getErrorMessage(error as GCSError);
            isStorageError = true;
          } else if (error instanceof Error) {
            errorMessage = error.message;
          }
          
          setUploadedFiles(prev =>
            prev.map(f =>
              f.id === uploadedFile.id
                ? { 
                    ...f, 
                    status: 'error', 
                    error: errorMessage,
                    // Add storage error indicator
                    ...(isStorageError && { storageError: true })
                  }
                : f
            )
          );
          
          onUploadError?.(errorMessage);
        }
      } finally {
        // Clean up the abort controller
        abortControllers.current.delete(uploadedFile.id);
      }
    }
    
    setIsUploading(false);
  }, [onUploadComplete, onUploadError]);

  // Monitor processing progress for uploaded documents
  const monitorProcessingProgress = useCallback((documentId: string, fileId: string) => {
    // Guard against undefined or null document IDs
    if (!documentId || documentId === 'undefined' || documentId === 'null') {
      console.warn('Attempted to monitor progress for document with invalid ID:', documentId);
      return;
    }
    
    // Validate UUID format
    const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
    if (!uuidRegex.test(documentId)) {
      console.warn('Attempted to monitor progress for document with invalid UUID format:', documentId);
      return;
    }

    // Add timeout to prevent infinite polling (30 minutes max)
    const startTime = Date.now();
    const maxPollingTime = 30 * 60 * 1000; // 30 minutes
    
    const checkProgress = async () => {
      // Check if we've exceeded the maximum polling time
      if (Date.now() - startTime > maxPollingTime) {
        console.warn(`Polling timeout for document ${documentId} after ${maxPollingTime / 1000 / 60} minutes`);
        setUploadedFiles(prev =>
          prev.map(f =>
            f.id === fileId
              ? { 
                  ...f, 
                  status: 'error',
                  error: 'Processing timeout - please check document status manually'
                }
              : f
          )
        );
        return;
      }

      try {
        const response = await fetch(`${import.meta.env.VITE_API_BASE_URL}/documents/${documentId}/progress`, {
          headers: {
            'Authorization': `Bearer ${token}`,
            'Content-Type': 'application/json',
          },
        });

        if (response.ok) {
          const progress = await response.json();
          
          // Update status based on progress
          let newStatus: UploadedFile['status'] = 'processing'; // Default to processing
          if (progress.status === 'uploading' || progress.status === 'uploaded') {
            newStatus = 'processing'; // Still processing
          } else if (progress.status === 'processing' || progress.status === 'extracting_text' || progress.status === 'processing_llm' || progress.status === 'generating_pdf') {
            newStatus = 'processing';
          } else if (progress.status === 'completed') {
            newStatus = 'completed';
          } else if (progress.status === 'error' || progress.status === 'failed') {
            newStatus = 'error';
          }

          setUploadedFiles(prev =>
            prev.map(f =>
              f.id === fileId
                ? { 
                    ...f, 
                    status: newStatus,
                    progress: progress.progress || f.progress
                  }
                : f
            )
          );

          // Stop monitoring if completed or error
          if (newStatus === 'completed' || newStatus === 'error') {
            return;
          }
        } else if (response.status === 404) {
          // Document not found, stop monitoring
          console.warn(`Document ${documentId} not found, stopping progress monitoring`);
          return;
        } else if (response.status === 401) {
          // Unauthorized, stop monitoring
          console.warn('Unauthorized access to document progress, stopping monitoring');
          return;
        }
      } catch (error) {
        console.error('Failed to fetch processing progress:', error);
        // Don't stop monitoring on network errors, just log and continue
      }

      // Continue monitoring with shorter intervals for better responsiveness
      setTimeout(checkProgress, 3000); // Check every 3 seconds
    };

    // Start monitoring immediately
    setTimeout(checkProgress, 500); // Start checking after 500ms
  }, [token]);

  const { getRootProps, getInputProps, isDragActive } = useDropzone({
    onDrop,
    accept: {
      'application/pdf': ['.pdf'],
    },
    multiple: true,
    maxSize: 50 * 1024 * 1024, // 50MB
  });

  const removeFile = (fileId: string) => {
    // Cancel the upload if it's still in progress
    const controller = abortControllers.current.get(fileId);
    if (controller) {
      controller.abort();
      abortControllers.current.delete(fileId);
    }
    
    setUploadedFiles(prev => prev.filter(f => f.id !== fileId));
  };

  const formatFileSize = (bytes: number) => {
    if (bytes === 0) return '0 Bytes';
    const k = 1024;
    const sizes = ['Bytes', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
  };

  const getStatusIcon = (status: UploadedFile['status']) => {
    switch (status) {
      case 'uploading':
        return <div className="animate-spin rounded-full h-4 w-4 border-b-2 border-primary-600" />;
      case 'uploaded':
        return <CheckCircle className="h-4 w-4 text-success-500" />;
      case 'processing':
        return <div className="animate-spin rounded-full h-4 w-4 border-b-2 border-accent-500" />;
      case 'completed':
        return <CheckCircle className="h-4 w-4 text-success-500" />;
      case 'error':
        return <AlertCircle className="h-4 w-4 text-error-500" />;
      default:
        return null;
    }
  };

  const getStatusText = (status: UploadedFile['status'], error?: string, storageError?: boolean) => {
    switch (status) {
      case 'uploading':
        return 'Uploading to Firebase Storage...';
      case 'uploaded':
        return 'Uploaded to Firebase Storage ✓';
      case 'processing':
        return 'Processing with Document AI + Optimized Agentic RAG...';
      case 'completed':
        return 'Completed ✓ (PDF automatically deleted)';
      case 'error':
        if (error === 'Upload cancelled') return 'Cancelled';
        if (storageError) return 'Firebase Storage Error';
        return 'Error';
      default:
        return '';
    }
  };

  return (
    <div className="space-y-6">
      {/* Processing Information */}
      <div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
        <div className="flex items-center">
          <CheckCircle className="h-5 w-5 text-blue-600 mr-2" />
          <div>
            <h3 className="text-sm font-medium text-blue-800">Document AI + Optimized Agentic RAG Processing</h3>
            <p className="text-sm text-blue-700 mt-1">
              All documents are automatically processed using Google Document AI for extraction and our advanced optimized agentic RAG system for analysis, 
              including intelligent chunking, vectorization, and multi-agent CIM review. PDFs are automatically deleted after processing.
            </p>
          </div>
        </div>
      </div>

      {/* Upload Area */}
      <div
        {...getRootProps()}
        className={cn(
          'border-2 border-dashed rounded-lg p-8 text-center cursor-pointer transition-colors duration-200',
          isDragActive
            ? 'border-primary-500 bg-primary-50'
            : 'border-gray-300 hover:border-primary-400'
        )}
      >
        <input {...getInputProps()} />
        <Upload className="mx-auto h-12 w-12 text-gray-400 mb-4" />
        <h3 className="text-lg font-medium text-primary-800 mb-2">
          {isDragActive ? 'Drop files here' : 'Upload Documents'}
        </h3>
        <p className="text-sm text-gray-600 mb-4">
          Drag and drop PDF files here, or click to browse
        </p>
        <p className="text-xs text-gray-500">
          Maximum file size: 50MB • Supported format: PDF • Stored securely in Firebase Storage • Automatic Document AI + Optimized Agentic RAG Processing • PDFs deleted after processing
        </p>
      </div>

      {/* Upload Cancellation Warning */}
      {isUploading && (
        <div className="bg-warning-50 border border-warning-200 rounded-lg p-4">
          <div className="flex items-center">
            <AlertCircle className="h-5 w-5 text-warning-600 mr-2" />
            <div>
              <h4 className="text-sm font-medium text-warning-800">Upload in Progress</h4>
              <p className="text-sm text-warning-700 mt-1">
                Please don't navigate away from this page while files are uploading. 
                Once files show "Uploaded ✓", you can safely navigate away - processing will continue in the background.
              </p>
            </div>
          </div>
        </div>
      )}

      {/* Upload Complete Success Message */}
      {!isUploading && uploadedFiles.some(f => f.status === 'uploaded') && (
        <div className="bg-success-50 border border-success-200 rounded-lg p-4">
          <div className="flex items-center">
            <CheckCircle className="h-5 w-5 text-success-600 mr-2" />
            <div>
              <h4 className="text-sm font-medium text-success-800">Upload Complete</h4>
              <p className="text-sm text-success-700 mt-1">
                Files have been uploaded successfully to Firebase Storage! You can now navigate away from this page. 
                Processing will continue in the background using Document AI + Optimized Agentic RAG. This can take several minutes. PDFs will be automatically deleted after processing to save costs.
              </p>
            </div>
          </div>
        </div>
      )}

      {/* Uploaded Files List */}
      {uploadedFiles.length > 0 && (
        <div className="space-y-3">
          <h4 className="text-sm font-medium text-primary-800">Uploaded Files</h4>
          <div className="space-y-2">
            {uploadedFiles.map((file) => (
              <div
                key={file.id}
                className="flex items-center justify-between p-3 bg-white border border-gray-200 rounded-lg"
              >
                <div className="flex items-center space-x-3 flex-1 min-w-0">
                  <FileText className="h-5 w-5 text-gray-400 flex-shrink-0" />
                  <div className="flex-1 min-w-0">
                    <p className="text-sm font-medium text-gray-900 truncate">
                      {file.name}
                    </p>
                    <p className="text-xs text-gray-500">
                      {formatFileSize(file.size)}
                    </p>
                  </div>
                </div>
                
                <div className="flex items-center space-x-3">
                  {/* Progress Bar */}
                  {(file.status === 'uploading' || file.status === 'processing') && (
                    <div className="w-24 bg-gray-200 rounded-full h-2">
                      <div
                        className={`h-2 rounded-full transition-all duration-300 ${
                          file.status === 'uploading' ? 'bg-blue-600' : 'bg-orange-600'
                        }`}
                        style={{ width: `${file.progress}%` }}
                      />
                    </div>
                  )}
                  
                  {/* Status */}
                  <div className="flex items-center space-x-1">
                    {getStatusIcon(file.status)}
                    <span className="text-xs text-gray-600">
                      {getStatusText(file.status, file.error, file.storageError)}
                    </span>
                    {/* Firebase Storage indicator */}
                    {file.storageType === 'firebase' && (
                      <Cloud className="h-3 w-3 text-blue-500" />
                    )}
                  </div>
                  
                  {/* Remove Button */}
                  <button
                    onClick={() => removeFile(file.id)}
                    className="text-gray-400 hover:text-gray-600 transition-colors"
                    disabled={file.status === 'uploading' || file.status === 'processing'}
                  >
                    <X className="h-4 w-4" />
                  </button>
                </div>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
};

export default DocumentUpload;