import React, { useState, useRef, useCallback, useEffect } from 'react';
import { Upload, X, Image, File, AlertCircle, CheckCircle } from 'lucide-react';
import { Button } from './Button';

export interface UploadedFile {
    id: string;
    name: string;
    size: number;
    type: string;
    url?: string;
    preview?: string;
    progress: number;
    status: 'uploading' | 'completed' | 'error';
    error?: string;
}

interface FileUploaderProps {
    onUpload: (file: File) => Promise<{ id: string; url: string; mimeType?: string }>;
    onRemove?: (fileId: string) => void;
    acceptedTypes?: string[];
    maxFileSize?: number;
    maxFiles?: number;
    label?: string;
    description?: string;
    error?: string;
    disabled?: boolean;
    className?: string;
    mode?: 'single' | 'multi';
    onUploadStart?: () => void;
    onUploadComplete?: () => void;
    initialFiles?: Array<Partial<UploadedFile> & { id: string; url?: string }>;
}

export const FileUploader: React.FC<FileUploaderProps> = ({
    onUpload,
    onRemove,
    acceptedTypes = ['image/*', 'video/*'],
    maxFileSize = 10 * 1024 * 1024,
    maxFiles = 10,
    label = "فایل‌ها",
    description = "تصاویر و ویدیوها را اینجا بکشید یا کلیک کنید",
    error,
    disabled = false,
    className = "",
    mode = 'multi',
    onUploadStart,
    onUploadComplete,
    initialFiles = [],
}) => {
    const [files, setFiles] = useState<UploadedFile[]>([]);
    const [isDragOver, setIsDragOver] = useState(false);
    const fileInputRef = useRef<HTMLInputElement>(null);

    const isImage = (type: string) => type.startsWith('image/');

    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];
    };

    useEffect(() => {
        if (initialFiles && initialFiles.length > 0) {
            const normalized: UploadedFile[] = initialFiles.map((f) => ({
                id: f.id,
                name: f.name || (f.url ? f.url.split('/').pop() || 'file' : 'file'),
                size: typeof f.size === 'number' ? f.size : 0,
                type: f.type || 'image/*',
                url: f.url,
                preview: f.preview,
                progress: 100,
                status: 'completed',
            }));
            setFiles(mode === 'single' ? [normalized[0]] : normalized);
        }
    }, [initialFiles, mode]);

    const validateFile = (file: File) => {
        if (maxFileSize && file.size > maxFileSize) {
            return `حجم فایل نباید بیشتر از ${formatFileSize(maxFileSize)} باشد`;
        }

        if (acceptedTypes.length > 0) {
            const isAccepted = acceptedTypes.some(type => {
                if (type === 'image/*') return file.type.startsWith('image/');
                if (type === 'video/*') return file.type.startsWith('video/');
                return file.type === type;
            });
            if (!isAccepted) {
                return 'نوع فایل پشتیبانی نمی‌شود';
            }
        }

        if (maxFiles && files.length >= maxFiles) {
            return `حداکثر ${maxFiles} فایل مجاز است`;
        }

        return null;
    };

    const createFilePreview = (file: File) => {
        return new Promise<string>((resolve) => {
            if (isImage(file.type)) {
                const reader = new FileReader();
                reader.onload = (e) => resolve(e.target?.result as string);
                reader.readAsDataURL(file);
            } else {
                resolve('');
            }
        });
    };

    const handleFileUpload = useCallback(async (file: File) => {
        const validationError = validateFile(file);
        if (validationError) {
            const errorFile: UploadedFile = {
                id: Math.random().toString(36).substr(2, 9),
                name: file.name,
                size: file.size,
                type: file.type,
                progress: 0,
                status: 'error',
                error: validationError,
            };
            setFiles(prev => mode === 'single' ? [errorFile] : [...prev, errorFile]);
            return;
        }

        onUploadStart?.();

        const fileId = Math.random().toString(36).substr(2, 9);
        const preview = await createFilePreview(file);

        const newFile: UploadedFile = {
            id: fileId,
            name: file.name,
            size: file.size,
            type: file.type,
            preview,
            progress: 0,
            status: 'uploading',
        };

        setFiles(prev => mode === 'single' ? [newFile] : [...prev, newFile]);

        try {
            const progressInterval = setInterval(() => {
                setFiles(prev => prev.map(f =>
                    f.id === fileId && f.progress < 90
                        ? { ...f, progress: f.progress + 10 }
                        : f
                ));
            }, 200);

            const result = await onUpload(file);

            clearInterval(progressInterval);

            setFiles(prev => prev.map(f =>
                f.id === fileId
                    ? { ...f, progress: 100, status: 'completed', url: result.url, id: result.id }
                    : f
            ));

            onUploadComplete?.();
        } catch (error: any) {
            setFiles(prev => prev.map(f =>
                f.id === fileId
                    ? { ...f, status: 'error', error: error.message || 'خطا در آپلود فایل' }
                    : f
            ));
            onUploadComplete?.();
        }
    }, [onUpload, maxFiles, maxFileSize, acceptedTypes, mode, onUploadStart, onUploadComplete]);

    const handleFileSelect = useCallback((selectedFiles: FileList) => {
        Array.from(selectedFiles).forEach(file => {
            handleFileUpload(file);
        });
    }, [handleFileUpload]);

    const handleDrop = useCallback((e: React.DragEvent) => {
        e.preventDefault();
        setIsDragOver(false);
        if (disabled) return;

        const droppedFiles = e.dataTransfer.files;
        handleFileSelect(droppedFiles);
    }, [disabled, handleFileSelect]);

    const handleDragOver = useCallback((e: React.DragEvent) => {
        e.preventDefault();
        if (!disabled) setIsDragOver(true);
    }, [disabled]);

    const handleDragLeave = useCallback((e: React.DragEvent) => {
        e.preventDefault();
        setIsDragOver(false);
    }, []);

    const handleClick = () => {
        if (!disabled) fileInputRef.current?.click();
    };

    const handleRemove = (fileId: string) => {
        setFiles(prev => prev.filter(f => f.id !== fileId));
        onRemove?.(fileId);
    };

    const hasUploadedFiles = files.some(f => f.status === 'completed');
    const showUploadArea = mode === 'multi' || (mode === 'single' && !hasUploadedFiles);

    return (
        <div className={`space-y-4 ${className}`}>
            {label && (
                <label className="block text-sm font-medium text-gray-700 dark:text-gray-300">
                    {label}
                </label>
            )}

            {showUploadArea && (
                <div
                    className={`
              relative border-2 border-dashed rounded-lg p-6 transition-colors cursor-pointer
              ${isDragOver ? 'border-primary-400 bg-primary-50 dark:bg-primary-900/20' : 'border-gray-300 dark:border-gray-600'}
              ${disabled ? 'opacity-50 cursor-not-allowed' : 'hover:border-primary-400 hover:bg-gray-50 dark:hover:bg-gray-700'}
              ${error ? 'border-red-300 bg-red-50 dark:bg-red-900/20' : ''}
            `}
                    onDrop={handleDrop}
                    onDragOver={handleDragOver}
                    onDragLeave={handleDragLeave}
                    onClick={handleClick}
                >
                    <input
                        ref={fileInputRef}
                        type="file"
                        multiple={mode === 'multi'}
                        accept={acceptedTypes.join(',')}
                        className="hidden"
                        onChange={(e) => e.target.files && handleFileSelect(e.target.files)}
                        disabled={disabled}
                    />

                    <div className="text-center">
                        <Upload className="mx-auto h-12 w-12 text-gray-400" />
                        <div className="mt-4">
                            <p className="text-sm text-gray-600 dark:text-gray-400">
                                {description}
                            </p>
                            <p className="text-xs text-gray-500 dark:text-gray-500 mt-1">
                                حداکثر {formatFileSize(maxFileSize)} • {acceptedTypes.join(', ')}
                            </p>
                        </div>
                    </div>
                </div>
            )}

            {error && (
                <p className="text-sm text-red-600 dark:text-red-400 flex items-center gap-1">
                    <AlertCircle className="h-4 w-4" />
                    {error}
                </p>
            )}

            {files.length > 0 && (
                <div className="space-y-3">
                    <h4 className="text-sm font-medium text-gray-700 dark:text-gray-300">
                        فایل‌های آپلود شده ({files.length})
                    </h4>
                    <div className="space-y-2">
                        {files.map((file) => (
                            <div
                                key={file.id}
                                className="flex items-center gap-3 p-3 bg-gray-50 dark:bg-gray-700 rounded-lg"
                            >
                                <div className="flex-shrink-0">
                                    {(file.preview || file.url) ? (
                                        <img
                                            src={(file.preview || file.url) as string}
                                            alt={file.name}
                                            className="w-10 h-10 object-cover rounded"
                                        />
                                    ) : (
                                        <div className="w-10 h-10 bg-gray-200 dark:bg-gray-600 rounded flex items-center justify-center">
                                            {isImage(file.type) ? (
                                                <Image className="h-5 w-5 text-gray-500" />
                                            ) : (
                                                <File className="h-5 w-5 text-gray-500" />
                                            )}
                                        </div>
                                    )}
                                </div>

                                <div className="flex-1 min-w-0">
                                    <p className="text-sm font-medium text-gray-900 dark:text-gray-100 truncate">
                                        {file.name}
                                    </p>
                                    <p className="text-xs text-gray-500 dark:text-gray-400">
                                        {formatFileSize(file.size)}
                                    </p>

                                    {file.status === 'uploading' && (
                                        <div className="mt-1">
                                            <div className="w-full bg-gray-200 dark:bg-gray-600 rounded-full h-1.5">
                                                <div
                                                    className="bg-primary-600 h-1.5 rounded-full transition-all duration-300"
                                                    style={{ width: `${file.progress}%` }}
                                                />
                                            </div>
                                            <p className="text-xs text-gray-500 mt-1">{file.progress}%</p>
                                        </div>
                                    )}

                                    {file.status === 'error' && file.error && (
                                        <p className="text-xs text-red-600 dark:text-red-400 mt-1 flex items-center gap-1">
                                            <AlertCircle className="h-3 w-3" />
                                            {file.error}
                                        </p>
                                    )}
                                </div>

                                <div className="flex items-center gap-2">
                                    {file.status === 'completed' && (
                                        <CheckCircle className="h-5 w-5 text-green-500" />
                                    )}
                                    {file.status === 'error' && (
                                        <AlertCircle className="h-5 w-5 text-red-500" />
                                    )}

                                    <Button
                                        variant="secondary"
                                        size="sm"
                                        onClick={(e) => {
                                            e?.stopPropagation();
                                            handleRemove(file.id);
                                        }}
                                        className="p-1 h-8 w-8"
                                    >
                                        <X className="h-4 w-4" />
                                    </Button>
                                </div>
                            </div>
                        ))}
                    </div>
                </div>
            )}
        </div>
    );
}; 