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

import {
  comMensagem,
  conferirMensagem,
  descreverValor,
  exemploDaMensagem,
  lerMensagem,
  lerObservacao,
  mesmoValor,
  MENSAGENS,
  observacaoPedida,
  QUAIS_MENSAGENS,
  qualMensagemPeloNome,
  TAMANHO_DA_MENSAGEM,
  textoEfetivo,
  tituloDe,
} from "./personalizacoes/catalogo.ts";
import { getDefaultTemplatesClient } from "../whatsapp-templates-client.ts";
import { contatosNoTexto, contatosNovos, recusaDeContatos } from "./contatos.ts";

test("mensagens: o texto padrão é o mesmo que o painel usa", () => {
  const padroes = getDefaultTemplatesClient();
  assert.equal(MENSAGENS.orcamento.padrao, padroes.quote_share);
  assert.equal(MENSAGENS.pedido.padrao, padroes.order_status);
  assert.equal(MENSAGENS.produto.padrao, padroes.product_inquiry);
  assert.equal(MENSAGENS.cabecalho_do_pedido.padrao, padroes.cart_checkout_header);
  assert.equal(MENSAGENS.rodape_do_pedido.padrao, padroes.cart_checkout_footer);
  /* As três da loja entraram quando a loja passou a lê-las (regras-da-loja.ts no apps/public). */
  assert.deepEqual(QUAIS_MENSAGENS, ["orcamento", "pedido", "produto", "cabecalho_do_pedido", "rodape_do_pedido"], "só as mensagens que o sistema de fato usa");
  /* Todo marcador do texto padrão está na lista dos aceitos. */
  for (const qual of QUAIS_MENSAGENS) {
    assert.ok(conferirMensagem(qual, MENSAGENS[qual].padrao).ok, `${qual}: o padrão passa na própria conferência`);
  }
});

test("mensagens: o nome que a pessoa usa vira a chave", () => {
  assert.equal(qualMensagemPeloNome("orçamento"), "orcamento");
  assert.equal(qualMensagemPeloNome("Andamento do pedido"), "pedido");
  assert.equal(qualMensagemPeloNome("pedido"), "pedido");
  assert.equal(qualMensagemPeloNome("dúvida sobre produto"), "produto");
  assert.equal(qualMensagemPeloNome("Rodapé do pedido da loja"), "rodape_do_pedido");
  assert.equal(qualMensagemPeloNome("carrinho"), null, "nome vago não adivinha qual é");
  assert.equal(qualMensagemPeloNome(undefined), null);
});

test("mensagens: ler, trocar e voltar ao padrão sem mexer nas outras", () => {
  const guardado = { quote_share: "Oi! Orçamento {{numero_orcamento}}: {{link}}", product_inquiry: "Quero {{nome_produto}}" };
  assert.equal(lerMensagem(guardado, "orcamento"), guardado.quote_share);
  assert.equal(lerMensagem(guardado, "pedido"), null, "sem texto próprio, vale o padrão");
  assert.equal(lerMensagem(null, "orcamento"), null);
  assert.equal(lerMensagem({ quote_share: "   " }, "orcamento"), null, "texto em branco é como não ter");
  assert.equal(lerMensagem("lixo", "orcamento"), null);
  assert.equal(textoEfetivo("pedido", null), MENSAGENS.pedido.padrao);

  const trocado = comMensagem(guardado, "pedido", "Pedido {{numero_pedido}}: {{status}} {{link}}");
  assert.equal(trocado.order_status, "Pedido {{numero_pedido}}: {{status}} {{link}}");
  assert.equal(trocado.product_inquiry, guardado.product_inquiry, "as outras ficam como estavam");
  assert.equal(trocado.quote_share, guardado.quote_share);

  const devolvido = comMensagem(guardado, "orcamento", null);
  assert.ok(!("quote_share" in devolvido), "voltar ao padrão tira a chave");
  assert.equal(devolvido.product_inquiry, guardado.product_inquiry);
  assert.deepEqual(comMensagem(null, "orcamento", "Olá {{link}}"), { quote_share: "Olá {{link}}" });
});

