import { useCallback, useEffect, useRef, useState } from 'react';

interface UseFileInputOptions {
  onFilesSelected: (files: File[]) => void;
  enabled: boolean;
}

export function useFileInput({
  onFilesSelected,
  enabled,
}: UseFileInputOptions) {
  const [isDragging, setIsDragging] = useState(false);
  const inputRef = useRef<HTMLInputElement | null>(null);
  const dragCountRef = useRef(0);

  // Latest callback in a ref, so the effects below don't re-register when the
  // caller passes a new function each render.
  const onFilesRef = useRef(onFilesSelected);
  useEffect(() => {
    onFilesRef.current = onFilesSelected;
  }, [onFilesSelected]);

  // Hidden file input element
  useEffect(() => {
    const input = document.createElement('input');
    input.type = 'file';
    input.multiple = true;
    input.style.display = 'none';
    input.addEventListener('change', () => {
      if (input.files?.length) {
        onFilesRef.current(Array.from(input.files));
        input.value = '';
      }
    });
    document.body.appendChild(input);
    inputRef.current = input;
    return () => {
      document.body.removeChild(input);
      inputRef.current = null;
    };
  }, []);

  const openFilePicker = useCallback(() => {
    inputRef.current?.click();
  }, []);

  // Clipboard paste
  useEffect(() => {
    if (!enabled) return;

    const handlePaste = (e: ClipboardEvent) => {
      const files = Array.from(e.clipboardData?.files ?? []);
      if (files.length > 0) {
        e.preventDefault();
        onFilesRef.current(files);
      }
    };

    window.addEventListener('paste', handlePaste);
    return () => window.removeEventListener('paste', handlePaste);
  }, [enabled]);

  // Drag and drop handlers
  const onDragOver = useCallback(
    (e: React.DragEvent) => {
      if (!enabled) return;
      e.preventDefault();
      e.stopPropagation();
    },
    [enabled],
  );

  const onDragEnter = useCallback(
    (e: React.DragEvent) => {
      if (!enabled) return;
      e.preventDefault();
      e.stopPropagation();
      dragCountRef.current++;
      if (dragCountRef.current === 1) setIsDragging(true);
    },
    [enabled],
  );

  const onDragLeave = useCallback(
    (e: React.DragEvent) => {
      if (!enabled) return;
      e.preventDefault();
      e.stopPropagation();
      dragCountRef.current--;
      if (dragCountRef.current === 0) setIsDragging(false);
    },
    [enabled],
  );

  const onDrop = useCallback(
    (e: React.DragEvent) => {
      if (!enabled) return;
      e.preventDefault();
      e.stopPropagation();
      dragCountRef.current = 0;
      setIsDragging(false);
      const files = Array.from(e.dataTransfer.files);
      if (files.length > 0) {
        onFilesRef.current(files);
      }
    },
    [enabled],
  );

  return {
    openFilePicker,
    isDragging,
    dropZoneProps: { onDragOver, onDragEnter, onDragLeave, onDrop },
  };
}
