import { randomBytes } from "node:crypto";

/*
 * O código do envio de imagem (migration 192, assistentes_envios): 12 letras
 * sorteadas, sem as que se confundem (0/O, 1/l/I), como o link curto dos
 * arquivos. Vai no link /enviar/<código> e volta ao assistente como
 * "envio:<código>". Sem nada de banco aqui: é o que os testes conferem.
 */

const LETRAS = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789";

/* O formato que o banco aceita (check da coluna): 12 letras ou números. */
export const FORMATO_DO_CODIGO = /^[A-Za-z0-9]{12}$/;

/* Um envio vale 24 horas; a faxina apaga o que venceu há mais de um dia. */
export const VALIDADE_DO_ENVIO_MS = 24 * 60 * 60 * 1000;

export function gerarCodigoDeEnvio() {
  /* 256 não é múltiplo de 56 letras: descartar os bytes do fim tira o
     desequilíbrio (as primeiras letras sairiam um pouco mais). */
  const teto = 256 - (256 % LETRAS.length);
  let codigo = "";
  while (codigo.length < 12) {
    for (const byte of randomBytes(16)) {
      if (byte >= teto) continue;
      codigo += LETRAS[byte % LETRAS.length];
      if (codigo.length === 12) break;
    }
  }
  return codigo;
}

/** "envio:Ab3dE9xK2mQp", "Ab3dE9xK2mQp" ou o link inteiro viram só o código; o resto vira null. */
export function lerCodigoDeEnvio(valor: unknown): string | null {
  let texto = String(valor ?? "").trim();
  const doLink = /\/enviar\/([A-Za-z0-9]{12})\/?(?:[?#].*)?$/.exec(texto);
  if (doLink) texto = doLink[1];
  texto = texto.replace(/^envio:\s*/i, "");
  return FORMATO_DO_CODIGO.test(texto) ? texto : null;
}

/** Nome do arquivo que dá para guardar no depósito: sem acento, sem barra, com limite. */
export function nomeDoArquivoEnviado(nome: unknown, extensao: string) {
  const base = String(nome ?? "")
    .normalize("NFD")
    .replace(/[̀-ͯ]/g, "")
    .replace(/\.[a-zA-Z0-9]{1,5}$/, "")
    .replace(/[^a-zA-Z0-9_-]+/g, "-")
    .replace(/-+/g, "-")
    .replace(/^-|-$/g, "")
    .slice(0, 60);
  return `${base || "imagem"}.${extensao}`;
}

/* A extensão e o tipo de cada formato que o sharp reconhece e a loja aceita. */
export const FORMATOS_DO_ENVIO: Record<string, { extensao: string; tipo: string }> = {
  jpeg: { extensao: "jpg", tipo: "image/jpeg" },
  png: { extensao: "png", tipo: "image/png" },
  webp: { extensao: "webp", tipo: "image/webp" },
  gif: { extensao: "gif", tipo: "image/gif" },
  avif: { extensao: "avif", tipo: "image/avif" },
  heif: { extensao: "heic", tipo: "image/heif" },
  tiff: { extensao: "tiff", tipo: "image/tiff" },
};
