import { Input } from '@workspace/ui/components/input';
import { Label } from '@workspace/ui/components/label';
import { cn } from '@workspace/ui/lib/utils';
import { Upload } from 'lucide-react';
import { useState } from 'react';

type ReturnType = 'base64' | 'file';

interface UploadImageProps {
  onChange: (value: string | File) => void;
  returnType?: ReturnType;
  id?: string;
  children?: React.ReactNode;
  className?: string;
}

export const UploadImage = ({
  onChange,
  returnType = 'base64',
  id = 'image-upload',
  children,
  className,
}: UploadImageProps) => {
  const [isDragging, setIsDragging] = useState(false);

  const toBase64 = (file: File): Promise<string> => {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.readAsDataURL(file);
      reader.onload = () => resolve(reader.result as string);
      reader.onerror = (error) => reject(error);
    });
  };

  const handleImageUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;

    try {
      if (returnType === 'base64') {
        const base64 = await toBase64(file);
        onChange(base64);
      } else {
        onChange(file);
      }
    } catch (error) {
      console.error(error);
    }
  };

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

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

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

    const file = e.dataTransfer.files?.[0];
    if (!file) return;

    try {
      if (returnType === 'base64') {
        const base64 = await toBase64(file);
        onChange(base64);
      } else {
        onChange(file);
      }
    } catch (error) {
      console.error(error);
    }
  };

  return (
    <>
      <Input type='file' accept='image/*' className='hidden' id={id} onChange={handleImageUpload} />
      <Label
        htmlFor={id}
        onDragOver={handleDragOver}
        onDragLeave={handleDragLeave}
        onDrop={handleDrop}
        className={cn(
          'cursor-pointer',
          !children && 'flex items-center justify-center rounded-lg border-2 border-dashed p-4',
          isDragging && 'border-primary bg-muted/50',
          className,
        )}
      >
        {children || <Upload />}
      </Label>
    </>
  );
};
