"use client"

import { useRef, useState } from "react"
import { UploadIcon, XIcon } from "lucide-react"
import { toast } from "sonner"

import { uploadAsset } from "@/lib/api/admin"
import { useI18n } from "@/i18n/provider"
import { cn } from "@/lib/utils"

export type ImageInputProps = {
  value?: string
  onChange?: (value: string) => void
  disabled?: boolean
  accept?: string
  maxSize?: number
  prefix?: string
  placeholder?: string
  className?: string
}

export function ImageInput({
  value,
  onChange,
  disabled,
  accept = "image/*",
  maxSize = 5 * 1024 * 1024,
  prefix,
  placeholder,
  className,
}: ImageInputProps) {
  const t = useI18n()
  const [uploading, setUploading] = useState(false)
  const fileInputRef = useRef<HTMLInputElement>(null)
  const resolvedPlaceholder = placeholder ?? t("upload.imagePlaceholder")

  function handleClick() {
    if (disabled || uploading) {
      return
    }
    fileInputRef.current?.click()
  }

  function handleClear(event: React.MouseEvent) {
    event.stopPropagation()
    onChange?.("")
  }

  async function handleFileChange(event: React.ChangeEvent<HTMLInputElement>) {
    const file = event.target.files?.[0]
    if (!file) {
      return
    }

    if (!file.type.startsWith("image/")) {
      toast.error(t("upload.chooseImage"))
      return
    }

    if (file.size > maxSize) {
      const maxSizeMB = (maxSize / 1024 / 1024).toFixed(0)
      toast.error(t("upload.imageTooLarge", { maxSize: maxSizeMB }))
      return
    }

    setUploading(true)
    try {
      const result = await uploadAsset(file, prefix)
      onChange?.(result.url)
      toast.success(t("upload.imageUploaded"))
    } catch (error) {
      toast.error(error instanceof Error ? error.message : t("upload.imageUploadFailed"))
    } finally {
      setUploading(false)
      if (fileInputRef.current) {
        fileInputRef.current.value = ""
      }
    }
  }

  const isDisabled = disabled || uploading

  return (
    <div className="relative w-fit">
      <input
        ref={fileInputRef}
        type="file"
        accept={accept}
        className="hidden"
        onChange={handleFileChange}
        disabled={isDisabled}
      />
      <div
        onClick={handleClick}
        className={cn(
          "group relative flex size-24 cursor-pointer items-center justify-center overflow-hidden rounded-lg border-2 border-dashed border-input bg-muted transition-colors",
          "hover:border-primary hover:bg-muted/50",
          "focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:outline-none",
          isDisabled && "cursor-not-allowed opacity-50",
          className
        )}
        tabIndex={isDisabled ? -1 : 0}
        onKeyDown={(e) => {
          if (e.key === "Enter" || e.key === " ") {
            e.preventDefault()
            handleClick()
          }
        }}
        role="button"
        aria-label={value ? t("upload.replaceImage") : resolvedPlaceholder}
      >
        {value ? (
          <>
            <img src={value} alt={t("upload.uploadedImage")} className="size-full object-cover" />
            <div className="absolute inset-0 flex items-center justify-center bg-black/50 opacity-0 transition-opacity group-hover:opacity-100">
              <span className="text-sm text-white">{t("upload.replaceImage")}</span>
            </div>
          </>
        ) : (
          <div className="flex flex-col items-center gap-1 text-muted-foreground">
            <UploadIcon className="size-6" />
            <span className="text-xs">{uploading ? t("upload.uploading") : resolvedPlaceholder}</span>
          </div>
        )}
        {uploading && (
          <div className="absolute inset-0 flex items-center justify-center bg-black/50">
            <div className="size-6 animate-spin rounded-full border-2 border-white border-t-transparent" />
          </div>
        )}
      </div>
      {value && !isDisabled && (
        <button
          type="button"
          onClick={handleClear}
          className="absolute -right-2 -top-2 flex size-5 items-center justify-center rounded-full bg-destructive text-destructive-foreground shadow-sm transition-colors hover:bg-destructive/80"
          aria-label={t("upload.deleteImage")}
        >
          <XIcon className="size-3" />
        </button>
      )}
    </div>
  )
}
