import styles from './FileInput.module.css'
import { forwardRef, useRef, useState, useImperativeHandle, type ReactNode } from 'react'
import { X } from 'lucide-react'

export interface FileInputProps {
  /** File type filter, e.g. ".pem,.crt,.cer" */
  accept?: string
  /** Icon rendered before the label */
  icon?: ReactNode
  /** Placeholder text when no file is selected */
  placeholder?: string
  /** Additional CSS class */
  className?: string
  /** Called when a file is selected or cleared */
  onChange?: (file: File | null) => void
}

export interface FileInputHandle {
  /** The currently selected File, or null */
  file: File | null
  /** Programmatically clear the selection */
  clear: () => void
}

export const FileInput = forwardRef<FileInputHandle, FileInputProps>(
  ({ accept, icon, placeholder = 'Drop file or click to browse', className, onChange }, ref) => {
    const inputRef = useRef<HTMLInputElement>(null)
    const [fileName, setFileName] = useState<string | null>(null)
    const [dragOver, setDragOver] = useState(false)
    const fileRef = useRef<File | null>(null)

    function select(file: File | null) {
      fileRef.current = file
      setFileName(file?.name ?? null)
      onChange?.(file)
    }

    function handleInputChange() {
      select(inputRef.current?.files?.[0] ?? null)
    }

    function handleDrop(e: React.DragEvent) {
      e.preventDefault()
      setDragOver(false)
      const file = e.dataTransfer.files[0]
      if (file && inputRef.current) {
        const dt = new DataTransfer()
        dt.items.add(file)
        inputRef.current.files = dt.files
        select(file)
      }
    }

    function handleClear(e: React.MouseEvent) {
      e.stopPropagation()
      if (inputRef.current) inputRef.current.value = ''
      select(null)
    }

    useImperativeHandle(ref, () => ({
      get file() { return fileRef.current },
      clear() {
        if (inputRef.current) inputRef.current.value = ''
        select(null)
      },
    }))

    const wrapClass = [styles.wrap, dragOver && styles.dragOver, className].filter(Boolean).join(' ')

    return (
      <div
        className={wrapClass}
        onClick={() => inputRef.current?.click()}
        onDragOver={(e) => { e.preventDefault(); setDragOver(true) }}
        onDragLeave={() => setDragOver(false)}
        onDrop={handleDrop}
      >
        {icon && <span className={styles.icon}>{icon}</span>}
        <span className={`${styles.label} ${fileName ? styles.fileName : styles.placeholder}`}>
          {fileName ?? placeholder}
        </span>
        {fileName && (
          <button type="button" className={styles.clearBtn} onClick={handleClear} aria-label="Clear file">
            <X size={12} />
          </button>
        )}
        <input
          ref={inputRef}
          type="file"
          accept={accept}
          onChange={handleInputChange}
          style={{ display: 'none' }}
        />
      </div>
    )
  },
)

FileInput.displayName = 'FileInput'
