import { useRef, useState, useCallback } from 'react';
import { FiUpload, FiX } from 'react-icons/fi';
import { FilePreview, FileMetadata } from './file-preview';

export interface FileUploadProps {
	onFilesChange: (files: File[]) => void;
	acceptedTypes?: string;
	maxFiles?: number;
	maxSize?: number; // in bytes
	disabled?: boolean;
}

export function FileUpload({
	onFilesChange,
	acceptedTypes = '*/*',
	maxFiles = 10,
	maxSize = 50 * 1024 * 1024, // 50MB default
	disabled = false,
}: FileUploadProps) {
	const [files, setFiles] = useState<File[]>([]);
	const [isDragging, setIsDragging] = useState(false);
	const fileInputRef = useRef<HTMLInputElement>(null);

	const validateFile = (file: File): string | null => {
		if (file.size > maxSize) {
			return `File ${file.name} exceeds maximum size of ${(maxSize / (1024 * 1024)).toFixed(0)}MB`;
		}
		return null;
	};

	const handleFiles = useCallback(
		(fileList: FileList | null) => {
			if (!fileList) return;

			const newFiles: File[] = [];
			const errors: string[] = [];

			Array.from(fileList).forEach(file => {
				const error = validateFile(file);
				if (error) {
					errors.push(error);
				} else if (files.length + newFiles.length < maxFiles) {
					newFiles.push(file);
				} else {
					errors.push(`Maximum ${maxFiles} files allowed`);
				}
			});

			if (errors.length > 0) {
				alert(errors.join('\n'));
			}

			if (newFiles.length > 0) {
				const updatedFiles = [...files, ...newFiles];
				setFiles(updatedFiles);
				onFilesChange(updatedFiles);
			}
		},
		[files, maxFiles, maxSize, onFilesChange],
	);

	const handleFileInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
		handleFiles(e.target.files);
		if (fileInputRef.current) {
			fileInputRef.current.value = '';
		}
	};

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

	const handleDragLeave = (e: React.DragEvent) => {
		e.preventDefault();
		e.stopPropagation();
		setIsDragging(false);
	};

	const handleDrop = (e: React.DragEvent) => {
		e.preventDefault();
		e.stopPropagation();
		setIsDragging(false);

		if (disabled) return;

		handleFiles(e.dataTransfer.files);
	};

	const removeFile = (index: number) => {
		const updatedFiles = files.filter((_, i) => i !== index);
		setFiles(updatedFiles);
		onFilesChange(updatedFiles);
	};

	const clearFiles = () => {
		setFiles([]);
		onFilesChange([]);
	};

	return (
		<div className='space-y-2'>
			<div
				onDragOver={handleDragOver}
				onDragLeave={handleDragLeave}
				onDrop={handleDrop}
				className={`
					border-2 border-dashed rounded-lg p-4 text-center transition-colors
					${isDragging ? 'border-sidebar-bg bg-sidebar-bg/10' : 'border-border'}
					${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer hover:border-sidebar-bg/50'}
				`}
				onClick={() => !disabled && fileInputRef.current?.click()}
			>
				<input
					ref={fileInputRef}
					type='file'
					accept={acceptedTypes}
					multiple
					onChange={handleFileInputChange}
					className='hidden'
					disabled={disabled}
				/>
				<FiUpload className='w-6 h-6 mx-auto mb-2 text-text-secondary' />
				<p className='text-sm text-text-primary'>Drag and drop files here, or click to select</p>
				<p className='text-xs text-text-secondary mt-1'>
					Max {maxFiles} files, {(maxSize / (1024 * 1024)).toFixed(0)}MB per file
				</p>
			</div>

			{files.length > 0 && (
				<div className='space-y-2'>
					<div className='flex items-center justify-between'>
						<p className='text-sm text-text-secondary'>
							{files.length} file{files.length > 1 ? 's' : ''} selected
						</p>
						<button
							onClick={clearFiles}
							className='text-xs text-text-secondary hover:text-text-primary transition-colors flex items-center gap-1'
						>
							<FiX className='w-3 h-3' />
							Clear all
						</button>
					</div>
					<div className='grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-2 max-h-48 overflow-y-auto'>
						{files.map((file, index) => {
							const fileMetadata: FileMetadata = {
								type: file.type.startsWith('audio/')
									? 'audio'
									: file.type.startsWith('image/')
									? 'image'
									: file.type.includes('pdf') ||
									  file.type.includes('word') ||
									  file.type.includes('text')
									? 'document'
									: file.type.includes('spreadsheet') ||
									  file.type.includes('excel') ||
									  file.name.endsWith('.csv')
									? 'spreadsheet'
									: 'other',
								mimeType: file.type,
								size: file.size,
								originalName: file.name,
								url: URL.createObjectURL(file),
							};
							return (
								<FilePreview
									key={index}
									file={fileMetadata}
									onRemove={() => removeFile(index)}
									showRemove={true}
									compact={true}
								/>
							);
						})}
					</div>
				</div>
			)}
		</div>
	);
}
