"use client";

import { cn } from "@/lib/utils";
import type { ReactNode } from "react";
import { useRef } from "react";
import { ImageIcon, X } from "lucide-react";
import { Button } from "@/components/ui/button";

interface FileUploadDropzoneProps {
  file?: File | null;
  files?: File[];
  existingImageUrl?: string;
  onFileChange?: (file: File | null) => void;
  onFilesChange?: (files: File[]) => void;
  multiple?: boolean;
  accept?: string;
  uploadHint: string;
  browseLabel: string;
  helperText?: string;
  icon?: ReactNode;
  className?: string;
  dropzoneClassName?: string;
  iconWrapperClassName?: string;
  minHeightClassName?: string;
  disabled?: boolean;
}

export function FileUploadDropzone({
  file,
  files,
  existingImageUrl,
  onFileChange,
  onFilesChange,
  multiple = false,
  accept,
  uploadHint,
  browseLabel,
  helperText,
  icon,
  className,
  dropzoneClassName,
  iconWrapperClassName,
  minHeightClassName = "min-h-40",
  disabled = false,
}: FileUploadDropzoneProps) {
  const inputRef = useRef<HTMLInputElement>(null);
  const currentFiles = multiple ? files || [] : file ? [file] : [];
  const showExisting = !multiple && !file && !!existingImageUrl;

  const setFile = (files?: FileList | null) => {
    if (multiple) {
      onFilesChange?.([...(currentFiles || []), ...Array.from(files || [])]);
      return;
    }

    const nextFile = files?.[0] ?? null;
    onFileChange?.(nextFile);
  };

  const removeFile = (index: number) => {
    if (multiple) {
      onFilesChange?.(currentFiles.filter((_, currentIndex) => currentIndex !== index));
      return;
    }

    onFileChange?.(null);
  };

  return (
    <div className={cn("w-full", className)}>
      <input
        ref={inputRef}
        type="file"
        accept={accept}
        multiple={multiple}
        className="hidden"
        disabled={disabled}
        onChange={(event) => setFile(event.target.files)}
      />

      {showExisting ? (
        <div className={cn("relative overflow-hidden rounded-xl border border-border", minHeightClassName, dropzoneClassName)}>
          {/* eslint-disable-next-line @next/next/no-img-element */}
          <img src={existingImageUrl} alt="" className="h-full w-full object-cover" />
          <button
            type="button"
            disabled={disabled}
            onClick={() => inputRef.current?.click()}
            className="absolute inset-0 flex items-center justify-center bg-black/40 opacity-0 transition-opacity hover:opacity-100 disabled:cursor-not-allowed"
          >
            <span className="font-sans rounded-lg bg-white px-4 py-2 text-sm font-medium text-foreground">
              {browseLabel}
            </span>
          </button>
        </div>
      ) : (
        <div
          role="button"
          tabIndex={disabled ? -1 : 0}
          aria-disabled={disabled}
          className={cn(
            "flex flex-col items-center justify-center gap-4 rounded-xl border-2 border-dashed p-6 text-center",
            "transition-colors",
            disabled && "cursor-not-allowed opacity-60",
            minHeightClassName,
            dropzoneClassName
          )}
          onClick={() => {
            if (!disabled) {
              inputRef.current?.click();
            }
          }}
          onKeyDown={(event) => {
            if (disabled) return;
            if (event.key === "Enter" || event.key === " ") {
              event.preventDefault();
              inputRef.current?.click();
            }
          }}
          onDragOver={(event) => {
            if (disabled) return;
            event.preventDefault();
          }}
          onDrop={(event) => {
            if (disabled) return;
            event.preventDefault();
            setFile(event.dataTransfer.files);
          }}
        >
          {icon ? (
            <div
              className={cn(
                "flex h-12 w-12 items-center justify-center rounded-full",
                iconWrapperClassName
              )}
            >
              {icon}
            </div>
          ) : null}

          <div className="space-y-1">
            <p className="font-sans text-sm text-muted-foreground">
              {uploadHint}
            </p>
            <button
              type="button"
              disabled={disabled}
              onClick={(event) => {
                event.stopPropagation();
                inputRef.current?.click();
              }}
              className="font-sans text-sm text-primary underline disabled:opacity-60"
            >
              {browseLabel}
            </button>
            <p className="font-sans text-xs text-muted-foreground">{helperText}</p>
          </div>
        </div>
      )}

      {currentFiles.length ? (
        <div className="mt-3 space-y-2">
          {currentFiles.map((currentFile, index) => (
            <div
              key={`${currentFile.name}-${index}`}
              className="flex items-center justify-between rounded-xl border border-border bg-muted px-3 py-2"
            >
              <div className="flex min-w-0 items-center gap-2">
                <ImageIcon className="size-4 shrink-0 text-muted-foreground" />
                <span className="truncate text-sm text-foreground">{currentFile.name}</span>
              </div>
              <Button
                type="button"
                variant="ghost"
                size="icon"
                className="size-7 shrink-0"
                disabled={disabled}
                onClick={() => removeFile(index)}
              >
                <X className="size-4" />
              </Button>
            </div>
          ))}
        </div>
      ) : null}
    </div>
  );
}
