import React, { useRef, useState } from 'react'
import { AnimatePresence, motion, useReducedMotion } from 'framer-motion'

function getExtension(fileName = '') {
  const parts = String(fileName).toLowerCase().split('.')
  return parts.length > 1 ? parts.pop() : ''
}

function detectPrimaryType(file) {
  if (!file) return 'unknown'

  const extension = getExtension(file.name)
  const mime = String(file.type || '').toLowerCase()

  const imageExt = new Set(['jpg', 'jpeg', 'png', 'webp'])
  const archiveExt = new Set(['zip', 'rar', '7z', 'tar', 'gz'])

  const imageMime = new Set(['image/jpeg', 'image/png', 'image/webp'])
  const archiveMime = new Set([
    'application/zip',
    'application/x-zip-compressed',
    'application/x-rar-compressed',
    'application/vnd.rar',
    'application/x-7z-compressed',
    'application/x-tar',
    'application/gzip',
    'application/x-gzip',
    'application/octet-stream',
  ])

  if (imageMime.has(mime) || imageExt.has(extension)) return 'image'
  if (archiveMime.has(mime) || archiveExt.has(extension)) return 'archive'
  return 'unsupported'
}

export default function UploadDropzone({
  title = 'Upload file',
  description = 'Drop file here or click to browse',
  fileName = '',
  fileHint = 'No file selected yet',
  previewUrl = '',
  fileMeta = null,
  errors = [],
  invalid = false,
  showLooksGood = false,
  looksGoodText = 'Looks good',
  locked = false,
  onPrimaryFileChange,
  onValidationResult,
}) {
  const [dragging, setDragging] = useState(false)
  const inputRef = useRef(null)
  const prefersReducedMotion = useReducedMotion()

  const dragTransition = prefersReducedMotion
    ? { duration: 0 }
    : { duration: 0.2, ease: 'easeOut' }

  const emitFile = (file) => {
    const detectedType = detectPrimaryType(file)
    if (typeof onPrimaryFileChange === 'function') {
      onPrimaryFileChange(file, { detectedType })
    }
    if (typeof onValidationResult === 'function') {
      onValidationResult({ file, detectedType })
    }
  }

  return (
    <section className={`rounded-xl bg-gradient-to-br p-0 shadow-[0_12px_32px_rgba(0,0,0,0.35)] transition-colors ${invalid ? 'ring-1 ring-red-400/40 from-red-500/10 to-slate-900/45' : 'ring-1 ring-white/10 from-slate-900/80 to-slate-900/50'}`}>
      {/* Intended props: file, dragState, accept, onDrop, onBrowse, onReset, disabled */}
      <motion.div
        data-testid="upload-dropzone"
        role="button"
        aria-disabled={locked ? 'true' : 'false'}
        tabIndex={locked ? -1 : 0}
        onClick={() => {
          if (locked) return
          inputRef.current?.click()
        }}
        onKeyDown={(event) => {
          if (locked) return
          if (event.key === 'Enter' || event.key === ' ') {
            event.preventDefault()
            inputRef.current?.click()
          }
        }}
        onDragOver={(event) => {
          if (locked) return
          event.preventDefault()
          setDragging(true)
        }}
        onDragLeave={() => setDragging(false)}
        onDrop={(event) => {
          if (locked) return
          event.preventDefault()
          setDragging(false)
          const droppedFile = event.dataTransfer?.files?.[0]
          if (droppedFile) emitFile(droppedFile)
        }}
        animate={prefersReducedMotion ? undefined : { scale: dragging ? 1.01 : 1 }}
        transition={dragTransition}
        className={`group rounded-xl border-2 border-dashed border-white/15 py-6 px-4 text-center transition hover:border-accent/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-300/70 ${locked ? 'cursor-default bg-white/5 opacity-75' : 'cursor-pointer'} ${invalid ? 'border-red-300/70 bg-red-500/10 shadow-[0_0_0_1px_rgba(248,113,113,0.2)]' : dragging ? 'border-cyan-300 bg-cyan-500/20 shadow-[0_0_0_1px_rgba(103,232,249,0.35)]' : locked ? 'bg-white/5' : 'bg-sky-500/5 hover:bg-sky-500/12'}`}
      >
        <h3 className="mt-3 text-sm font-semibold text-white">{title}</h3>
        <p className="mt-1 text-xs text-soft">{description}</p>

        {previewUrl ? (
          <div className="mt-2 w-full flex flex-col items-center gap-2">
            <div className="flex h-52 w-64 items-center justify-center overflow-hidden rounded-lg bg-black/40 ring-1 ring-white/10">
              <img
                src={previewUrl}
                alt="Selected preview"
                className="h-full w-full object-contain object-center"
                loading="lazy"
                decoding="async"
                width="250"
                height="208"
              />
            </div>
            <div className="text-xs text-white/70">Click to replace</div>
          </div>
        ) : (
          <>
            <div className="mx-auto flex h-14 w-14 items-center justify-center rounded-full border border-sky-400/60 bg-sky-500/12 text-sky-100 shadow-sm">
              <svg viewBox="0 0 24 24" className="h-7 w-7" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                <path d="M21 15v4a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-4" />
                <path d="M7 10l5-5 5 5" />
                <path d="M12 5v10" />
              </svg>
            </div>

            <p className="mt-1 text-xs text-soft">Accepted: JPG, JPEG, PNG, WEBP, ZIP, RAR, 7Z, TAR, GZ</p>
            <p className="text-xs text-soft">Max size: images 50MB · archives 200MB</p>

            <span className={`btn-secondary mt-3 inline-flex text-sm ${locked ? 'opacity-80' : 'group-focus-visible:bg-white/15'}`}>
              Click to browse files
            </span>
          </>
        )}

        <input
          ref={inputRef}
          type="file"
          className="hidden"
          aria-label="Upload file input"
          disabled={locked}
          accept=".jpg,.jpeg,.png,.webp,.zip,.rar,.7z,.tar,.gz,image/jpeg,image/png,image/webp"
          onChange={(event) => {
            const selectedFile = event.target.files?.[0]
            if (selectedFile) {
              emitFile(selectedFile)
            }
          }}
        />

        {(previewUrl || (fileMeta && String(fileMeta.type || '').startsWith('image/'))) && (
          <div className="mt-3 rounded-lg ring-1 ring-white/10 bg-black/25 px-3 py-2 text-left text-xs text-white/80">
            <div className="font-medium text-white/85">Selected file</div>
            <div className="mt-1 truncate">{fileName || fileHint}</div>
            {fileMeta && (
              <div className="mt-1 flex flex-wrap gap-2 text-xs text-white/60">
                <span>Type: <span className="text-white/80">{fileMeta.type || '—'}</span></span>
                <span>·</span>
                <span>Size: <span className="text-white/80">{fileMeta.size || '—'}</span></span>
                <span>·</span>
                <span>Resolution: <span className="text-white/80">{fileMeta.resolution || '—'}</span></span>
              </div>
            )}
          </div>
        )}

        {showLooksGood && (
          <div className="mt-3 inline-flex items-center gap-1.5 rounded-full border border-emerald-300/35 bg-emerald-500/15 px-3 py-1 text-xs text-emerald-100">
            <span aria-hidden="true">✓</span>
            <span>{looksGoodText}</span>
          </div>
        )}

        <AnimatePresence initial={false}>
          {errors.length > 0 && (
            <motion.div
              key="dropzone-errors"
              initial={prefersReducedMotion ? false : { opacity: 0, y: 4 }}
              animate={prefersReducedMotion ? {} : { opacity: 1, y: 0 }}
              exit={prefersReducedMotion ? {} : { opacity: 0, y: -4 }}
              transition={dragTransition}
              className="mt-4 rounded-lg border border-red-300/40 bg-red-500/10 p-3 text-left"
            >
              <p className="text-xs font-semibold uppercase tracking-wide text-red-100">Please fix the following</p>
              <ul className="mt-2 space-y-1 text-xs text-red-100" role="status" aria-live="polite">
                {errors.map((error, index) => (
                  <li key={`${error}-${index}`} className="rounded-md border border-red-300/35 bg-red-500/10 px-2 py-1">
                    {error}
                  </li>
                ))}
              </ul>
            </motion.div>
          )}
        </AnimatePresence>
      </motion.div>
    </section>
  )
}
