import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { test } from "node:test";

import {
  chaveDaFonte,
  corHex,
  FONTES_DA_LOJA,
  montarMudancaDaAparencia,
  temaPeloNome,
} from "./ferramentas/loja-e-documentos-aparencia.ts";
import { dominioComprado, explicarRegistros, nomeNoPainel, passoAPasso, situacaoDoDominio } from "./ferramentas/loja-e-documentos-dominio.ts";
import { escapar, htmlDaFolha, pedidoDoDocumentoPermitido } from "./ferramentas/loja-e-documentos-folha.ts";
import { conferirDominioPedido, getDomainKind, mergeDnsRecords, normalizeDomain } from "../dominio-personalizado.ts";

/* ------------------------------------------------------------- aparência */

test("a lista de fontes do assistente é a mesma da tela", () => {
  const arquivo = readFileSync(new URL("../catalog-fonts.ts", import.meta.url), "utf8");
  const daTela = [...arquivo.matchAll(/tipo: "fonte", key: "([^"]+)"/g)].map((m) => m[1]);
  assert.deepEqual(
    FONTES_DA_LOJA.map(([chave]) => chave),
    daTela
  );
});

test("cor: aceita #abc, abc e #AABBCC; recusa o resto", () => {
  assert.equal(corHex("#1F6FEB"), "#1F6FEB");
  assert.equal(corHex("abc"), "#AABBCC");
  assert.equal(corHex(" #ff0000 "), "#FF0000");
  assert.equal(corHex("vermelho"), null);
  assert.equal(corHex("#12345"), null);
  assert.equal(corHex("url(x)"), null);
});

test("fonte pela chave ou pelo nome; tema pelo nome", () => {
  assert.equal(chaveDaFonte("DM Sans"), "dm-sans");
  assert.equal(chaveDaFonte("dm-sans"), "dm-sans");
  assert.equal(chaveDaFonte("plus jakarta sans"), "plus-jakarta-sans");
  assert.equal(chaveDaFonte("Comic Sans"), null);
  assert.equal(temaPeloNome("Padrão"), "default");
  assert.equal(temaPeloNome("Vitrine"), "vitrine");
  assert.equal(temaPeloNome("Vendor"), "vendor");
  assert.equal(temaPeloNome("Ateliê"), "boutique");
  assert.equal(temaPeloNome("Boutique"), "boutique");
  assert.equal(temaPeloNome("outro"), null);
  /* O Neo a tela não oferece e a loja desenha como o Padrão: o assistente não escolhe. */
  assert.equal(temaPeloNome("Neo"), null);
});

test("mudança de aparência: só o que muda, com o antes para desfazer", () => {
  const atual = { catalog_name: "Aurora", primary_color: "#111111", catalog_slogan: null, catalog_theme: "neo", catalog_advanced_enabled: false };
  const r = montarMudancaDaAparencia({ valores: { nome: "Aurora", cor_principal: "#222", slogan: "Tudo impresso" }, voltarAoPadrao: [], tema: "Vitrine" }, atual);
  assert.ok(r.ok);
  if (!r.ok) return;
  assert.deepEqual(r.mudanca.colunas, { primary_color: "#222222", catalog_slogan: "Tudo impresso", catalog_theme: "vitrine" });
  assert.deepEqual(r.mudanca.antes, { primary_color: "#111111", catalog_slogan: null, catalog_theme: "neo" });
  assert.equal(r.mudanca.avisos.length, 0);
});

test("cor avançada liga a personalização avançada junto, com aviso", () => {
  const r = montarMudancaDaAparencia({ valores: { cor_do_cabecalho: "#000" }, voltarAoPadrao: [] }, { catalog_advanced_enabled: false });
  assert.ok(r.ok);
  if (!r.ok) return;
  assert.equal(r.mudanca.colunas.catalog_advanced_enabled, true);
  assert.equal(r.mudanca.antes.catalog_advanced_enabled, false);
  assert.equal(r.mudanca.avisos.length, 1);
});

test("quem já tem o Neo lê Padrão, e escolher Padrão grava default", () => {
  const r = montarMudancaDaAparencia({ valores: {}, voltarAoPadrao: [], tema: "Padrão" }, { catalog_theme: "neo" });
  assert.ok(r.ok);
  if (!r.ok) return;
  assert.equal(r.mudanca.colunas.catalog_theme, "default");
  assert.equal(r.mudanca.antes.catalog_theme, "neo");
  assert.equal(montarMudancaDaAparencia({ valores: {}, voltarAoPadrao: [], tema: "Neo" }, {}).ok, false);
});

test("mudança de aparência recusa o que não dá", () => {
  assert.equal(montarMudancaDaAparencia({ valores: { cor_principal: "azul" }, voltarAoPadrao: [] }, {}).ok, false);
  assert.equal(montarMudancaDaAparencia({ valores: {}, voltarAoPadrao: ["cor_principal"] }, {}).ok, false);
  assert.equal(montarMudancaDaAparencia({ valores: {}, voltarAoPadrao: ["inventado"] }, {}).ok, false);
  assert.equal(montarMudancaDaAparencia({ valores: { slogan: "x" }, voltarAoPadrao: ["slogan"] }, {}).ok, false);
  assert.equal(montarMudancaDaAparencia({ valores: { fonte_dos_titulos: "Comic Sans" }, voltarAoPadrao: [] }, {}).ok, false);
  const nada = montarMudancaDaAparencia({ valores: { nome: "Aurora" }, voltarAoPadrao: [] }, { catalog_name: "Aurora" });
  assert.equal(nada.ok, false);
  const padrao = montarMudancaDaAparencia({ valores: {}, voltarAoPadrao: ["cor_do_rodape"] }, { catalog_footer_color: "#ababab" });
  assert.ok(padrao.ok && padrao.mudanca.colunas.catalog_footer_color === null);
});