test("mensagens: só os marcadores daquela mensagem, e chaves sempre em par", () => {
  const ok = conferirMensagem("orcamento", "Olá! Orçamento *#{{numero_orcamento}}*, total {{total}}.{{validade}}{{condicoes}} Veja: {{link}}");
  assert.ok(ok.ok && ok.avisos.length === 0);

  const deOutra = conferirMensagem("orcamento", "Pedido {{numero_pedido}} {{link}}");
  assert.ok(!deOutra.ok && /\{\{numero_pedido\}\} não existe/.test(deOutra.erro) && deOutra.erro.includes("{{numero_orcamento}}"));
  const inventado = conferirMensagem("pedido", "Oi {{nome_do_cliente}}, {{status}} {{link}}");
  assert.ok(!inventado.ok && inventado.erro.includes("{{nome_do_cliente}}"));
  const comEspaco = conferirMensagem("pedido", "Status: {{ status }} {{link}}");
  assert.ok(!comEspaco.ok, "o marcador tem de estar escrito exatamente igual");
  const semPar = conferirMensagem("pedido", "Status: {{status} {{link}}");
  assert.ok(!semPar.ok);
  const sobrando = conferirMensagem("pedido", "Status: {{status}}}} {{link}}");
  assert.ok(!sobrando.ok);

  assert.ok(!conferirMensagem("orcamento", "   ").ok, "vazia não");
  assert.ok(!conferirMensagem("orcamento", "a".repeat(TAMANHO_DA_MENSAGEM + 1)).ok, "longa demais não");

  const semLink = conferirMensagem("orcamento", "Segue o orçamento {{numero_orcamento}}.");
  assert.ok(semLink.ok && /não tem \{\{link\}\}/.test(semLink.avisos[0]), "sem o link passa, mas avisa");
});

test("mensagens: o exemplo troca cada marcador pelo valor de exemplo", () => {
  const exemplo = exemploDaMensagem("orcamento", "Orçamento #{{numero_orcamento}}: {{total}}.{{validade}}{{condicoes}} {{link}} {{link}}");
  assert.ok(!exemplo.includes("{{"), "nenhum marcador sobra");
  assert.ok(exemplo.startsWith("Orçamento #42: R$ 1.500,00. Validade: 15/03/2027. Pagamento:"));
  assert.equal(exemplo.split("https://ktalogu.com.br/sua-loja/o/abc123").length - 1, 2, "marcador repetido troca as duas vezes");
  assert.equal(exemploDaMensagem("pedido", MENSAGENS.pedido.padrao).includes("*Em produção*"), true);
});

test("observação padrão: o que a pessoa pediu sobre o que já existe", () => {
  const desligada = { texto: null, ligada: false };
  const atual = { texto: "Prazo de 5 dias úteis.", ligada: true };

  assert.deepEqual(lerObservacao({ quote_default_notes: "Prazo", quote_default_notes_enabled: true }), { texto: "Prazo", ligada: true });
  assert.deepEqual(lerObservacao({ quote_default_notes: "  ", quote_default_notes_enabled: null }), { texto: null, ligada: false });
  assert.deepEqual(lerObservacao(null), { texto: null, ligada: false });

  const nova = observacaoPedida(desligada, { texto: "  Arte aprovada antes da produção.  " });
  assert.ok(nova.ok);
  assert.deepEqual(nova.observacao, { texto: "Arte aprovada antes da produção.", ligada: true }, "texto novo sem dizer nada já liga");

  const soDesligar = observacaoPedida(atual, { ligada: false });
  assert.ok(soDesligar.ok);
  assert.deepEqual(soDesligar.observacao, { texto: "Prazo de 5 dias úteis.", ligada: false }, "desligar guarda o texto");

  const religar = observacaoPedida({ texto: "Prazo.", ligada: false }, { ligada: true });
  assert.ok(religar.ok && religar.observacao.ligada);

  const ligarSemTexto = observacaoPedida(desligada, { ligada: true });
  assert.ok(!ligarSemTexto.ok, "ligar sem ter texto não");

  const textoDesligado = observacaoPedida(atual, { texto: "Outro texto", ligada: false });
  assert.ok(textoDesligado.ok);
  assert.deepEqual(textoDesligado.observacao, { texto: "Outro texto", ligada: false }, "trocar o texto e deixar desligada");

  assert.ok(!observacaoPedida(desligada, { texto: "a".repeat(2001) }).ok);
});

test("comparar e descrever valores guardados", () => {
  assert.ok(mesmoValor({ texto: "a", ligada: true }, { ligada: true, texto: "a" }), "a ordem das chaves não conta");
  assert.ok(!mesmoValor({ texto: "a", ligada: true }, { texto: "a", ligada: false }));
  assert.ok(mesmoValor(null, undefined), "nulo e ausente são o mesmo");
  assert.ok(mesmoValor("Olá", "Olá"));
  assert.ok(!mesmoValor("Olá", null));

  assert.equal(descreverValor("mensagem_do_whatsapp", null), "o texto padrão do sistema");
  assert.equal(descreverValor("mensagem_do_whatsapp", "Olá\n  {{link}}"), "“Olá {{link}}”");
  assert.equal(descreverValor("mensagem_do_whatsapp", "x".repeat(200), 10), `“${"x".repeat(10)}…”`);
  assert.equal(descreverValor("observacao_do_orcamento", { texto: null, ligada: false }), "desligada");
  assert.equal(descreverValor("observacao_do_orcamento", { texto: "Prazo de 5 dias", ligada: true }), "“Prazo de 5 dias”");
  assert.equal(descreverValor("observacao_do_orcamento", { texto: "Prazo", ligada: false }), "desligada: “Prazo”");

  assert.equal(tituloDe("mensagem_do_whatsapp", "quote_share"), "Mensagem do orçamento no WhatsApp");
  assert.equal(tituloDe("mensagem_do_whatsapp", "order_status"), "Mensagem do andamento do pedido no WhatsApp");
  assert.equal(tituloDe("observacao_do_orcamento", null), "Observação padrão do orçamento");
});

