import { useCallback, useRef, useState, type ReactNode } from "react";
import "../styles/components/dropzone.css";

interface DropZoneProps {
  accept?: string;
  multiple?: boolean;
  onFiles: (files: File[]) => void;
  children?: ReactNode;
  className?: string;
  label?: string;
  hint?: string;
  disabled?: boolean;
}

export default function DropZone({
  accept = "image/*",
  multiple = false,
  onFiles,
  children,
  className = "",
  label = "拖入文件或点击上传",
  hint,
  disabled = false,
}: DropZoneProps) {
  const [isDragging, setIsDragging] = useState(false);
  const inputRef = useRef<HTMLInputElement>(null);
  const dragCounter = useRef(0);

  const handleDragEnter = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    dragCounter.current += 1;
    setIsDragging(true);
  }, []);

  const handleDragLeave = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    dragCounter.current -= 1;
    if (dragCounter.current <= 0) {
      dragCounter.current = 0;
      setIsDragging(false);
    }
  }, []);

  const handleDrop = useCallback(
    (e: React.DragEvent) => {
      e.preventDefault();
      dragCounter.current = 0;
      setIsDragging(false);
      if (disabled) return;
      const acceptTypes = accept.split(",").map((t) => t.trim());
      const files = Array.from(e.dataTransfer.files).filter((f) =>
        acceptTypes.some((t) => {
          if (t.endsWith("/*")) return f.type.startsWith(t.replace("/*", "/"));
          return f.type === t || f.name.endsWith(t);
        }),
      );
      if (files.length) onFiles(multiple ? files : files.slice(0, 1));
    },
    [accept, disabled, multiple, onFiles],
  );

  const handleChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const files = Array.from(e.target.files || []);
      if (files.length) onFiles(multiple ? files : files.slice(0, 1));
      e.target.value = "";
    },
    [multiple, onFiles],
  );

  return (
    <div
      className={`dropzone${isDragging ? " dropzone--active" : ""} ${className}`}
      onDragEnter={handleDragEnter}
      onDragOver={(e) => e.preventDefault()}
      onDragLeave={handleDragLeave}
      onDrop={handleDrop}
      onClick={() => !disabled && inputRef.current?.click()}
      role="button"
      tabIndex={0}
      onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") inputRef.current?.click(); }}
    >
      <input
        ref={inputRef}
        type="file"
        accept={accept}
        multiple={multiple}
        onChange={handleChange}
        style={{ display: "none" }}
      />
      {children || (
        <>
          <strong className="dropzone__label">{label}</strong>
          {hint && <span className="dropzone__hint">{hint}</span>}
        </>
      )}
    </div>
  );
}
