'use client'

import { useCallback, useState } from 'react'
import { useDropzone } from 'react-dropzone'
import { motion, AnimatePresence } from 'framer-motion'
import { Upload, Image, Video, FileText, X, AlertCircle } from 'lucide-react'
import { cn } from '@/lib/utils'
import { Button } from './ui/button'
import toast from 'react-hot-toast'

interface UploadZoneProps {
  onUpload?: (files: File[]) => void
  onDragChange?: (isDragging: boolean) => void
  accept?: Record<string, string[]>
  maxSize?: number
  maxFiles?: number
  className?: string
}

export function UploadZone({
  onUpload,
  onDragChange,
  accept = {
    'image/*': ['.png', '.jpg', '.jpeg', '.gif', '.webp'],
    'video/*': ['.mp4', '.webm', '.mov'],
  },
  maxSize = 50 * 1024 * 1024, // 50MB
  maxFiles = 10,
  className,
}: UploadZoneProps) {
  const [files, setFiles] = useState<File[]>([])
  const [isProcessing, setIsProcessing] = useState(false)

  const onDrop = useCallback(
    async (acceptedFiles: File[], rejectedFiles: any[]) => {
      if (rejectedFiles.length > 0) {
        const errors = rejectedFiles.map((file) => {
          if (file.errors[0]?.code === 'file-too-large') {
            return `${file.file.name} is too large (max ${maxSize / 1024 / 1024}MB)`
          }
          return `${file.file.name} is not supported`
        })
        toast.error(errors.join(', '))
        return
      }

      setFiles(acceptedFiles)
      
      if (onUpload) {
        setIsProcessing(true)
        try {
          await onUpload(acceptedFiles)
        } catch (error) {
          toast.error('Failed to upload files')
        } finally {
          setIsProcessing(false)
        }
      }
    },
    [onUpload, maxSize]
  )

  const { getRootProps, getInputProps, isDragActive, isDragReject } = useDropzone({
    onDrop,
    accept,
    maxSize,
    maxFiles,
    onDragEnter: () => onDragChange?.(true),
    onDragLeave: () => onDragChange?.(false),
    onDropAccepted: () => onDragChange?.(false),
    onDropRejected: () => onDragChange?.(false),
  })

  const getFileIcon = (file: File) => {
    if (file.type.startsWith('image/')) return <Image className="w-4 h-4" />
    if (file.type.startsWith('video/')) return <Video className="w-4 h-4" />
    return <FileText className="w-4 h-4" />
  }

  const removeFile = (index: number) => {
    setFiles((prev) => prev.filter((_, i) => i !== index))
  }

  return (
    <div className={className}>
      <div
        {...getRootProps()}
        className={cn(
          'relative rounded-xl border-2 border-dashed transition-all duration-200 cursor-pointer',
          'bg-gray-800/50 hover:bg-gray-800/70',
          isDragActive && !isDragReject && 'border-purple-500 bg-purple-500/10',
          isDragReject && 'border-red-500 bg-red-500/10',
          !isDragActive && !isDragReject && 'border-gray-700',
          isProcessing && 'pointer-events-none opacity-50'
        )}
      >
        <input {...getInputProps()} />
        
        <div className="p-12 text-center">
          <AnimatePresence mode="wait">
            {isDragReject ? (
              <motion.div
                key="reject"
                initial={{ opacity: 0, scale: 0.9 }}
                animate={{ opacity: 1, scale: 1 }}
                exit={{ opacity: 0, scale: 0.9 }}
                className="text-red-500"
              >
                <AlertCircle className="w-12 h-12 mx-auto mb-4" />
                <p className="text-lg font-medium">File not supported</p>
                <p className="text-sm mt-2 text-red-400">
                  Please upload image or video files only
                </p>
              </motion.div>
            ) : isDragActive ? (
              <motion.div
                key="active"
                initial={{ opacity: 0, scale: 0.9 }}
                animate={{ opacity: 1, scale: 1 }}
                exit={{ opacity: 0, scale: 0.9 }}
                className="text-purple-400"
              >
                <Upload className="w-12 h-12 mx-auto mb-4 animate-bounce" />
                <p className="text-lg font-medium">Drop files here</p>
                <p className="text-sm mt-2 text-purple-300">
                  Release to upload
                </p>
              </motion.div>
            ) : (
              <motion.div
                key="default"
                initial={{ opacity: 0, scale: 0.9 }}
                animate={{ opacity: 1, scale: 1 }}
                exit={{ opacity: 0, scale: 0.9 }}
              >
                <Upload className="w-12 h-12 mx-auto mb-4 text-gray-500" />
                <p className="text-lg font-medium text-white mb-2">
                  Drop files here or click to browse
                </p>
                <p className="text-sm text-gray-400">
                  Support for PNG, JPG, GIF, WebP, MP4, MOV
                </p>
                <p className="text-xs text-gray-500 mt-2">
                  Max {maxSize / 1024 / 1024}MB per file • Up to {maxFiles} files
                </p>
                
                <Button className="mt-6" variant="outline">
                  Select Files
                </Button>
              </motion.div>
            )}
          </AnimatePresence>
        </div>

        {isProcessing && (
          <div className="absolute inset-0 bg-gray-900/80 rounded-xl flex items-center justify-center">
            <div className="text-center">
              <div className="inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-purple-500 mb-4"></div>
              <p className="text-white">Processing...</p>
            </div>
          </div>
        )}
      </div>

      {/* File List */}
      {files.length > 0 && (
        <div className="mt-4 space-y-2">
          <p className="text-sm font-medium text-gray-300 mb-2">
            Selected files ({files.length})
          </p>
          {files.map((file, index) => (
            <motion.div
              key={`${file.name}-${index}`}
              initial={{ opacity: 0, x: -20 }}
              animate={{ opacity: 1, x: 0 }}
              transition={{ delay: index * 0.05 }}
              className="flex items-center gap-3 p-3 bg-gray-800 rounded-lg"
            >
              {getFileIcon(file)}
              <div className="flex-1 min-w-0">
                <p className="text-sm font-medium text-white truncate">
                  {file.name}
                </p>
                <p className="text-xs text-gray-400">
                  {(file.size / 1024 / 1024).toFixed(2)} MB
                </p>
              </div>
              <Button
                size="sm"
                variant="ghost"
                onClick={() => removeFile(index)}
                className="text-gray-400 hover:text-red-400"
              >
                <X className="w-4 h-4" />
              </Button>
            </motion.div>
          ))}
        </div>
      )}
    </div>
  )
}