"use client"

import React, { useCallback, useState, useRef } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import { cva } from 'class-variance-authority'
import { 
  Upload, 
  X, 
  File, 
  Image as ImageIcon, 
  Video, 
  Music, 
  FileText,
  AlertCircle,
  Loader2,
  Play,
  Pause,
  RotateCcw,
  Download,
  Eye,
  Trash2,
  MoreHorizontal,
  Copy,
  Share,
  Archive,
  Lock,
  Sparkles,
  CheckCircle2
} from 'lucide-react'
import { cn } from '../../lib/utils'
import { Button } from '../ui/button'
import { Badge } from '../ui/badge'
import { Progress } from '../ui/progress'
import { Card, CardContent } from '../ui/card'
import { 
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger 
} from '../ui/dropdown-menu'
import { 
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle 
} from '../ui/dialog'
import { useSubscription } from '../../hooks/use-subscription'
import { useToast } from '../../use-toast'

// Ana interface'ler ve type'lar
export interface FileUploadProProps {
  accept?: string
  multiple?: boolean
  maxSize?: number // bytes cinsinden
  maxFiles?: number
  disabled?: boolean
  className?: string
  variant?: 'default' | 'compact' | 'grid'
  theme?: 'light' | 'dark' | 'auto'
  
  // Gelişmiş özellikler
  chunkSize?: number // chunk upload için
  resumable?: boolean
  compression?: boolean
  imageResize?: {
    maxWidth: number
    maxHeight: number
    quality: number
  }
  
  // Validasyon
  allowedMimeTypes?: string[]
  maxTotalSize?: number
  customValidation?: (file: File) => Promise<string | null>
  duplicateCheck?: boolean
  
  // Upload ayarları
  uploadStrategy?: 'direct' | 'presigned' | 'multipart'
  endpoint?: string
  headers?: Record<string, string>
  
  // Service integrations
  serviceConfig?: {
    type: 'aws-s3' | 'cloudinary' | 'firebase' | 'custom'
    config?: any
  }
  
  // Callbacks
  onUpload?: (files: FileUploadItem[]) => Promise<void>
  onProgress?: (fileId: string, progress: number) => void
  onComplete?: (fileId: string, result: any) => void
  onError?: (fileId: string, error: string) => void
  onRemove?: (fileId: string) => void
  onPreview?: (file: FileUploadItem) => void
  onBulkSelect?: (selectedIds: string[]) => void
  
  // UI özelleştirme
  showPreview?: boolean
  showProgress?: boolean
  showMetadata?: boolean
  allowBulkOperations?: boolean
  previewTypes?: ('image' | 'video' | 'audio' | 'pdf' | 'document')[]
}

export interface FileUploadItem {
  id: string
  file: File
  status: 'pending' | 'uploading' | 'paused' | 'success' | 'error' | 'cancelled'
  progress: number
  uploadedBytes?: number
  totalBytes: number
  speed?: number // bytes/second
  estimatedTime?: number // seconds
  error?: string
  chunks?: FileChunk[]
  preview?: FilePreview
  metadata?: FileMetadata
  result?: any // upload sonucu
}

interface FileChunk {
  index: number
  start: number
  end: number
  status: 'pending' | 'uploading' | 'success' | 'error'
  attempts: number
}

interface FilePreview {
  type: 'image' | 'video' | 'audio' | 'pdf' | 'document' | 'unknown'
  url?: string
  thumbnail?: string
  duration?: number // video/audio için
  dimensions?: { width: number; height: number }
  pages?: number // PDF için
}

interface FileMetadata {
  name: string
  size: number
  type: string
  lastModified: number
  hash?: string
  dimensions?: { width: number; height: number }
  duration?: number
  bitrate?: number
}

// CVA variants
const fileUploadVariants = cva(
  "relative overflow-hidden transition-all duration-200",
  {
    variants: {
      variant: {
        default: "border-2 border-dashed rounded-lg p-8",
        compact: "border border-dashed rounded-md p-4",
        grid: "border-2 border-dashed rounded-lg p-6"
      },
      state: {
        idle: "border-muted-foreground/25 hover:border-primary/50",
        dragover: "border-primary bg-primary/5 scale-102",
        disabled: "opacity-50 cursor-not-allowed"
      }
    },
    defaultVariants: {
      variant: "default",
      state: "idle"
    }
  }
)

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

const formatTime = (seconds: number): string => {
  if (seconds < 60) return `${Math.round(seconds)}s`
  const minutes = Math.floor(seconds / 60)
  const remainingSeconds = Math.round(seconds % 60)
  return `${minutes}m ${remainingSeconds}s`
}

const getFileIcon = (type: string, size: 'sm' | 'md' | 'lg' = 'md') => {
  const iconSize = size === 'sm' ? 'h-4 w-4' : size === 'md' ? 'h-5 w-5' : 'h-6 w-6'
  
  if (type.startsWith('image/')) return <ImageIcon className={iconSize} />
  if (type.startsWith('video/')) return <Video className={iconSize} />
  if (type.startsWith('audio/')) return <Music className={iconSize} />
  if (type.includes('pdf')) return <FileText className={iconSize} />
  if (type.includes('zip') || type.includes('rar') || type.includes('7z')) {
    return <Archive className={iconSize} />
  }
  return <File className={iconSize} />
}

const generateFileHash = async (file: File): Promise<string> => {
  const buffer = await file.arrayBuffer()
  const hashBuffer = await crypto.subtle.digest('SHA-256', buffer)
  const hashArray = Array.from(new Uint8Array(hashBuffer))
  return hashArray.map(b => b.toString(16).padStart(2, '0')).join('')
}

