import assert from "node:assert/strict";
import { test } from "node:test";
import { categoriaDaExtensao, conferirConteudo, conferirExtensao, formatoReal, tipoDaExtensao } from "./formatos.ts";
import { faixaDoEspaco, GB, limitesDaLoja, MB, partesDoArquivo } from "./limites.ts";

const b = (...n: number[]) => new Uint8Array(n);
const texto = (s: string) => new TextEncoder().encode(s);

test("extensão: aceita, recusa programa e pede ZIP no lugar de RAR", () => {
  assert.deepEqual(conferirExtensao("PDF"), { ok: true, categoria: "pdf" });
  assert.deepEqual(conferirExtensao("mp4"), { ok: true, categoria: "video" });
  assert.deepEqual(conferirExtensao("cdr"), { ok: true, categoria: "imagem" });
  assert.deepEqual(conferirExtensao("pes"), { ok: true, categoria: "outro" });
  assert.equal(conferirExtensao("exe").ok, false);
  assert.equal(conferirExtensao("apk").ok, false);
  const rar = conferirExtensao("rar");
  assert.ok(!rar.ok && rar.motivo.includes(".zip"));
  assert.equal(conferirExtensao("").ok, false);
  assert.equal(conferirExtensao("xyz").ok, false);
});

test("formato real pelos primeiros bytes", () => {
  assert.equal(formatoReal(texto("%PDF-1.7")), "pdf");
  assert.equal(formatoReal(b(0x50, 0x4b, 0x03, 0x04)), "zip");
  assert.equal(formatoReal(b(0x4d, 0x5a, 0x90, 0x00)), "executavel");
  assert.equal(formatoReal(b(0x7f, 0x45, 0x4c, 0x46)), "executavel");
  assert.equal(formatoReal(b(0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70, 0x69, 0x73, 0x6f, 0x6d)), "mp4");
  assert.equal(formatoReal(texto("RIFF\u0000\u0000\u0000\u0000WEBPVP8 ")), "webp");
  assert.equal(formatoReal(texto("Rar!\u001a\u0007")), "rar");
  assert.equal(formatoReal(texto("ID3\u0004")), "mp3");
  assert.equal(formatoReal(texto("qualquer texto")), "desconhecido");
  assert.equal(formatoReal(b()), "desconhecido");
});

test("conteúdo tem de bater com a extensão", () => {
  assert.equal(conferirConteudo("pdf", texto("%PDF-1.4")).ok, true);
  assert.equal(conferirConteudo("pdf", b(0x4d, 0x5a)).ok, false, "programa com nome de pdf");
  assert.equal(conferirConteudo("zip", texto("Rar!")).ok, false, "rar com nome de zip");
  assert.equal(conferirConteudo("docx", b(0x50, 0x4b, 0x03, 0x04)).ok, true, "docx é zip por dentro");
  assert.equal(conferirConteudo("pdf", texto("<html>")).ok, false);
  assert.equal(conferirConteudo("svg", texto("<svg ...")).ok, true, "sem assinatura confiável, passa");
  assert.equal(conferirConteudo("cdr", b(0x4d, 0x5a)).ok, false, "programa nunca passa");
});

test("tipo e categoria", () => {
  assert.equal(tipoDaExtensao("mp4"), "video/mp4");
  assert.equal(tipoDaExtensao("desconhecida"), "application/octet-stream");
  assert.equal(categoriaDaExtensao("ZIP"), "compactado");
  assert.equal(categoriaDaExtensao("exe"), null);
});

test("limites: assinante 20 GB e 2 GB por arquivo; teste 1 GB e 100 MB", () => {
  assert.deepEqual(limitesDaLoja("ativa"), { total: 20 * GB, porArquivo: 2 * GB, teste: false });
  assert.deepEqual(limitesDaLoja("teste"), { total: 1 * GB, porArquivo: 100 * MB, teste: true });
  assert.equal(faixaDoEspaco(10, 100), "folga");
  assert.equal(faixaDoEspaco(80, 100), "perto");
  assert.equal(faixaDoEspaco(100, 100), "cheio");
  assert.equal(partesDoArquivo(0), 0);
  assert.equal(partesDoArquivo(1), 1);
  assert.equal(partesDoArquivo(16 * MB), 1);
  assert.equal(partesDoArquivo(16 * MB + 1), 2);
  assert.equal(partesDoArquivo(2 * GB), 128);
});