test("peneira de contatos: pega link, telefone, e-mail e chave Pix, e deixa passar preço, CEP e datas", () => {
  assert.deepEqual(contatosNoTexto("Olá! Segue o orçamento #{{numero_orcamento}}. Total: {{total}}.{{validade}} {{link}}"), []);
  assert.deepEqual(contatosNoTexto("R$ 1.500,00 em 3x. Prazo de 5 dias úteis. CEP 50000-000. Total 1.234.567,89"), []);
  assert.deepEqual(contatosNoTexto("Entrega entre 03/10/2026 - 10/10/2026, arquivo.pdf, caneca 325ml"), []);
  assert.deepEqual(contatosNoTexto("Instagram @grafica"), [], "arroba de rede social não é contato");

  assert.deepEqual(contatosNoTexto("Pix: 12.345.678/0001-90"), ["12345678000190"], "CNPJ é chave Pix comum");
  assert.deepEqual(contatosNoTexto("WhatsApp (81) 99999-9999 ou 81 3333 4444"), ["81999999999", "8133334444"]);
  assert.deepEqual(contatosNoTexto("Site www.grafica.com.br e bit.ly/abc"), ["grafica.com.br", "bit.ly/abc"]);
  assert.deepEqual(contatosNoTexto("fale@grafica.com.br"), ["fale@grafica.com.br"], "o domínio do e-mail não conta duas vezes");
  assert.deepEqual(contatosNoTexto('<p>Veja <a href="https://pague-aqui.example/pix">aqui</a></p>'), ["pague-aqui.example/pix"], "link escondido no HTML aparece");
  assert.ok(contatosNoTexto("chave 123e4567-e89b-12d3-a456-426614174000").includes("123e4567-e89b-12d3-a456-426614174000"), "chave aleatória do Pix");

  assert.deepEqual(contatosNovos("Pix 12.345.678/0001-90", "Pix: 12345678000190 ou (81) 99999-9999"), ["81999999999"], "o que já estava lá, escrito de outro jeito, não é novo");
  assert.deepEqual(contatosNovos(null, "sem contato nenhum"), []);
  assert.deepEqual(contatosNovos("www.grafica.com.br", "https://grafica.com.br"), [], "o mesmo site com e sem www");

  const recusa = recusaDeContatos(["81999999999", "a.com", "b.com", "c.com"], "no menu WhatsApp");
  assert.ok(recusa.includes("81999999999, a.com, b.com…") && recusa.includes("no menu WhatsApp"));
});

test("mensagens da loja: marcadores próprios, sem cobrar link, e a loja é avisada", () => {
  assert.ok(conferirMensagem("produto", "Oi! Quero saber do {{nome_produto}}").ok);
  const semLink = conferirMensagem("produto", "Oi! Quero saber do {{nome_produto}}");
  assert.ok(semLink.ok && semLink.avisos.length === 0, "a dúvida sobre produto não tem link");
  assert.equal(conferirMensagem("produto", "Pedido {{numero_pedido}}").ok, false, "marcador de outra mensagem é recusado");
  assert.equal(conferirMensagem("cabecalho_do_pedido", "*Pedido {{total}}*").ok, false, "o cabeçalho não tem marcadores");
  const semTotal = conferirMensagem("rodape_do_pedido", "{{resumo_itens}} {{subtotal}}");
  assert.ok(semTotal.ok && semTotal.avisos.some((aviso) => aviso.includes("{{total}}")));
  assert.equal(exemploDaMensagem("produto", MENSAGENS.produto.padrao), "Olá! Tenho interesse no produto Adesivo Vinílico Premium");
  assert.deepEqual(
    QUAIS_MENSAGENS.filter((qual) => MENSAGENS[qual].daLoja),
    ["produto", "cabecalho_do_pedido", "rodape_do_pedido"]
  );
  assert.equal(tituloDe("mensagem_do_whatsapp", "cart_checkout_footer"), "Rodapé do pedido da loja no WhatsApp");
});
