import React, { useRef, useState } from "react";
import { Plus, X } from "lucide-react";
import { toast } from "sonner";
import { cn } from "./utils";
import { PICTURE_UPLOAD_MAX_BYTES, resolvePictureUrlForDisplay, uploadImageFile } from "../../services/imageUploadService";

export type ImageUrlUploadProps = {
  value: string;
  onChange: (url: string) => void;
  disabled?: boolean;
  /** 辅助说明，显示在方框下方 */
  hint?: string;
  /** 空状态主文案 */
  emptyLabel?: string;
  accept?: string;
  /** 默认 5MB，与平台 picture 上传接口一致 */
  maxSizeMb?: number;
  className?: string;
  /** 上传区域宽度（tailwind），默认 max-w-[200px] */
  boxClassName?: string;
  /** 传给后端的 multipart `subDir`（如 category、product） */
  uploadSubDir?: string;
  /** 明确单图：隐藏多选、提示文案 */
  oneImageOnly?: boolean;
};

export function ImageUrlUpload({
  value,
  onChange,
  disabled,
  hint,
  emptyLabel = "Click to upload image",
  accept = "image/jpeg,image/png,image/webp,image/gif",
  maxSizeMb = PICTURE_UPLOAD_MAX_BYTES / (1024 * 1024),
  className,
  boxClassName,
  uploadSubDir,
  oneImageOnly,
}: ImageUrlUploadProps) {
  const inputRef = useRef<HTMLInputElement>(null);
  const [uploading, setUploading] = useState(false);

  const onFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    e.target.value = "";
    if (!file) return;
    if (!file.type.startsWith("image/")) {
      toast.error("Please select an image file.");
      return;
    }
    if (file.size > maxSizeMb * 1024 * 1024) {
      toast.error(`Image must be ${maxSizeMb} MB or smaller.`);
      return;
    }

    setUploading(true);
    try {
      const url = await uploadImageFile(file, { subDir: uploadSubDir });
      onChange(url);
      toast.success("Image uploaded.");
    } catch (err: unknown) {
      const msg = err instanceof Error ? err.message : String(err);
      toast.error("Upload failed", { description: msg || undefined });
    } finally {
      setUploading(false);
    }
  };

  const busy = disabled || uploading;

  const openPicker = () => {
    if (!busy) inputRef.current?.click();
  };

  const boxBase =
    "w-full max-w-[200px] aspect-square rounded-md transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2";

  return (
    <div className={cn("space-y-2", className)}>
      <input
        ref={inputRef}
        type="file"
        accept={accept}
        className="sr-only"
        disabled={busy}
        multiple={false}
        onChange={onFileChange}
      />

      {!value ? (
        <button
          type="button"
          disabled={busy}
          onClick={openPicker}
          className={cn(
            boxBase,
            "flex flex-col items-center justify-center gap-3 border-2 border-dashed border-gray-300 bg-gray-50/80 text-gray-400",
            "hover:border-gray-400 hover:bg-gray-100/90 hover:text-gray-500",
            "disabled:pointer-events-none disabled:opacity-50",
            boxClassName,
          )}
        >
          <Plus className="h-10 w-10 shrink-0 stroke-[1.25]" aria-hidden />
          <span className="px-3 text-center text-sm font-normal leading-tight">
            {uploading ? "Uploading…" : emptyLabel}
          </span>
        </button>
      ) : (
        <div
          className={cn(
            "group relative overflow-hidden rounded-md border-2 border-dashed border-gray-300 bg-gray-50/80",
            boxBase,
            boxClassName,
          )}
        >
          <button
            type="button"
            disabled={busy}
            onClick={openPicker}
            className="relative h-full w-full p-0"
            aria-label="Replace image"
          >
            <img
              src={resolvePictureUrlForDisplay(value)}
              alt=""
              className="h-full w-full object-contain"
              onError={(ev) => {
                (ev.target as HTMLImageElement).style.opacity = "0.2";
              }}
            />
            <span className="absolute inset-0 flex items-center justify-center bg-black/0 text-sm font-medium text-white opacity-0 transition group-hover:bg-black/45 group-hover:opacity-100">
              Click to replace
            </span>
          </button>
          <button
            type="button"
            disabled={busy}
            onClick={(e) => {
              e.stopPropagation();
              onChange("");
            }}
            className="absolute right-1.5 top-1.5 flex h-7 w-7 items-center justify-center rounded-full bg-white/95 text-gray-600 shadow-sm ring-1 ring-gray-200 transition hover:bg-white hover:text-gray-900 disabled:opacity-50"
            aria-label="Remove image"
          >
            <X className="h-4 w-4" />
          </button>
        </div>
      )}

      {oneImageOnly ? (
        <p className="text-xs text-muted-foreground">One image only. Replace or clear to change.</p>
      ) : null}
      {hint ? <p className="text-xs text-muted-foreground">{hint}</p> : null}
    </div>
  );
}