const createImagePreview = (file: File): Promise<FilePreview> => {
  return new Promise((resolve) => {
    const reader = new FileReader()
    
    reader.onload = (e) => {
      const result = e.target?.result as string
      const img = new Image()
      
      img.onload = () => {
        // Create high-quality thumbnail
        const canvas = document.createElement('canvas')
        const ctx = canvas.getContext('2d')!
        
        // Calculate thumbnail dimensions (max 400px)
        const maxThumbSize = 400
        let thumbWidth = img.width
        let thumbHeight = img.height
        
        if (thumbWidth > maxThumbSize || thumbHeight > maxThumbSize) {
          const aspectRatio = img.width / img.height
          if (aspectRatio > 1) {
            thumbWidth = maxThumbSize
            thumbHeight = maxThumbSize / aspectRatio
          } else {
            thumbHeight = maxThumbSize
            thumbWidth = maxThumbSize * aspectRatio
          }
        }
        
        canvas.width = thumbWidth
        canvas.height = thumbHeight
        ctx.drawImage(img, 0, 0, thumbWidth, thumbHeight)
        
        const thumbnail = canvas.toDataURL('image/jpeg', 0.9)
        
        resolve({
          type: 'image',
          url: result,
          thumbnail,
          dimensions: { width: img.width, height: img.height }
        })
      }
      
      img.onerror = () => {
        resolve({
          type: 'image',
          url: result,
          thumbnail: result
        })
      }
      
      img.src = result
    }
    
    reader.onerror = () => {
      const url = URL.createObjectURL(file)
      resolve({
        type: 'image',
        url
      })
    }
    
    reader.readAsDataURL(file)
  })
}

const createVideoPreview = (file: File): Promise<FilePreview> => {
  return new Promise((resolve) => {
    const video = document.createElement('video')
    const url = URL.createObjectURL(file)
    
    video.onloadedmetadata = () => {
      // Video thumbnail oluşturma
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')!
      
      canvas.width = 320
      canvas.height = (video.videoHeight / video.videoWidth) * 320
      
      video.currentTime = Math.min(1, video.duration / 4) // İlk saniye veya %25
      
      video.onseeked = () => {
        ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
        const thumbnail = canvas.toDataURL('image/jpeg', 0.8)
        
        resolve({
          type: 'video',
          url,
          thumbnail,
          duration: video.duration,
          dimensions: { width: video.videoWidth, height: video.videoHeight }
        })
      }
    }
    
    video.onerror = () => {
      resolve({
        type: 'video',
        url
      })
    }
    
    video.src = url
  })
}

// Bulk operation bileşeni
const BulkActions = ({ 
  selectedIds, 
  onClearSelection, 
  onBulkRemove,
  onBulkDownload 
}: {
  selectedIds: string[]
  onClearSelection: () => void
  onBulkRemove: () => void
  onBulkDownload: () => void
}) => {
  if (selectedIds.length === 0) return null
  
  return (
    <motion.div
      initial={{ opacity: 0, y: -10 }}
      animate={{ opacity: 1, y: 0 }}
      exit={{ opacity: 0, y: -10 }}
      className="flex items-center gap-2 p-3 bg-primary/5 rounded-lg border"
    >
      <span className="text-sm font-medium">{selectedIds.length} files selected</span>
      <div className="flex gap-1 ml-auto">
        <Button variant="ghost" size="sm" onClick={onBulkDownload}>
          <Download className="h-4 w-4 mr-1" />
          Download
        </Button>
        <Button variant="ghost" size="sm" onClick={onBulkRemove}>
          <Trash2 className="h-4 w-4 mr-1" />
          Delete
        </Button>
        <Button variant="ghost" size="sm" onClick={onClearSelection}>
          <X className="h-4 w-4" />
        </Button>
      </div>
    </motion.div>
  )
}

// Dosya önizleme modal
const FilePreviewModal = ({ 
  file, 
  isOpen, 
  onClose 
}: {
  file: FileUploadItem | null
  isOpen: boolean
  onClose: () => void
}) => {
  if (!file || !file.preview) return null
  
  return (
    <Dialog open={isOpen} onOpenChange={onClose}>
      <DialogContent className="max-w-4xl max-h-[90vh]">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2">
            {getFileIcon(file.file.type)}
            {file.file.name}
            <Badge variant="secondary">
              {formatFileSize(file.file.size)}
            </Badge>
          </DialogTitle>
        </DialogHeader>
        
        <div className="flex items-center justify-center p-4 bg-muted/20 rounded-lg">
          {file.preview.type === 'image' && (
            <div className="relative">
              <img 
                src={file.preview.url} 
                alt={file.file.name}
                className="max-w-full max-h-[60vh] object-contain rounded shadow-lg"
                loading="eager"
              />
              {/* Image loading indicator */}
              <div className="absolute inset-0 flex items-center justify-center bg-background/80 rounded opacity-0 pointer-events-none transition-opacity duration-300">
                <Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
              </div>
            </div>
          )}
          
          {file.preview.type === 'video' && (
            <div className="relative w-full max-w-4xl">
              <video 
                src={file.preview.url} 
                controls 
                className="w-full max-h-[60vh] rounded shadow-lg"
                poster={file.preview.thumbnail}
              />
            </div>
          )}
          
          {file.preview.type === 'audio' && (
            <div className="w-full max-w-md space-y-4">
              <div className="p-8 bg-gradient-to-br from-primary/10 to-primary/5 rounded-lg">
                <Music className="h-16 w-16 mx-auto text-primary mb-4" />
                <audio src={file.preview.url} controls className="w-full" />
              </div>
            </div>
          )}
          
          {!['image', 'video', 'audio'].includes(file.preview.type) && (
            <div className="text-center py-8">
              {getFileIcon(file.file.type, 'lg')}
              <p className="mt-2 text-muted-foreground">Preview not available</p>
            </div>
          )}
        </div>
        
        {file.preview.dimensions && (
          <div className="flex gap-4 text-sm text-muted-foreground">
            <span>Dimensions: {file.preview.dimensions.width} × {file.preview.dimensions.height}</span>
            {file.preview.duration && (
              <span>Duration: {formatTime(file.preview.duration)}</span>
            )}
          </div>
        )}
      </DialogContent>
    </Dialog>
  )
}

