import React, { useState, useRef } from 'react';
import { Upload, File, X, CheckCircle2, AlertCircle } from 'lucide-react';
import { Box } from '@/ui/Box';
import { Text } from '@/ui/Text';
import { Icon } from '@/ui/Icon';
import { Button } from '@/ui/Button';

export interface UploadDropzoneProps {
  onFilesSelected: (files: File[]) => void;
  accept?: string;
  multiple?: boolean;
  maxSize?: number; // in bytes
  isLoading?: boolean;
  error?: string;
}

export function UploadDropzone({
  onFilesSelected,
  accept,
  multiple = false,
  maxSize,
  isLoading,
  error,
}: UploadDropzoneProps) {
  const [isDragging, setIsDragging] = useState(false);
  const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
  const fileInputRef = useRef<HTMLInputElement>(null);

  const handleDragOver = (e: React.DragEvent) => {
    e.preventDefault();
    setIsDragging(true);
  };

  const handleDragLeave = () => {
    setIsDragging(false);
  };

  const handleDrop = (e: React.DragEvent) => {
    e.preventDefault();
    setIsDragging(false);
    const files = Array.from(e.dataTransfer.files);
    validateAndSelectFiles(files);
  };

  const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files) {
      const files = Array.from(e.target.files);
      validateAndSelectFiles(files);
    }
  };

  const validateAndSelectFiles = (files: File[]) => {
    let filteredFiles = files;
    
    if (accept) {
      const acceptedTypes = accept.split(',').map(t => t.trim());
      filteredFiles = filteredFiles.filter(file => {
        return acceptedTypes.some(type => {
          if (type.startsWith('.')) {
            return file.name.endsWith(type);
          }
          if (type.endsWith('/*')) {
            return file.type.startsWith(type.replace('/*', ''));
          }
          return file.type === type;
        });
      });
    }

    if (maxSize) {
      filteredFiles = filteredFiles.filter(file => file.size <= maxSize);
    }

    if (!multiple) {
      filteredFiles = filteredFiles.slice(0, 1);
    }

    setSelectedFiles(filteredFiles);
    onFilesSelected(filteredFiles);
  };

  const removeFile = (index: number) => {
    const newFiles = [...selectedFiles];
    newFiles.splice(index, 1);
    setSelectedFiles(newFiles);
    onFilesSelected(newFiles);
  };

  return (
    <Box w="full">
      <Box
        onDragOver={handleDragOver}
        onDragLeave={handleDragLeave}
        onDrop={handleDrop}
        onClick={() => fileInputRef.current?.click()}
        display="flex"
        flexDirection="col"
        alignItems="center"
        justifyContent="center"
        p={8}
        border
        borderStyle="dashed"
        borderColor={isDragging ? 'border-blue-500' : error ? 'border-amber-500' : 'border-charcoal-outline'}
        bg={isDragging ? 'bg-blue-500/5' : 'bg-charcoal-outline/10'}
        rounded="xl"
        cursor="pointer"
        transition
        hoverBg="bg-charcoal-outline/20"
      >
        <Box as="input"
          type="file"
          ref={fileInputRef}
          onChange={handleFileSelect}
          accept={accept}
          multiple={multiple}
          display="none"
        />
        
        <Icon 
          icon={isLoading ? Upload : (selectedFiles.length > 0 ? CheckCircle2 : Upload)} 
          size={10} 
          color={isDragging ? 'text-blue-500' : error ? 'text-amber-500' : 'text-gray-500'}
          animate={isLoading ? 'pulse' : 'none'}
          mb={4}
        />
        
        <Text weight="semibold" size="lg" mb={1}>
          {isDragging ? 'Drop files here' : 'Click or drag to upload'}
        </Text>
        
        <Text size="sm" color="text-gray-500" align="center">
          {accept ? `Accepted formats: ${accept}` : 'All file types accepted'}
          {maxSize && ` (Max ${Math.round(maxSize / 1024 / 1024)}MB)`}
        </Text>

        {error && (
          <Box display="flex" alignItems="center" gap={2} mt={4} color="text-amber-500">
            <Icon icon={AlertCircle} size={4} />
            <Text size="sm" weight="medium">{error}</Text>
          </Box>
        )}
      </Box>

      {selectedFiles.length > 0 && (
        <Box mt={4} display="flex" flexDirection="col" gap={2}>
          {selectedFiles.map((file, index) => (
            <Box 
              key={`${file.name}-${index}`}
              display="flex" 
              alignItems="center" 
              justifyContent="between"
              p={3}
              bg="bg-charcoal-outline/20"
              rounded="lg"
              border
              borderColor="border-charcoal-outline/30"
            >
              <Box display="flex" alignItems="center" gap={3}>
                <Icon icon={File} size={5} color="text-gray-400" />
                <Box>
                  <Text block size="sm" weight="medium" truncate maxWidth="200px">
                    {file.name}
                  </Text>
                  <Text block size="xs" color="text-gray-500">
                    {Math.round(file.size / 1024)} KB
                  </Text>
                </Box>
              </Box>
              <Button 
                variant="ghost" 
                size="sm" 
                onClick={(e) => {
                  e.stopPropagation();
                  removeFile(index);
                }}
                p={1}
                h="auto"
              >
                <Icon icon={X} size={4} />
              </Button>
            </Box>
          ))}
        </Box>
      )}
    </Box>
  );
}