/* ---------------------------------------------------------------- domínio */

test("domínio: limpa, confere e separa raiz de subdomínio", () => {
  assert.equal(normalizeDomain("https://www.MinhaGrafica.com.br/loja"), "minhagrafica.com.br");
  assert.deepEqual(conferirDominioPedido("minhagrafica.com.br"), { ok: true, domain: "minhagrafica.com.br" });
  assert.equal(conferirDominioPedido("sem-ponto").ok, false);
  assert.equal(conferirDominioPedido("ktalogu.com.br").ok, false);
  assert.equal(getDomainKind("minhagrafica.com.br"), "root");
  assert.equal(getDomainKind("loja.minhagrafica.com.br"), "subdomain");
  assert.equal(getDomainKind("grafica.com"), "root");
  assert.equal(mergeDnsRecords([{ type: "TXT", host: "a", value: "1" }], [{ type: "TXT", host: "a", value: "1" }]).length, 1);
});

test("registros explicados com o nome que vai no painel", () => {
  assert.equal(dominioComprado("loja.minhagrafica.com.br"), "minhagrafica.com.br");
  assert.equal(dominioComprado("loja.grafica.com"), "grafica.com");
  assert.equal(nomeNoPainel("minhagrafica.com.br", "minhagrafica.com.br"), "@");
  assert.equal(nomeNoPainel("_cf-custom-hostname.loja.minhagrafica.com.br", "minhagrafica.com.br"), "_cf-custom-hostname.loja");
  const registros = explicarRegistros("loja.minhagrafica.com.br", [
    { type: "CNAME", host: "loja.minhagrafica.com.br", value: "lojas.ktalogu.com.br" },
    { type: "txt", host: "_acme-challenge.loja.minhagrafica.com.br", value: "abc" },
  ]);
  assert.deepEqual(registros.map((r) => [r.tipo, r.nome, r.valor]), [
    ["CNAME", "loja", "lojas.ktalogu.com.br"],
    ["TXT", "_acme-challenge.loja", "abc"],
  ]);
  const passos = passoAPasso("minhagrafica.com.br", registros, true);
  assert.ok(passos.cloudflare.some((p) => p.includes("dash.cloudflare.com")));
  assert.ok(passos.registro_br.some((p) => p.includes("registro.br")));
  assert.ok("atencao_dominio_raiz" in passos);
  assert.ok(!("atencao_dominio_raiz" in passoAPasso("loja.minhagrafica.com.br", registros, false)));
  assert.match(situacaoDoDominio({ domain: "x.com.br", verified: true }), /Funcionando/);
  assert.match(situacaoDoDominio({ domain: null }), /não tem domínio/);
  assert.match(situacaoDoDominio({ domain: "x.com.br", verified: false, cf_hostname_status: "active", cf_ssl_status: "pending_validation" }), /cadeado/);
});

/* -------------------------------------------------------------------- PDF */

test("a folha escapa o que veio do cadastro", () => {
  assert.equal(escapar(`<script>"x"&'y'</script>`), "&lt;script&gt;&quot;x&quot;&amp;&#39;y&#39;&lt;/script&gt;");
  const html = htmlDaFolha({
    rotulo: "PEDIDO",
    numero: 12,
    empresa: { nome: "<b>Aurora</b>", logo: "javascript:alert(1)" },
    cliente: { nome: "Cliente <img src=x onerror=alert(1)>" },
    itens: [{ titulo: "Banner", descricao: "linha 1\nlinha 2", medidas: "1 m × 2 m", quantidade: 2, unitario: 10, total: 20 }],
    totais: [["Total", "R$ 20,00", true]],
    secoes: [["Observações", "Entregar <amanhã>"]],
  });
  assert.ok(!html.includes("<b>Aurora</b>"));
  assert.ok(!html.includes("<img src=x"));
  assert.ok(!html.includes("javascript:"));
  assert.ok(html.includes("linha 1<br>linha 2"));
  assert.ok(html.includes("#12"));
});

test("o Chrome do servidor não busca endereço de dentro", () => {
  const loja = "http://127.0.0.1:3001";
  assert.equal(pedidoDoDocumentoPermitido("http://127.0.0.1:3001/_next/x.js", "GET", loja), true);
  assert.equal(pedidoDoDocumentoPermitido("http://127.0.0.1:3001/api/orcamento/leitura", "POST", loja), false);
  assert.equal(pedidoDoDocumentoPermitido("https://xyz.supabase.co/storage/v1/object/public/products/a.png", "GET", loja), true);
  assert.equal(pedidoDoDocumentoPermitido("http://169.254.169.254/latest/meta-data", "GET", loja), false);
  assert.equal(pedidoDoDocumentoPermitido("https://169.254.169.254/", "GET", loja), false);
  assert.equal(pedidoDoDocumentoPermitido("https://[::1]/", "GET", loja), false);
  assert.equal(pedidoDoDocumentoPermitido("https://localhost/", "GET", loja), false);
  assert.equal(pedidoDoDocumentoPermitido("https://servidor.internal/", "GET", loja), false);
  assert.equal(pedidoDoDocumentoPermitido("http://exemplo.com.br/a.png", "GET", loja), false);
  assert.equal(pedidoDoDocumentoPermitido("https://exemplo.com.br:8443/a.png", "GET", loja), false);
  assert.equal(pedidoDoDocumentoPermitido("data:image/png;base64,AAA", "GET", null), true);
  assert.equal(pedidoDoDocumentoPermitido("file:///etc/passwd", "GET", null), false);
});
