import { Label } from '@/components/ui/label';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
import Image from 'next/image';
import { useCallback, useState } from 'react';
import { ImageIcon, Loader2, X } from 'lucide-react';

interface FileInputProps {
  label?: string;
  name: string;
  accept?: string;
  required?: boolean;
  description?: string;
  error?: string;
  defaultValue?: string;
  isLoading?: boolean;
  onFileSelect?: (file: File | null) => void;
}

export function FileInput({
  label,
  name,
  accept,
  required,
  description,
  error,
  defaultValue,
  isLoading,
  onFileSelect,
}: FileInputProps) {
  const [preview, setPreview] = useState<string>(defaultValue || '');
  const [isDragging, setIsDragging] = useState(false);
  const inputId = `input-${name}`;
  const descriptionId = `description-${name}`;
  const errorId = `error-${name}`;

  const handleFileSelect = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const file = e.target.files?.[0];
      if (file) {
        const reader = new FileReader();
        reader.onloadend = () => {
          setPreview(reader.result as string);
        };
        reader.readAsDataURL(file);
        onFileSelect?.(file);
      }
    },
    [onFileSelect]
  );

  const handleRemove = useCallback(() => {
    setPreview('');
    onFileSelect?.(null);
  }, [onFileSelect]);

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

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

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

      const file = e.dataTransfer.files[0];
      if (file?.type?.startsWith('image/')) {
        const reader = new FileReader();
        reader.onloadend = () => {
          setPreview(reader.result as string);
        };
        reader.readAsDataURL(file);
        onFileSelect?.(file);
      }
    },
    [onFileSelect]
  );

  return (
    <div className='gap-2 flex-1 w-full'>
      <div className='flex items-center justify-between'>
        {label && (
          <Label
            htmlFor={inputId}
            className={cn(
              'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 mb-2',
              error && 'text-red-500'
            )}
          >
            {label}
            {required && <span className='text-red-500 ml-1'>*</span>}
          </Label>
        )}
        {error && (
          <span id={errorId} className='text-[0.8rem] text-red-500'>
            {error}
          </span>
        )}
      </div>

      {description && (
        <p id={descriptionId} className={cn('text-sm', 'text-neutral-200')}>
          {description}
        </p>
      )}

      <div className='flex flex-col gap-4'>
        {isLoading ? (
          <div
            className={cn(
              'flex flex-col items-center justify-center p-8 rounded-lg border-2 border-dashed',
              'border-neutral-700 bg-neutral-200 hover:bg-neutral-700'
            )}
          >
            <Loader2 className='h-8 w-8 animate-spin text-blue-600 mb-2' />
            <p className={cn('text-sm', 'text-neutral-200')}>Uploading image...</p>
          </div>
        ) : preview ? (
          <div className='flex justify-center items-center'>
            <div className='relative w-fit'>
              <Image
                src={preview}
                alt='Preview'
                width={400}
                height={300}
                className='object-contain rounded-lg mx-auto'
              />
              <Button
                type='button'
                variant='destructive'
                size='icon'
                className='absolute right-2 top-2 cursor-pointer'
                onClick={handleRemove}
              >
                <X className='h-4 w-4' />
              </Button>
            </div>
          </div>
        ) : (
          <label
            htmlFor={inputId}
            className={cn(
              'flex flex-col items-center justify-center rounded-lg',
              'border-2 border-dashed transition-colors duration-200',
              isDragging ? 'border-blue-600 bg-blue-50' : 'border-neutral-300 bg-neutral-200 hover:bg-neutral-300',
              'cursor-pointer'
            )}
            onDragOver={handleDragOver}
            onDragLeave={handleDragLeave}
            onDrop={handleDrop}
          >
            <div className='flex flex-col items-center justify-center pt-5 pb-6'>
              <ImageIcon className={cn('w-8 h-8 mb-4', isDragging ? 'text-blue-600' : 'text-neutral-800')} />
              <p className={cn('mb-2 text-sm', isDragging ? 'text-blue-600' : 'text-neutral-800')}>
                <span className='font-semibold text-neutral-800'>Click to upload</span> or drag and drop
              </p>
              <p className={cn('text-xs', isDragging ? 'text-blue-600' : 'text-neutral-800')}>
                You can upload any image format (max. 3MB)
              </p>
            </div>
            <input
              id={inputId}
              type='file'
              name={name}
              className='hidden'
              accept={accept}
              onChange={handleFileSelect}
              aria-describedby={description ? descriptionId : undefined}
              aria-errormessage={error ? errorId : undefined}
              disabled={isLoading}
            />
          </label>
        )}
      </div>
    </div>
  );
}
