import React, { useEffect, useRef, useState } from 'react';
import Uppy from '@uppy/core';
import Dashboard from '@uppy/dashboard';
import XHRUpload from '@uppy/xhr-upload';
import ImageEditor from '@uppy/image-editor';
import { DashboardModal } from '@uppy/react';
import { supabase } from '@/integrations/supabase/client';
import { useToast } from '@/hooks/use-toast';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { Upload, X, Eye, Loader2 } from 'lucide-react';
import { cn } from '@/lib/utils';

interface UppyPhotoUploadProps {
  onUploadComplete?: (urls: string[]) => void;
  onUploadStart?: () => void;
  onUploadError?: (error: Error) => void;
  maxFiles?: number;
  maxSizeMB?: number;
  allowedFileTypes?: string[];
  metadata?: Record<string, any>;
  variant?: string;
  className?: string;
  children?: React.ReactNode;
  disabled?: boolean;
  showPreview?: boolean;
  size?: 'default' | 'compact' | 'large';
}

interface CloudflareResponse {
  uploadURL: string;
  id: string;
}

interface UploadSuccessResponse {
  success: boolean;
  id: string;
  uploaded: boolean;
  urls?: {
    public: string;
    thumbnail: string;
    medium: string;
    large: string;
    avatar: string;
  };
}