// Ana bileşen
export const MoonUIFileUploadPro = React.forwardRef<HTMLDivElement, FileUploadProProps>(
  ({
    accept = "*",
    multiple = true,
    maxSize = 100 * 1024 * 1024, // 100MB
    maxFiles = 10,
    disabled = false,
    className,
    variant = "default",
    chunkSize = 1024 * 1024, // 1MB chunks
    resumable = true,
    compression = false,
    allowedMimeTypes = [],
    maxTotalSize,
    duplicateCheck = true,
    uploadStrategy = 'direct',
    showPreview = true,
    showProgress = true,
    showMetadata = true,
    allowBulkOperations = true,
    previewTypes = ['image', 'video', 'audio', 'pdf'],
    onUpload,
    onProgress,
    onComplete,
    onError,
    onRemove,
    onPreview,
    onBulkSelect,
    customValidation,
    serviceConfig,
    imageResize,
    endpoint,
    headers,
    ...props
  }, ref) => {
    
    // Subscription kontrolü - Pro bileşen
    const { hasProAccess, isLoading } = useSubscription()
    
    // State'ler
    const [files, setFiles] = useState<FileUploadItem[]>([])
    const [isDragOver, setIsDragOver] = useState(false)
    const [selectedIds, setSelectedIds] = useState<string[]>([])
    const [previewFile, setPreviewFile] = useState<FileUploadItem | null>(null)
    const [isPreviewOpen, setIsPreviewOpen] = useState(false)
    const [error, setError] = useState<string | null>(null)
    
    const fileInputRef = useRef<HTMLInputElement>(null)
    const uploadQueue = useRef<Map<string, AbortController>>(new Map())
    
    // Pro lisans kontrolü
    if (!isLoading && !hasProAccess) {
      return (
        <Card className={cn("w-full", className)}>
          <CardContent className="py-12 text-center">
            <div className="max-w-md mx-auto space-y-4">
              <div className="rounded-full bg-purple-100 dark:bg-purple-900/30 p-3 w-fit mx-auto">
                <Lock className="h-6 w-6 text-purple-600 dark:text-purple-400" />
              </div>
              <div>
                <h3 className="font-semibold text-lg mb-2">Pro Feature</h3>
                <p className="text-muted-foreground text-sm mb-4">
                  Advanced File Upload is exclusive to MoonUI Pro subscribers.
                </p>
                <div className="flex gap-3 justify-center">
                  <a href="/pricing">
                    <Button size="sm">
                      <Sparkles className="mr-2 h-4 w-4" />
                      Upgrade to Pro
                    </Button>
                  </a>
                </div>
              </div>
            </div>
          </CardContent>
        </Card>
      )
    }
    
    // Dosya validasyonu
    const validateFile = useCallback(async (file: File): Promise<string | null> => {
      // Boyut kontrolü
      if (file.size > maxSize) {
        return `File size exceeds ${formatFileSize(maxSize)} limit`
      }
      
      // MIME type kontrolü
      if (allowedMimeTypes.length > 0 && !allowedMimeTypes.includes(file.type)) {
        return `File type ${file.type} is not supported`
      }
      
      // Accept kontrolü
      if (accept !== "*") {
        const acceptTypes = accept.split(',').map(t => t.trim())
        const isAccepted = acceptTypes.some(acceptType => {
          if (acceptType.includes('*')) {
            return file.type.startsWith(acceptType.replace('*', ''))
          }
          return file.type === acceptType
        })
        
        if (!isAccepted) {
          return `File type not accepted`
        }
      }
      
      // Özel validasyon
      if (customValidation) {
        const customError = await customValidation(file)
        if (customError) return customError
      }
      
      return null
    }, [maxSize, allowedMimeTypes, accept, customValidation])
    
    // Duplicate kontrolü
    const checkDuplicate = useCallback(async (file: File): Promise<boolean> => {
      if (!duplicateCheck) return false
      
      const hash = await generateFileHash(file)
      return files.some(f => f.metadata?.hash === hash)
    }, [files, duplicateCheck])
    
    // Dosya önizleme oluşturma
    const createPreview = useCallback(async (file: File): Promise<FilePreview | undefined> => {
      if (!showPreview) return undefined
      
      const fileType = file.type.split('/')[0] as 'image' | 'video' | 'audio'
      
      if (!previewTypes.includes(fileType)) return undefined
      
      try {
        if (fileType === 'image') {
          return await createImagePreview(file)
        } else if (fileType === 'video') {
          return await createVideoPreview(file)
        } else if (fileType === 'audio') {
          const url = URL.createObjectURL(file)
          return {
            type: 'audio',
            url
          }
        }
      } catch (error) {
        console.warn('Failed to create preview:', error)
      }
      
      return undefined
    }, [showPreview, previewTypes])
    
    // Dosya metadata oluşturma
    const createMetadata = useCallback(async (file: File): Promise<FileMetadata> => {
      const metadata: FileMetadata = {
        name: file.name,
        size: file.size,
        type: file.type,
        lastModified: file.lastModified
      }
      
      if (duplicateCheck) {
        metadata.hash = await generateFileHash(file)
      }
      
      return metadata
    }, [duplicateCheck])
    
    // Image resize handler
    const resizeImage = useCallback(async (file: File): Promise<File> => {
      if (!imageResize || !file.type.startsWith('image/')) return file

      const { maxWidth, maxHeight, quality } = imageResize

      return new Promise((resolve) => {
        const img = new Image()
        const reader = new FileReader()

        reader.onload = (e) => {
          img.src = e.target?.result as string

          img.onload = () => {
            const canvas = document.createElement('canvas')
            const ctx = canvas.getContext('2d')!

            let width = img.width
            let height = img.height

            // Calculate new dimensions
            if (width > maxWidth || height > maxHeight) {
              const aspectRatio = width / height
              if (width > height) {
                width = maxWidth
                height = maxWidth / aspectRatio
              } else {
                height = maxHeight
                width = maxHeight * aspectRatio
              }
            }

            canvas.width = width
            canvas.height = height
            ctx.drawImage(img, 0, 0, width, height)

            canvas.toBlob(
              (blob) => {
                if (blob) {
                  // Create a resized file
                  const resizedFile = new window.File([blob], file.name, {
                    type: file.type,
                    lastModified: Date.now()
                  })
                  resolve(resizedFile)
                } else {
                  resolve(file)
                }
              },
              file.type,
              quality
            )
          }
        }

        reader.readAsDataURL(file)
      })
    }, [imageResize])
    
    // Service specific upload handler
    const uploadToService = useCallback(async (fileItem: FileUploadItem): Promise<any> => {
      if (!serviceConfig) return null

      const { file } = fileItem
      let processedFile = file
      
      // Resize image if needed
      if (imageResize && file.type.startsWith('image/')) {
        processedFile = await resizeImage(file)
      }

      try {
        switch (serviceConfig.type) {
          case 'aws-s3': {
            // AWS S3 Direct Upload
            const { config } = serviceConfig as any
            if (!config) throw new Error('AWS S3 config is required')
            
            const { bucketUrl, bucketName, region, accessKeyId, policy, signature, algorithm, credential, date, fields } = config
            
            if (!bucketUrl && !bucketName) {
              throw new Error('AWS S3 requires either bucketUrl or bucketName')
            }
            
            // Option 1: Direct upload to custom S3-compatible endpoint
            if (bucketUrl && !bucketName) {
              const formData = new FormData()
              formData.append('file', processedFile || file)
              
              const response = await fetch(bucketUrl, {
                method: 'POST',
                body: formData,
                headers: {
                  ...headers,
                  ...(config.headers || {})
                }
              })
              
              if (!response.ok) {
                throw new Error(`Upload failed: ${response.statusText}`)
              }
              
              return await response.json()
            }
            
            // Option 2: AWS S3 POST upload with policy-based authentication
            // This requires server-side generation of policy and signature
            const s3Endpoint = bucketUrl || `https://${bucketName}.s3.${region || 'us-east-1'}.amazonaws.com/`
            const key = fields?.key || `uploads/${Date.now()}_${file.name}`
            
            const formData = new FormData()
            
            // AWS S3 POST policy fields must be added in specific order
            if (fields) {
              // Add all policy fields first
              Object.entries(fields).forEach(([k, v]) => {
                if (k !== 'file') {
                  formData.append(k, v as string)
                }
              })
            } else {
              // Basic fields for public bucket upload
              formData.append('key', key)
              if (accessKeyId) formData.append('AWSAccessKeyId', accessKeyId)
              formData.append('Content-Type', file.type)
              if (policy) formData.append('policy', policy)
              if (signature) formData.append('signature', signature)
              if (algorithm) formData.append('x-amz-algorithm', algorithm)
              if (credential) formData.append('x-amz-credential', credential)
              if (date) formData.append('x-amz-date', date)
            }
            
            // File must be the last field
            formData.append('file', processedFile || file)
            
            const response = await fetch(s3Endpoint, {
              method: 'POST',
              body: formData
            })
            
            // S3 returns 204 No Content on success for POST uploads
            if (!response.ok && response.status !== 204) {
              const errorText = await response.text()
              throw new Error(`S3 upload failed: ${response.status} - ${errorText}`)
            }
            
            return {
              url: `${s3Endpoint}${key}`,
              key,
              bucket: bucketName,
              etag: response.headers.get('ETag'),
              location: response.headers.get('Location') || `${s3Endpoint}${key}`
            }
          }

          case 'cloudinary': {
            // Cloudinary upload logic
            const { config } = serviceConfig as any
            if (!config) throw new Error('Cloudinary config is required')
            
            const { cloudName, uploadPreset, apiKey } = config
            const formData = new FormData()
            formData.append('file', processedFile || file)
            formData.append('upload_preset', uploadPreset)
            
            if (apiKey) {
              formData.append('api_key', apiKey)
            }
            
            // Add optional transformations
            if (imageResize) {
              formData.append('eager', `w_${imageResize.maxWidth},h_${imageResize.maxHeight},c_limit,q_${Math.round(imageResize.quality * 100)}`)
            }
            
            const response = await fetch(
              `https://api.cloudinary.com/v1_1/${cloudName}/auto/upload`,
              {
                method: 'POST',
                body: formData
              }
            )
            
            if (!response.ok) throw new Error('Cloudinary upload failed')
            const result = await response.json()
            
            return {
              url: result.secure_url,
              publicId: result.public_id,
              format: result.format,
              width: result.width,
              height: result.height,
              bytes: result.bytes,
              cloudName
            }
          }

          case 'firebase': {
            // Firebase Storage REST API upload (no SDK required)
            const { config } = serviceConfig as any
            if (!config) throw new Error('Firebase config is required')
            
            const { storageBucket, folder = 'uploads' } = config
            const fileName = `${folder}/${Date.now()}-${file.name}`
            
            // Firebase Storage uses Google Cloud Storage REST API
            const uploadUrl = `https://storage.googleapis.com/upload/storage/v1/b/${storageBucket}/o?uploadType=media&name=${encodeURIComponent(fileName)}`
            
            const response = await fetch(uploadUrl, {
              method: 'POST',
              body: processedFile || file,
              headers: {
                'Content-Type': file.type,
                ...headers // Should include Authorization: Bearer [token]
              }
            })
            
            if (!response.ok) throw new Error('Firebase upload failed')
            const result = await response.json()
            
            return {
              url: `https://storage.googleapis.com/${storageBucket}/${fileName}`,
              name: result.name,
              bucket: result.bucket,
              generation: result.generation,
              contentType: result.contentType,
              size: result.size
            }
          }

          case 'custom': {
            // Custom endpoint upload
            if (!endpoint) throw new Error('Custom endpoint is required')
            
            const formData = new FormData()
            formData.append('file', file)
            
            const response = await fetch(endpoint, {
              method: 'POST',
              body: formData,
              headers: headers
            })
            
            if (!response.ok) throw new Error('Custom upload failed')
            return response.json()
          }

          default:
            throw new Error(`Unsupported service type: ${serviceConfig.type}`)
        }
      } catch (error) {
        console.error('Upload service error:', error)
        throw error
      }
    }, [serviceConfig, endpoint, headers, imageResize, resizeImage])

    // Chunked upload simülasyonu
    const uploadFileChunked = useCallback(async (fileItem: FileUploadItem) => {
      const { file } = fileItem
      const chunks: FileChunk[] = []
      const chunkCount = Math.ceil(file.size / chunkSize)
      
      // Chunk'ları oluştur
      for (let i = 0; i < chunkCount; i++) {
        chunks.push({
          index: i,
          start: i * chunkSize,
          end: Math.min((i + 1) * chunkSize, file.size),
          status: 'pending',
          attempts: 0
        })
      }
      
      // FileItem'i güncelle
      setFiles(prev => prev.map(f => 
        f.id === fileItem.id 
          ? { ...f, chunks, status: 'uploading' }
          : f
      ))
      
      const abortController = new AbortController()
      uploadQueue.current.set(fileItem.id, abortController)
      
      let uploadedBytes = 0
      const startTime = Date.now()
      
      try {
        // Image resize if needed
        let processedFile = file
        if (imageResize && file.type.startsWith('image/')) {
          processedFile = await resizeImage(file)
        }
        
        // If service config exists, do the actual upload
        if (serviceConfig) {
          const uploadResult = await uploadToService({ ...fileItem, file: processedFile })
          
          // Update progress to 100% immediately for service uploads
          setFiles(prev => prev.map(f => 
            f.id === fileItem.id 
              ? { ...f, status: 'success', progress: 100, result: uploadResult }
              : f
          ))
          
          onComplete?.(fileItem.id, uploadResult)
          return
        }
        
        // Regular chunk upload simulation for non-service uploads
        for (const chunk of chunks) {
          if (abortController.signal.aborted) {
            throw new Error('Upload cancelled')
          }
          
          await new Promise(resolve => setTimeout(resolve, 100 + Math.random() * 200))
          
          uploadedBytes += (chunk.end - chunk.start)
          const progress = Math.round((uploadedBytes / file.size) * 100)
          const elapsedTime = (Date.now() - startTime) / 1000
          const speed = uploadedBytes / elapsedTime
          const estimatedTime = (file.size - uploadedBytes) / speed
          
          // Progress güncelle
          setFiles(prev => prev.map(f => 
            f.id === fileItem.id 
              ? { 
                  ...f, 
                  progress, 
                  uploadedBytes, 
                  speed,
                  estimatedTime: estimatedTime || 0,
                  chunks: f.chunks?.map(c => 
                    c.index === chunk.index 
                      ? { ...c, status: 'success' }
                      : c
                  )
                }
              : f
          ))
          
          onProgress?.(fileItem.id, progress)
        }
        
        // Upload tamamlandı
        setFiles(prev => prev.map(f => 
          f.id === fileItem.id 
            ? { ...f, status: 'success', progress: 100 }
            : f
        ))
        
        onComplete?.(fileItem.id, { success: true })
        
      } catch (error) {
        setFiles(prev => prev.map(f => 
          f.id === fileItem.id 
            ? { ...f, status: 'error', error: error instanceof Error ? error.message : 'Upload failed' }
            : f
        ))
        
        onError?.(fileItem.id, error instanceof Error ? error.message : 'Upload failed')
      } finally {
        uploadQueue.current.delete(fileItem.id)
      }
    }, [chunkSize, onProgress, onComplete, onError, serviceConfig, uploadToService, resizeImage, imageResize])
    
    // Dosya işleme
    const processFiles = useCallback(async (fileList: FileList | File[]) => {
      const fileArray = Array.from(fileList)
      setError(null)
      
      // Toplam dosya sayısı kontrolü
      if (files.length + fileArray.length > maxFiles) {
        setError(`Maximum ${maxFiles} files allowed`)
        return
      }
      
      // Toplam boyut kontrolü
      if (maxTotalSize) {
        const currentSize = files.reduce((sum, f) => sum + f.file.size, 0)
        const newSize = fileArray.reduce((sum, f) => sum + f.size, 0)
        
        if (currentSize + newSize > maxTotalSize) {
          setError(`Total file size exceeds ${formatFileSize(maxTotalSize)} limit`)
          return
        }
      }
      
      const validFiles: File[] = []
      const errors: string[] = []
      
      // Her dosyayı validate et
      for (const file of fileArray) {
        const validationError = await validateFile(file)
        if (validationError) {
          errors.push(`${file.name}: ${validationError}`)
          continue
        }
        
        const isDuplicate = await checkDuplicate(file)
        if (isDuplicate) {
          errors.push(`${file.name}: File already exists`)
          continue
        }
        
        validFiles.push(file)
      }
      
      if (errors.length > 0) {
        setError(errors.join(', '))
      }
      
      if (validFiles.length === 0) return
      
      // FileUploadItem'ları oluştur
      const newFileItems: FileUploadItem[] = []
      
      for (const file of validFiles) {
        const id = `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`
        
        // Resize image if needed
        const processedFile = await resizeImage(file)
        
        const preview = await createPreview(processedFile)
        const metadata = await createMetadata(processedFile)
        
        newFileItems.push({
          id,
          file: processedFile,
          status: 'pending',
          progress: 0,
          totalBytes: processedFile.size,
          preview,
          metadata
        })
      }
      
      setFiles(prev => [...prev, ...newFileItems])
      
      // Upload işlemini başlat
      if (onUpload) {
        try {
          await onUpload(newFileItems)
        } catch (error) {
          console.error('Upload failed:', error)
        }
      } else {
        // Otomatik upload başlat
        newFileItems.forEach(fileItem => {
          uploadFileChunked(fileItem)
        })
      }
    }, [
      files, 
      maxFiles, 
      maxTotalSize, 
      validateFile, 
      checkDuplicate, 
      createPreview, 
      createMetadata, 
      onUpload, 
      uploadFileChunked,
      resizeImage
    ])
    
    // Drag & Drop handlers
    const handleDrop = useCallback((e: React.DragEvent) => {
      e.preventDefault()
      setIsDragOver(false)
      
      if (disabled) return
      
      const droppedFiles = Array.from(e.dataTransfer.files)
      if (droppedFiles.length > 0) {
        processFiles(droppedFiles)
      }
    }, [processFiles, disabled])
    
    const handleDragOver = useCallback((e: React.DragEvent) => {
      e.preventDefault()
      if (!disabled) {
        setIsDragOver(true)
      }
    }, [disabled])
    
    const handleDragLeave = useCallback((e: React.DragEvent) => {
      e.preventDefault()
      setIsDragOver(false)
    }, [])
    
    // Dosya seçimi
    const handleFileSelect = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
      const selectedFiles = e.target.files
      if (selectedFiles && selectedFiles.length > 0) {
        processFiles(selectedFiles)
      }
      // Input'u temizle
      e.target.value = ''
    }, [processFiles])
    
    // Dosya kaldırma
    const removeFile = useCallback((fileId: string) => {
      const fileToRemove = files.find(f => f.id === fileId)
      if (!fileToRemove) return
      
      // Upload'ı iptal et
      const controller = uploadQueue.current.get(fileId)
      if (controller) {
        controller.abort()
        uploadQueue.current.delete(fileId)
      }
      
      // Preview URL'yi temizle
      if (fileToRemove.preview?.url) {
        URL.revokeObjectURL(fileToRemove.preview.url)
      }
      
      setFiles(prev => prev.filter(f => f.id !== fileId))
      setSelectedIds(prev => prev.filter(id => id !== fileId))
      
      onRemove?.(fileId)
    }, [files, onRemove])
    
    // Upload'ı duraklat/devam ettir
    const pauseResumeUpload = useCallback((fileId: string) => {
      const file = files.find(f => f.id === fileId)
      if (!file) return
      
      if (file.status === 'uploading') {
        const controller = uploadQueue.current.get(fileId)
        if (controller) {
          controller.abort()
          uploadQueue.current.delete(fileId)
        }
        
        setFiles(prev => prev.map(f => 
          f.id === fileId ? { ...f, status: 'paused' } : f
        ))
      } else if (file.status === 'paused' && resumable) {
        uploadFileChunked(file)
      }
    }, [files, resumable, uploadFileChunked])
    
    // Bulk operations
    const handleBulkSelect = useCallback((fileId: string, selected: boolean) => {
      setSelectedIds(prev => 
        selected 
          ? [...prev, fileId]
          : prev.filter(id => id !== fileId)
      )
    }, [])
    
    const handleSelectAll = useCallback(() => {
      const allIds = files.map(f => f.id)
      setSelectedIds(allIds)
      onBulkSelect?.(allIds)
    }, [files, onBulkSelect])
    
    const handleClearSelection = useCallback(() => {
      setSelectedIds([])
      onBulkSelect?.([])
    }, [onBulkSelect])
    
    const handleBulkRemove = useCallback(() => {
      selectedIds.forEach(id => removeFile(id))
      setSelectedIds([])
    }, [selectedIds, removeFile])
    
    const handleBulkDownload = useCallback(() => {
      // Bulk download implementation
      console.log('Bulk download:', selectedIds)
    }, [selectedIds])
    
    // Preview
    const handlePreview = useCallback((file: FileUploadItem) => {
      setPreviewFile(file)
      setIsPreviewOpen(true)
      onPreview?.(file)
    }, [onPreview])
    
    return (
      <div ref={ref} className={cn("w-full space-y-4", className)} {...props}>
        {/* Bulk Actions */}
        <AnimatePresence>
          {allowBulkOperations && selectedIds.length > 0 && (
            <BulkActions
              selectedIds={selectedIds}
              onClearSelection={handleClearSelection}
              onBulkRemove={handleBulkRemove}
              onBulkDownload={handleBulkDownload}
            />
          )}
        </AnimatePresence>
        
        {/* Upload Area */}
        <motion.div
          className={cn(
            fileUploadVariants({ 
              variant, 
              state: disabled ? "disabled" : isDragOver ? "dragover" : "idle" 
            })
          )}
          onDrop={handleDrop}
          onDragOver={handleDragOver}
          onDragLeave={handleDragLeave}
          onClick={() => !disabled && fileInputRef.current?.click()}
          animate={{
            scale: isDragOver ? 1.02 : 1
          }}
          transition={{ duration: 0.2 }}
        >
          <input
            ref={fileInputRef}
            type="file"
            accept={accept}
            multiple={multiple}
            disabled={disabled}
            onChange={handleFileSelect}
            className="absolute inset-0 w-full h-full opacity-0 cursor-pointer"
          />
          
          <div className="text-center space-y-4">
            <motion.div
              animate={{ 
                scale: isDragOver ? 1.1 : 1,
                rotate: isDragOver ? 5 : 0
              }}
              className="mx-auto h-12 w-12 text-muted-foreground"
            >
              <Upload className="h-full w-full" />
            </motion.div>
            
            <div>
              <h3 className="text-lg font-semibold">
                {isDragOver ? 'Drop files here' : 'Upload Files'}
              </h3>
              <p className="text-sm text-muted-foreground mt-1">
                Drag and drop files or click to select
              </p>
              <div className="flex items-center justify-center gap-4 mt-3 text-xs text-muted-foreground">
                <span>Max {maxFiles} files</span>
                <span>•</span>
                <span>{formatFileSize(maxSize)} per file</span>
                {resumable && (
                  <>
                    <span>•</span>
                    <span>Resumable</span>
                  </>
                )}
              </div>
            </div>
            
            <Button variant="outline" disabled={disabled} type="button">
              <Upload className="mr-2 h-4 w-4" />
              Select Files
            </Button>
          </div>
        </motion.div>
        
        {/* Error Message */}
        <AnimatePresence>
          {error && (
            <motion.div
              initial={{ opacity: 0, y: -10 }}
              animate={{ opacity: 1, y: 0 }}
              exit={{ opacity: 0, y: -10 }}
              className="flex items-center gap-2 p-3 bg-destructive/10 border border-destructive/20 rounded-lg"
            >
              <AlertCircle className="h-4 w-4 text-destructive flex-shrink-0" />
              <span className="text-sm text-destructive">{error}</span>
              <Button
                variant="ghost"
                size="sm"
                className="ml-auto h-6 w-6 p-0"
                onClick={() => setError(null)}
              >
                <X className="h-3 w-3" />
              </Button>
            </motion.div>
          )}
        </AnimatePresence>
        
        {/* File List */}
        <AnimatePresence>
          {files.length > 0 && (
            <motion.div
              initial={{ opacity: 0, height: 0 }}
              animate={{ opacity: 1, height: 'auto' }}
              exit={{ opacity: 0, height: 0 }}
              className="space-y-3"
            >
              {/* List Header */}
              <div className="flex items-center justify-between">
                <h4 className="text-sm font-medium">
                  Uploaded Files ({files.length})
                </h4>
                {allowBulkOperations && files.length > 1 && (
                  <Button 
                    variant="ghost" 
                    size="sm"
                    onClick={selectedIds.length === files.length ? handleClearSelection : handleSelectAll}
                  >
                    {selectedIds.length === files.length ? 'Clear Selection' : 'Select All'}
                  </Button>
                )}
              </div>
              
              {/* File Items */}
              <div className={cn(
                "space-y-2",
                variant === 'grid' && "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3 space-y-0"
              )}>
                <AnimatePresence>
                  {files.map(file => (
                    <FileUploadItem
                      key={file.id}
                      file={file}
                      variant={variant}
                      showPreview={showPreview}
                      showProgress={showProgress}
                      showMetadata={showMetadata}
                      allowBulkOperations={allowBulkOperations}
                      resumable={resumable}
                      selected={selectedIds.includes(file.id)}
                      onSelect={(selected) => handleBulkSelect(file.id, selected)}
                      onRemove={() => removeFile(file.id)}
                      onPauseResume={() => pauseResumeUpload(file.id)}
                      onPreview={() => handlePreview(file)}
                    />
                  ))}
                </AnimatePresence>
              </div>
            </motion.div>
          )}
        </AnimatePresence>
        
        {/* Preview Modal */}
        <FilePreviewModal
          file={previewFile}
          isOpen={isPreviewOpen}
          onClose={() => setIsPreviewOpen(false)}
        />
      </div>
    )
  }
)

