/**
 * Encolhe a foto no navegador antes de subir: no máximo 1600 px no lado
 * maior, em WebP com qualidade 0,85. A foto do celular de 4 MB vira uns
 * 200 KB; o Storage deixa de guardar originais gigantes; a transformação
 * de imagem da vitrine responde em milissegundos em vez de segundos; e o
 * limite de 25 MB do serviço deixa de existir na prática.
 *
 * Fica de fora o que não é foto (SVG, GIF, que pode ser animado) e o que já
 * é pequeno (até 1600 px e até 300 KB), que sobe como veio. Se o navegador
 * não conseguir (formato estranho, memória), sobe o original: encolher é
 * melhoria, nunca motivo para falhar o upload.
 */
export const LADO_MAIOR_PADRAO = 1600;
const PEQUENA_O_BASTANTE = 300 * 1024;

export async function encolherParaUpload(
  arquivo: File,
  opcoes?: { ladoMaior?: number; qualidade?: number }
): Promise<File> {
  const ladoMaior = opcoes?.ladoMaior ?? LADO_MAIOR_PADRAO;
  const qualidade = opcoes?.qualidade ?? 0.85;
  const tipo = String(arquivo.type || "").toLowerCase();
  if (!tipo.startsWith("image/") || tipo === "image/svg+xml" || tipo === "image/gif") return arquivo;
  if (typeof createImageBitmap !== "function" || typeof document === "undefined") return arquivo;

  let bitmap: ImageBitmap | null = null;
  try {
    /* "from-image": a foto do celular vem deitada e a orientação certa está
       nos metadados; sem isso ela subiria virada. */
    bitmap = await createImageBitmap(arquivo, { imageOrientation: "from-image" });
    const maior = Math.max(bitmap.width, bitmap.height);
    if (maior <= ladoMaior && arquivo.size <= PEQUENA_O_BASTANTE) return arquivo;

    const escala = Math.min(1, ladoMaior / maior);
    const largura = Math.max(1, Math.round(bitmap.width * escala));
    const altura = Math.max(1, Math.round(bitmap.height * escala));
    const canvas = document.createElement("canvas");
    canvas.width = largura;
    canvas.height = altura;
    const ctx = canvas.getContext("2d");
    if (!ctx) return arquivo;
    ctx.drawImage(bitmap, 0, 0, largura, altura);

    const blob = await new Promise<Blob | null>((resolve) => canvas.toBlob(resolve, "image/webp", qualidade));
    if (!blob || blob.size === 0) return arquivo;
    /* Saiu maior que a original (PNG pequeno com transparência, por exemplo)
       e nem precisava encolher: fica a original. */
    if (blob.size >= arquivo.size && maior <= ladoMaior) return arquivo;

    const nome = `${arquivo.name.replace(/\.[^/.]+$/, "") || "foto"}.webp`;
    return new File([blob], nome, { type: "image/webp", lastModified: Date.now() });
  } catch {
    return arquivo;
  } finally {
    bitmap?.close?.();
  }
}
