const IMAGE_UPLOAD_MAX_SIDE: Record<string, number> = {
  avatar: 512,
  chat: 1280,
  "home-banner": 1920,
  listing: 1920,
  dispute: 1920,
  handoff: 1920,
  realname: 1920,
};

const IMAGE_UPLOAD_QUALITY: Record<string, number> = {
  avatar: 0.82,
  chat: 0.8,
  "home-banner": 0.84,
  listing: 0.84,
  dispute: 0.86,
  handoff: 0.86,
  realname: 0.86,
};

export async function optimizeImageForUpload(file: File, scene: string) {
  if (!file.type.startsWith("image/")) return file;
  if (!["image/jpeg", "image/png", "image/webp"].includes(file.type)) return file;
  if (typeof document === "undefined") return file;

  try {
    const image = await loadImage(file);
    const maxSide = IMAGE_UPLOAD_MAX_SIDE[scene] || 1600;
    const quality = IMAGE_UPLOAD_QUALITY[scene] || 0.82;
    const { width, height } = fitSize(image.naturalWidth, image.naturalHeight, maxSide);
    const canvas = document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;
    const context = canvas.getContext("2d");
    if (!context) return file;
    context.fillStyle = "#ffffff";
    context.fillRect(0, 0, width, height);
    context.drawImage(image, 0, 0, width, height);
    const blob = await canvasToBlob(canvas, "image/webp", quality);
    if (!blob || blob.size >= file.size) return file;
    return new File([blob], replaceFileExt(file.name, "webp"), {
      type: "image/webp",
      lastModified: Date.now(),
    });
  } catch {
    return file;
  }
}

function loadImage(file: File) {
  return new Promise<HTMLImageElement>((resolve, reject) => {
    const url = URL.createObjectURL(file);
    const image = new Image();
    image.onload = () => {
      URL.revokeObjectURL(url);
      resolve(image);
    };
    image.onerror = () => {
      URL.revokeObjectURL(url);
      reject(new Error("图片读取失败"));
    };
    image.src = url;
  });
}

function fitSize(width: number, height: number, maxSide: number) {
  if (width <= 0 || height <= 0) return { width: 1, height: 1 };
  const scale = Math.min(1, maxSide / Math.max(width, height));
  return {
    width: Math.max(1, Math.round(width * scale)),
    height: Math.max(1, Math.round(height * scale)),
  };
}

function canvasToBlob(canvas: HTMLCanvasElement, type: string, quality: number) {
  return new Promise<Blob | null>((resolve) => {
    canvas.toBlob(resolve, type, quality);
  });
}

function replaceFileExt(filename: string, ext: string) {
  const base = filename.replace(/\.[^.]+$/, "");
  return `${base || "image"}.${ext}`;
}