// Tekil dosya bileşeni
const FileUploadItem = ({ 
  file, 
  variant = 'default',
  showPreview = true,
  showProgress = true,
  showMetadata = true,
  allowBulkOperations = true,
  resumable = true,
  selected = false,
  onSelect,
  onRemove,
  onPauseResume,
  onPreview
}: {
  file: FileUploadItem
  variant?: 'default' | 'compact' | 'grid'
  showPreview?: boolean
  showProgress?: boolean
  showMetadata?: boolean
  allowBulkOperations?: boolean
  resumable?: boolean
  selected?: boolean
  onSelect?: (selected: boolean) => void
  onRemove?: () => void
  onPauseResume?: () => void
  onPreview?: () => void
}) => {
  const { toast } = useToast()
  const canPauseResume = resumable && ['uploading', 'paused'].includes(file.status)
  const canPreview = showPreview && file.preview && ['image', 'video', 'audio'].includes(file.preview.type)
  
  return (
    <motion.div
      layout
      initial={{ opacity: 0, y: 10 }}
      animate={{ opacity: 1, y: 0 }}
      exit={{ opacity: 0, y: -10, scale: 0.95 }}
      className={cn(
        "group relative overflow-hidden rounded-lg border bg-card transition-all",
        selected && "ring-2 ring-primary bg-primary/5",
        variant === 'compact' && "p-3",
        variant === 'default' && "p-4",
        variant === 'grid' && "p-4"
      )}
    >
      {/* Selection Checkbox for grid variant only */}
      {allowBulkOperations && variant === 'grid' && (
        <div className="absolute top-3 left-3 z-10">
          <input
            type="checkbox"
            checked={selected}
            onChange={(e) => onSelect?.(e.target.checked)}
            className="rounded border-muted-foreground/25 h-4 w-4"
          />
        </div>
      )}
      
      {/* Checkbox for non-grid variants */}
      {allowBulkOperations && variant !== 'grid' && (
        <input
          type="checkbox"
          checked={selected}
          onChange={(e) => onSelect?.(e.target.checked)}
          className="rounded border-muted-foreground/25 h-4 w-4 mt-1 mr-3 float-left"
        />
      )}
      
      {/* Preview/Thumbnail */}
      {showPreview && file.preview && (
        <div className={cn(
          "relative overflow-hidden rounded bg-muted/20",
          variant === 'grid' ? "aspect-video mb-3" : 
          variant === 'compact' ? "w-10 h-10 float-left mr-2" : 
          "w-12 h-12 float-left mr-3"
        )}>
          {file.preview.type === 'image' && file.preview.thumbnail && (
            <img
              src={file.preview.thumbnail}
              alt={file.file.name}
              className="w-full h-full object-cover"
            />
          )}
          
          {file.preview.type === 'video' && file.preview.thumbnail && (
            <div className="relative w-full h-full">
              <img
                src={file.preview.thumbnail}
                alt={file.file.name}
                className="w-full h-full object-cover"
              />
              <div className="absolute inset-0 flex items-center justify-center bg-black/20">
                <Play className="h-6 w-6 text-white" />
              </div>
            </div>
          )}
          
          {!file.preview.thumbnail && (
            <div className="w-full h-full flex items-center justify-center">
              {getFileIcon(file.file.type, variant === 'grid' ? 'lg' : 'md')}
            </div>
          )}
          
          {canPreview && (
            <Button
              variant="secondary"
              size="sm"
              className="absolute top-1 right-1 h-6 w-6 p-0 opacity-0 group-hover:opacity-100 transition-opacity"
              onClick={onPreview}
            >
              <Eye className="h-3 w-3" />
            </Button>
          )}
        </div>
      )}
      
        {/* File Info */}
        <div className={cn(
          "flex-1 min-w-0",
          variant === 'grid' ? "text-center w-full" : "overflow-hidden"
        )}>
          <div className="flex items-start justify-between gap-3">
            <div className="min-w-0 flex-1">
              <h5 className={cn(
                "font-medium truncate",
                variant === 'compact' ? "text-sm" : "text-base"
              )}>
                {file.file.name}
              </h5>
            
              {showMetadata && (
                <div className={cn(
                  "flex items-center gap-2 mt-1 text-muted-foreground",
                  variant === 'compact' ? "text-xs" : "text-sm",
                  variant === 'grid' && "justify-center"
                )}>
                <span>{formatFileSize(file.file.size)}</span>
                {file.preview?.dimensions && (
                  <>
                    <span>•</span>
                    <span>{file.preview.dimensions.width} × {file.preview.dimensions.height}</span>
                  </>
                )}
                {file.preview?.duration && (
                  <>
                    <span>•</span>
                    <span>{formatTime(file.preview.duration)}</span>
                  </>
                )}
              </div>
            )}
          </div>
          
          {/* Status Badge */}
          <Badge 
            variant={
              file.status === 'success' ? 'success' :
              file.status === 'error' ? 'destructive' :
              file.status === 'paused' ? 'secondary' : 'secondary'
            }
            size={variant === 'compact' ? 'sm' : 'md'}
            className={cn(
              "flex-shrink-0 whitespace-nowrap min-w-fit",
              file.status === 'success' && "bg-green-500 hover:bg-green-600 text-white border-transparent"
            )}
          >
            {file.status === 'uploading' && <Loader2 className={cn("h-3 w-3 animate-spin flex-shrink-0", variant !== 'compact' && "mr-1")} />}
            {file.status === 'success' && <CheckCircle2 className={cn("h-3 w-3 flex-shrink-0", variant !== 'compact' && "mr-1")} />}
            {file.status === 'error' && <AlertCircle className={cn("h-3 w-3 flex-shrink-0", variant !== 'compact' && "mr-1")} />}
            {file.status === 'paused' && <Pause className={cn("h-3 w-3 flex-shrink-0", variant !== 'compact' && "mr-1")} />}
            {variant !== 'compact' && (
              file.status === 'pending' ? 'Pending' :
              file.status === 'uploading' ? 'Uploading' :
              file.status === 'paused' ? 'Paused' :
              file.status === 'success' ? 'Done' :
              file.status === 'error' ? 'Error' : 'Cancelled'
            )}
          </Badge>
        </div>
        
        {/* Progress */}
        {showProgress && file.status === 'uploading' && (
          <div className="mt-3 space-y-1">
            <div className="flex items-center justify-between text-xs text-muted-foreground">
              <span>{file.progress}%</span>
              {file.speed && (
                <span>{formatFileSize(file.speed)}/s</span>
              )}
              {file.estimatedTime && file.estimatedTime > 0 && (
                <span>{formatTime(file.estimatedTime)} remaining</span>
              )}
            </div>
            <Progress value={file.progress} className="h-1" />
          </div>
        )}
        
        {/* Error Message */}
        {file.status === 'error' && file.error && (
          <p className="mt-2 text-xs text-destructive">{file.error}</p>
        )}
        
        {/* Actions */}
        <div className={cn(
          "flex items-center gap-1 mt-3 clear-both",
          variant === 'grid' && "justify-center"
        )}>
          {canPauseResume && (
            <Button
              variant="ghost"
              size="sm"
              onClick={onPauseResume}
              className="h-7 px-2"
            >
              {file.status === 'uploading' ? (
                <Pause className="h-3 w-3" />
              ) : (
                <Play className="h-3 w-3" />
              )}
            </Button>
          )}
          
          {file.status === 'error' && resumable && (
            <Button
              variant="ghost"
              size="sm"
              onClick={onPauseResume}
              className="h-7 px-2"
            >
              <RotateCcw className="h-3 w-3" />
            </Button>
          )}
          
          {file.status === 'success' && (
            <Button
              variant="ghost"
              size="sm"
              className="h-7 px-2"
              onClick={() => {
                // Download file
                const link = document.createElement('a')
                link.href = file.preview?.url || URL.createObjectURL(file.file)
                link.download = file.file.name
                link.click()
              }}
            >
              <Download className="h-3 w-3" />
            </Button>
          )}
          
          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <Button variant="ghost" size="sm" className="h-7 w-7 p-0">
                <MoreHorizontal className="h-3 w-3" />
              </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end">
              {canPreview && (
                <DropdownMenuItem onClick={onPreview}>
                  <Eye className="mr-2 h-4 w-4" />
                  Preview
                </DropdownMenuItem>
              )}
              <DropdownMenuItem onClick={async () => {
                try {
                  const url = file.result?.url || file.preview?.url || URL.createObjectURL(file.file)
                  await navigator.clipboard.writeText(url)
                  toast({
                    title: "Link copied",
                    description: "File link has been copied to clipboard",
                  })
                } catch (err) {
                  console.error('Failed to copy link:', err)
                  toast({
                    title: "Failed to copy",
                    description: "Could not copy link to clipboard",
                    variant: "destructive"
                  })
                }
              }}>
                <Copy className="mr-2 h-4 w-4" />
                Copy Link
              </DropdownMenuItem>
              {navigator.share && (
                <DropdownMenuItem onClick={async () => {
                  try {
                    await navigator.share({
                      title: file.file.name,
                      text: `Check out this file: ${file.file.name}`,
                      url: file.result?.url || file.preview?.url || window.location.href,
                      files: [file.file]
                    })
                  } catch (err) {
                    console.log('Share cancelled or failed:', err)
                  }
                }}>
                  <Share className="mr-2 h-4 w-4" />
                  Share
                </DropdownMenuItem>
              )}
              <DropdownMenuItem onClick={onRemove} className="text-destructive">
                <Trash2 className="mr-2 h-4 w-4" />
                Delete
              </DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
        </div>
      </div>
    </motion.div>
  )
}

MoonUIFileUploadPro.displayName = "MoonUIFileUploadPro"

export default MoonUIFileUploadPro