'use client'

import { useEffect, useRef, useState } from 'react'
import { Camera, Clipboard, X } from 'lucide-react'
import { cn } from '@/lib/utils'

interface Props {
  name: string
  label?: string
  hint?: string
  globalPaste?: boolean
  className?: string
  required?: boolean
}

export function ImageDropzone({
  name,
  label = 'Photo',
  hint = 'Take a photo, choose a file, paste from clipboard, or drag in',
  globalPaste = true,
  className,
  required,
}: Props) {
  const inputRef = useRef<HTMLInputElement>(null)
  const [previewUrl, setPreviewUrl] = useState<string | null>(null)
  const [fileName, setFileName] = useState<string | null>(null)
  const [dragActive, setDragActive] = useState(false)

  const setFile = (file: File | null) => {
    if (!file) {
      if (inputRef.current) inputRef.current.value = ''
      if (previewUrl) URL.revokeObjectURL(previewUrl)
      setPreviewUrl(null)
      setFileName(null)
      return
    }
    if (!file.type.startsWith('image/')) return

    const dt = new DataTransfer()
    dt.items.add(file)
    if (inputRef.current) inputRef.current.files = dt.files

    if (previewUrl) URL.revokeObjectURL(previewUrl)
    setPreviewUrl(URL.createObjectURL(file))
    setFileName(file.name || 'pasted-image.png')
  }

  useEffect(() => {
    return () => {
      if (previewUrl) URL.revokeObjectURL(previewUrl)
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  useEffect(() => {
    if (!globalPaste) return
    const handler = (e: ClipboardEvent) => {
      const items = e.clipboardData?.items
      if (!items) return
      const target = e.target as HTMLElement | null
      if (target && (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable)) {
        const hasImage = Array.from(items).some(it => it.type.startsWith('image/'))
        if (!hasImage) return
      }
      for (const item of items) {
        if (item.type.startsWith('image/')) {
          const file = item.getAsFile()
          if (file) {
            setFile(file)
            e.preventDefault()
            break
          }
        }
      }
    }
    document.addEventListener('paste', handler)
    return () => document.removeEventListener('paste', handler)
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [globalPaste])

  const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setFile(e.target.files?.[0] || null)
  }

  const onDrop = (e: React.DragEvent) => {
    e.preventDefault()
    setDragActive(false)
    const file = e.dataTransfer.files?.[0]
    if (file) setFile(file)
  }

  const onPasteLocal = (e: React.ClipboardEvent) => {
    const items = e.clipboardData?.items
    if (!items) return
    for (const item of items) {
      if (item.type.startsWith('image/')) {
        const file = item.getAsFile()
        if (file) {
          setFile(file)
          e.preventDefault()
          break
        }
      }
    }
  }

  return (
    <div className={cn('space-y-2', className)}>
      {label && <div className="text-sm font-medium">{label}</div>}

      <div
        tabIndex={0}
        onPaste={onPasteLocal}
        onDragOver={e => { e.preventDefault(); setDragActive(true) }}
        onDragLeave={() => setDragActive(false)}
        onDrop={onDrop}
        onClick={() => inputRef.current?.click()}
        className={cn(
          'relative rounded-lg border-2 border-dashed transition-colors cursor-pointer outline-none',
          'focus-visible:border-primary focus-visible:ring-2 focus-visible:ring-ring/50',
          dragActive ? 'border-primary bg-primary/5' : 'hover:bg-accent/40',
          previewUrl ? 'p-2' : 'p-6 min-h-[140px] flex flex-col items-center justify-center gap-2 text-center',
        )}
      >
        {previewUrl ? (
          <div className="relative">
            {/* eslint-disable-next-line @next/next/no-img-element */}
            <img src={previewUrl} alt="Preview" className="w-full h-auto rounded max-h-80 object-contain bg-muted" />
            <button
              type="button"
              onClick={(e) => { e.stopPropagation(); setFile(null) }}
              className="absolute top-2 right-2 size-8 rounded-full bg-black/60 text-white flex items-center justify-center"
              aria-label="Remove photo"
            >
              <X className="size-4" />
            </button>
            <div className="mt-2 text-xs text-muted-foreground text-center truncate">{fileName}</div>
          </div>
        ) : (
          <>
            <div className="flex items-center gap-2 text-sm text-muted-foreground">
              <Camera className="size-5" />
              <span>Tap to capture, or</span>
              <Clipboard className="size-4" />
              <span className="font-medium">paste</span>
            </div>
            {hint && <p className="text-xs text-muted-foreground max-w-xs">{hint}</p>}
          </>
        )}
        <input
          ref={inputRef}
          type="file"
          name={name}
          accept="image/*"
          required={required}
          className="sr-only"
          onChange={onChange}
        />
      </div>
    </div>
  )
}