export function UppyPhotoUpload({
  onUploadComplete,
  onUploadStart,
  onUploadError,
  maxFiles = 5,
  maxSizeMB = 10,
  allowedFileTypes = ['image/*'],
  metadata = {},
  variant = 'public',
  className = '',
  children,
  disabled = false,
  showPreview = true,
  size = 'default',
}: UppyPhotoUploadProps) {
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [uploadedImages, setUploadedImages] = useState<string[]>([]);
  const [isUploading, setIsUploading] = useState(false);
  const [uploadProgress, setUploadProgress] = useState(0);
  const uppyRef = useRef<Uppy | null>(null);
  const { toast } = useToast();

  useEffect(() => {
    // Initialize Uppy
    const uppy = new Uppy({
      restrictions: {
        maxNumberOfFiles: maxFiles,
        allowedFileTypes,
        maxFileSize: maxSizeMB * 1024 * 1024,
      },
      autoProceed: false,
    });

    // Add Dashboard plugin
    uppy.use(Dashboard, {
      inline: false,
      trigger: null,
      hideProgressDetails: false,
      proudlyDisplayPoweredByUppy: false,
      showRemoveButtonAfterComplete: true,
      showSelectedFiles: true,
      note: `Images up to ${maxSizeMB}MB, max ${maxFiles} files`,
      theme: 'auto',
      closeAfterFinish: true,
    });

    // Add Image Editor plugin
    uppy.use(ImageEditor, {
      quality: 0.8,
      cropperOptions: {
        viewMode: 1,
        background: false,
        autoCropArea: 1,
      },
    });

    // Add XHR Upload plugin (configured per file in beforeUpload)
    uppy.use(XHRUpload, {
      endpoint: '', // Will be set dynamically
      method: 'POST',
      formData: true,
      bundle: false,
    });

    // Before upload hook - fetch upload URL for each file
    uppy.on('files-added', async (files) => {
      if (disabled) {
        uppy.cancelAll();
        return;
      }

      setIsUploading(true);
      setUploadProgress(0);
      onUploadStart?.();

      // Process each file to get upload URL
      for (const file of files) {
        try {
          const response = await supabase.functions.invoke('upload-image', {
            body: { metadata, variant },
          });

          if (response.error) {
            throw new Error(response.error.message);
          }

          const result: CloudflareResponse = response.data;
          
          // Store Cloudflare ID in file meta
          uppy.setFileMeta(file.id, {
            ...file.meta,
            cloudflareId: result.id,
          });

          // Configure XHR upload endpoint for this file
          const xhrPlugin = uppy.getPlugin('XHRUpload') as any;
          if (xhrPlugin) {
            xhrPlugin.setOptions({
              endpoint: result.uploadURL,
            });
          }
        } catch (error) {
          console.error('Failed to get upload URL:', error);
          uppy.removeFile(file.id);
          toast({
            variant: 'destructive',
            title: 'Upload Error',
            description: `Failed to prepare upload for ${file.name}`,
          });
          onUploadError?.(error as Error);
        }
      }
    });

    // Handle upload progress
    uppy.on('progress', (progress) => {
      setUploadProgress(Math.round(progress));
    });

    // Handle upload success
    uppy.on('upload-success', async (file, response) => {
      try {
        const cloudflareId = file?.meta?.cloudflareId as string;
        if (!cloudflareId) {
          throw new Error('Missing Cloudflare ID');
        }

        // Poll for upload completion
        let attempts = 0;
        const maxAttempts = 30; // 30 seconds max
        let imageData: UploadSuccessResponse | null = null;

        while (attempts < maxAttempts) {
          const statusResponse = await supabase.functions.invoke('upload-image', {
            body: null,
            method: 'GET',
          });

          if (!statusResponse.error && statusResponse.data) {
            const status: UploadSuccessResponse = statusResponse.data;
            if (status.uploaded && status.urls) {
              imageData = status;
              break;
            }
          }

          await new Promise(resolve => setTimeout(resolve, 1000));
          attempts++;
        }

        if (imageData?.urls) {
          setUploadedImages(prev => [...prev, imageData.urls!.public]);
        }
      } catch (error) {
        console.error('Upload post-processing failed:', error);
        onUploadError?.(error as Error);
      }
    });

    // Handle upload error
    uppy.on('upload-error', (file, error, response) => {
      console.error('Upload error:', error);
      setIsUploading(false);
      
      // Check if it's an expired URL error and retry
      if (error.message?.includes('expired') || response?.status === 400) {
        toast({
          title: 'Upload URL Expired',
          description: 'Retrying upload...',
        });
        
        // Retry the upload by re-adding the file
        if (file) {
          uppy.removeFile(file.id);
          // Re-add the file to trigger new URL fetch
          uppy.addFile({
            source: 'retry',
            name: file.name,
            type: file.type,
            data: file.data,
            meta: { ...file.meta, cloudflareId: undefined },
          });
        }
      } else {
        toast({
          variant: 'destructive',
          title: 'Upload Failed',
          description: error.message || 'An error occurred during upload',
        });
        onUploadError?.(error);
      }
    });

    // Handle upload complete
    uppy.on('complete', (result) => {
      setIsUploading(false);
      setUploadProgress(0);
      
      if (result.successful.length > 0) {
        onUploadComplete?.(uploadedImages);
        toast({
          title: 'Upload Complete',
          description: `Successfully uploaded ${result.successful.length} image(s)`,
        });
      }
      setIsModalOpen(false);
    });

    uppyRef.current = uppy;

    return () => {
      uppy.destroy();
    };
  }, [maxFiles, maxSizeMB, allowedFileTypes, metadata, variant, disabled, onUploadStart, onUploadComplete, onUploadError, toast, uploadedImages, size]);

  const removeImage = (index: number) => {
    const newUrls = uploadedImages.filter((_, i) => i !== index);
    setUploadedImages(newUrls);
    if (onUploadComplete) {
      onUploadComplete(newUrls);
    }
  };

  const handleOpenModal = () => {
    if (!disabled) {
      setIsModalOpen(true);
    }
  };

  const getSizeClasses = () => {
    switch (size) {
      case 'compact':
        return 'px-4 py-2 text-sm';
      case 'large':
        return 'px-8 py-4 text-lg';
      default:
        return 'px-6 py-3';
    }
  };

  const renderUploadTrigger = () => {
    if (children) {
      return (
        <div onClick={handleOpenModal} className="cursor-pointer">
          {children}
        </div>
      );
    }

    const baseClasses = "photo-upload-trigger transition-all duration-300 flex items-center justify-center gap-2";
    const sizeClasses = getSizeClasses();
    const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer hover:scale-105';
    
    return (
      <Button
        onClick={handleOpenModal}
        disabled={disabled || isUploading}
        className={cn(baseClasses, sizeClasses, disabledClasses)}
        size={size === 'compact' ? 'sm' : size === 'large' ? 'lg' : 'default'}
      >
        {isUploading ? (
          <>
            <Loader2 className="w-4 h-4 animate-spin" />
            Uploading... {uploadProgress}%
          </>
        ) : (
          <>
            <Upload className="w-4 h-4" />
            {size === 'compact' ? 'Upload' : 'Upload Photos'}
          </>
        )}
      </Button>
    );
  };

  const renderPreview = () => {
    if (!showPreview || uploadedImages.length === 0) return null;

    return (
      <div className="mt-4">
        <div className="flex items-center justify-between mb-3">
          <span className="text-sm font-medium text-muted-foreground">
            Uploaded Photos ({uploadedImages.length})
          </span>
          <Badge variant="secondary" className="text-xs">
            {uploadedImages.length}/{maxFiles}
          </Badge>
        </div>
        <div className="upload-preview-grid">
          {uploadedImages.map((url, index) => (
            <div key={index} className="upload-preview-item group">
              <img
                src={url}
                alt={`Uploaded ${index + 1}`}
                className="w-full h-full object-cover"
              />
              <div className="upload-preview-overlay">
                <button
                  onClick={() => removeImage(index)}
                  className="p-1 bg-destructive text-destructive-foreground rounded-full hover:bg-destructive/90 transition-colors mr-2"
                  title="Remove image"
                >
                  <X className="w-3 h-3" />
                </button>
                <button
                  onClick={() => window.open(url, '_blank')}
                  className="p-1 bg-primary text-primary-foreground rounded-full hover:bg-primary/90 transition-colors"
                  title="View full size"
                >
                  <Eye className="w-3 h-3" />
                </button>
              </div>
            </div>
          ))}
        </div>
      </div>
    );
  };

  return (
    <div className={cn("space-y-4", className)}>
      {renderUploadTrigger()}
      {renderPreview()}
      
      {uppyRef.current && (
        <DashboardModal
          uppy={uppyRef.current}
          open={isModalOpen}
          onRequestClose={() => setIsModalOpen(false)}
          closeModalOnClickOutside
          animateOpenClose
          browserBackButtonClose
        />
      )}
    </div>
  );
}