/*
 * Nomes de arquivo: o que a loja enviou é guardado como veio, mas o que vai
 * para o cabeçalho de download e para a tela passa por aqui.
 */

const TETO_DO_NOME = 180;

/* Tira caminho, caracteres de controle e o que o Windows não aceita. */
export function nomeLimpo(nome: string): string {
  const base = String(nome || "")
    .split(/[\\/]/)
    .pop()!
    .replace(/[\u0000-\u001f\u007f<>:"|?*]/g, "")
    .replace(/\s+/g, " ")
    .trim()
    .replace(/^\.+/, "");
  if (!base) return "arquivo";
  if (base.length <= TETO_DO_NOME) return base;
  const ponto = base.lastIndexOf(".");
  const extensao = ponto > 0 && base.length - ponto <= 12 ? base.slice(ponto) : "";
  return base.slice(0, TETO_DO_NOME - extensao.length) + extensao;
}

/* A extensão em minúsculas, sem o ponto ("" quando não há). */
export function extensaoDe(nome: string): string {
  const limpo = nomeLimpo(nome);
  const ponto = limpo.lastIndexOf(".");
  if (ponto <= 0 || ponto === limpo.length - 1) return "";
  const ext = limpo.slice(ponto + 1).toLowerCase();
  return /^[a-z0-9]{1,10}$/.test(ext) ? ext : "";
}

/* Versão só com ASCII, para navegador antigo. */
function nomeAscii(nome: string): string {
  const semAcento = nome.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
  const ascii = semAcento.replace(/[^\x20-\x7e]/g, "_").replace(/["\\;]/g, "_").trim();
  return ascii || "arquivo";
}

function codificar5987(texto: string): string {
  return encodeURIComponent(texto).replace(/['()*!]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
}

/* O valor do Content-Disposition: baixar (attachment) ou abrir (inline). */
export function disposicaoDoArquivo(nome: string, abrirNoNavegador = false): string {
  const limpo = nomeLimpo(nome);
  const tipo = abrirNoNavegador ? "inline" : "attachment";
  return `${tipo}; filename="${nomeAscii(limpo)}"; filename*=UTF-8''${codificar5987(limpo)}`;
}

/* "12,4 MB", "1,2 GB", "820 KB": como a tela mostra tamanho. */
export function tamanhoLegivel(bytes: number): string {
  const valor = Number(bytes);
  if (!Number.isFinite(valor) || valor <= 0) return "0 KB";
  const kb = valor / 1024;
  if (kb < 1024) return `${Math.max(1, Math.round(kb))} KB`;
  const mb = kb / 1024;
  if (mb < 1024) return `${mb < 10 ? mb.toFixed(1).replace(".", ",") : Math.round(mb)} MB`;
  const gb = mb / 1024;
  return `${gb.toFixed(gb < 10 ? 1 : 0).replace(".", ",")} GB`;
}
