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

import {
  contaDoCorte,
  cupomValeAgora,
  condicoesDoCupom,
  dadosDasPerguntas,
  dadosPedidos,
  descontoDoCupom,
  enderecoDoMapa,
  enderecoDoPlayer,
  instanteDeBrasilia,
  juntarVisto,
  lancamentos,
  lerFaixa,
  lerImagemComPontos,
  lerListaDosVistos,
  lerOferta,
  lerPerguntas,
  lerTextoSimples,
  lerVideo,
  liveDaVez,
  montarEndereco,
  ofertaNoAr,
  posicaoPeloTeclado,
  precoComDesconto,
  precoDoCartao,
  relogioDaContagem,
  textoDeBrasilia,
  textoPuro,
} from "./widgets-da-home.ts";
import { modoDaSecao, secoesParaOsTemasAntigos } from "./pagina-inicial.ts";

test("hora de Brasília vira o instante certo (UTC-3)", () => {
  assert.equal(new Date(instanteDeBrasilia("2026-10-20T18:00") as number).toISOString(), "2026-10-20T21:00:00.000Z");
  assert.equal(textoDeBrasilia(Date.parse("2026-10-20T21:00:00Z")), "2026-10-20T18:00");
  assert.equal(instanteDeBrasilia("ontem"), null);
  assert.equal(instanteDeBrasilia("2026-13-01T10:00"), null);
});

test("contagem regressiva no formato da loja", () => {
  assert.equal(relogioDaContagem((2 * 3600 + 14 * 60 + 33) * 1000), "02:14:33");
  assert.equal(relogioDaContagem((26 * 3600 + 5) * 1000), "1d 02:00:05");
  assert.equal(relogioDaContagem(-5000), "00:00:00");
});

test("oferta só fica no ar com data e antes do fim", () => {
  const agora = Date.parse("2026-10-16T12:00:00Z");
  const oferta = lerOferta({ produtos: ["11111111-1111-1111-1111-111111111111", "x"], termina_em: "2026-10-16T18:00" });
  assert.deepEqual(oferta.produtos, ["11111111-1111-1111-1111-111111111111"]);
  assert.equal(ofertaNoAr(oferta, agora), true);
  assert.equal(ofertaNoAr(oferta, Date.parse("2026-10-16T21:00:01Z")), false);
  assert.equal(ofertaNoAr(lerOferta({ produtos: [] }), agora), false);
});

test("corte de produção: hoje antes da hora, próximo dia útil depois e no fim de semana", () => {
  /* Quinta 15/10/2026, 10h em Brasília. */
  const quinta = Date.parse("2026-10-15T13:00:00Z");
  const hoje = contaDoCorte("16:00", quinta);
  assert.equal(hoje?.hoje, true);
  assert.equal(hoje && hoje.hoje ? hoje.faltaMs : 0, 6 * 3600 * 1000);
  /* Quinta 17h: lote de amanhã (sexta). */
  const depois = contaDoCorte("16:00", Date.parse("2026-10-15T20:00:00Z"));
  assert.equal(depois?.hoje, false);
  assert.equal(depois && !depois.hoje ? depois.amanha : null, true);
  /* Sexta 17h: segunda. */
  const sexta = contaDoCorte("16:00", Date.parse("2026-10-16T20:00:00Z"));
  assert.equal(sexta && !sexta.hoje ? sexta.proximoDia : "", "segunda-feira");
  /* Sábado de manhã: nunca "hoje". */
  const sabado = contaDoCorte("16:00", Date.parse("2026-10-17T12:00:00Z"));
  assert.equal(sabado?.hoje, false);
  assert.equal(contaDoCorte("25:00", quinta), null);
});

test("cupom: validade e texto do desconto", () => {
  const agora = Date.parse("2026-10-16T12:00:00Z");
  const cupom = { id: "c", code: "BEMVINDO", type: "percent", value: 10, min_total: 150, min_items: null, active: true, starts_at: null, ends_at: "2026-10-31T02:59:00Z" };
  assert.equal(cupomValeAgora(cupom, agora), true);
  assert.equal(cupomValeAgora({ ...cupom, active: false }, agora), false);
  assert.equal(cupomValeAgora({ ...cupom, ends_at: "2026-10-01T00:00:00Z" }, agora), false);
  assert.equal(descontoDoCupom(cupom), "10% OFF");
  assert.match(descontoDoCupom({ type: "fixed", value: 20 }), /R\$\s*20,00 OFF/);
  const condicoes = condicoesDoCupom(cupom, true);
  assert.match(condicoes[0], /150,00/);
  assert.equal(condicoes[1], "Válido até 30/10 às 23h59");
});

test("texto do lojista: negrito, link seguro, lista; nada de HTML", () => {
  const blocos = lerTextoSimples("Olá **mundo** <b>x</b>\n[site](https://a.com) [mau](javascript:alert(1))\n\n- um\n- dois");
  assert.equal(blocos.length, 2);
  const [p] = blocos;
  assert.equal(p.tipo, "paragrafo");
  if (p.tipo !== "paragrafo") return;
  assert.deepEqual(p.linhas[0], [
    { tipo: "texto", valor: "Olá " },
    { tipo: "negrito", valor: "mundo" },
    { tipo: "texto", valor: " <b>x</b>" },
  ]);
  assert.equal(p.linhas[1][0].tipo, "link");
  assert.deepEqual(p.linhas[1][2], { tipo: "texto", valor: "mau" });
  assert.equal(blocos[1].tipo, "lista");
  assert.equal(textoPuro("**a** [b](/x)"), "a b");
});

test("perguntas frequentes viram FAQPage sem marcação", () => {
  const lidas = lerPerguntas({ itens: [{ pergunta: "Entrega?", resposta: "**Sim**, em 2 dias." }, { pergunta: "", resposta: "x" }] });
  assert.equal(lidas.itens.length, 1);
  const dados = dadosDasPerguntas([lidas]) as { mainEntity: Array<{ name: string; acceptedAnswer: { text: string } }> };
  assert.equal(dados.mainEntity[0].name, "Entrega?");
  assert.equal(dados.mainEntity[0].acceptedAnswer.text, "Sim, em 2 dias.");
  assert.equal(dadosDasPerguntas([lerPerguntas({})]), null);
});

test("vídeo só do YouTube (sem cookie) e do Vimeo (sem rastreio)", () => {
  const yt = lerVideo({ url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ" });
  assert.ok(yt.link);
  assert.match(enderecoDoPlayer(yt.link!), /^https:\/\/www\.youtube-nocookie\.com\/embed\/dQw4w9WgXcQ\?/);
  const vimeo = lerVideo({ url: "vimeo.com/123456789" });
  assert.match(enderecoDoPlayer(vimeo.link!), /dnt=1/);
  assert.equal(lerVideo({ url: "https://evil.com/v.mp4" }).link, null);
});

test("vistos recentemente: lista limpa, sem repetir, com teto", () => {
  const id = "11111111-1111-1111-1111-111111111111";
  assert.deepEqual(lerListaDosVistos("{lixo"), []);
  assert.deepEqual(juntarVisto([id, "22222222-2222-2222-2222-222222222222"], "22222222-2222-2222-2222-222222222222")[0], "22222222-2222-2222-2222-222222222222");
  assert.equal(juntarVisto([], "<script>").length, 0);
  const muitos = Array.from({ length: 30 }, (_, i) => `aaaaaaaa-0000-0000-0000-${String(i).padStart(12, "0")}`);
  assert.equal(juntarVisto(muitos, id).length, 20);
});

test("faixa, pontos e barra: valores sempre dentro do permitido", () => {
  const faixa = lerFaixa({ itens: ["Frete grátis", "", 3], cor_de_fundo: "red; x", cor_do_texto: "#fff" }, "#7c3aed");
  assert.deepEqual(faixa.itens, ["Frete grátis", "3"]);
  assert.equal(faixa.fundo, "#7c3aed");
  const pontos = lerImagemComPontos({ imagem: "javascript:x", pontos: [{ x: 150, y: -3, produto_id: "11111111-1111-1111-1111-111111111111" }, { x: "a", y: 1 }] });
  assert.equal(pontos.imagem, "");
  assert.deepEqual(pontos.pontos, [{ x: 100, y: 0, produtoId: "11111111-1111-1111-1111-111111111111" }]);
  assert.equal(posicaoPeloTeclado(50, "ArrowLeft"), 45);
  assert.equal(posicaoPeloTeclado(98, "ArrowRight"), 100);
  assert.equal(posicaoPeloTeclado(50, "a"), null);
});

test("preço dos cartões segue o card da loja", () => {
  assert.equal(precoDoCartao({ price: 10, price_on_request: true }, "Consulte").texto, "Consulte");
  assert.match(precoDoCartao({ price: 10, product_price_tiers: [{ unit_price: 8, active: true }] }).texto, /^A partir de R\$\s*8,00$/);
  assert.equal(precoDoCartao({ price: 10, unit_type: "square_meter" }).texto, "Preço sob medida");
  assert.equal(precoComDesconto(100, { discount_type: "percentage", discount_value: 10 }), 90);
  assert.equal(precoComDesconto(10, { discount_type: "fixed", discount_value: 50 }), 0);
});

test("endereço montado e mapa sem chave", () => {
  const e = montarEndereco({ rua: "Rua A", numero: "10", bairro: "Centro", cidade: "Campinas", estado: "SP", cep: "13000-000" });
  assert.deepEqual(e?.linhas, ["Rua A, 10", "Centro, Campinas - SP", "CEP 13000-000"]);
  assert.match(enderecoDoMapa(e!.busca), /^https:\/\/www\.google\.com\/maps\?q=.*output=embed/);
  assert.equal(montarEndereco({}), null);
});

test("lives: a no ar vem antes da agendada", () => {
  const agora = Date.parse("2026-10-16T12:00:00Z");
  const base = { duracao_min: 60, espera_min: 15, iniciada_em: null, categoria: "venda" as const, capa: null, titulo: "x" };
  const vez = liveDaVez(
    [
      { ...base, id: "a", status: "agendada", comeca_em: "2026-10-17T12:00:00Z" },
      { ...base, id: "b", status: "ao_vivo", comeca_em: "2026-10-16T11:50:00Z", iniciada_em: "2026-10-16T11:55:00Z" },
    ],
    agora
  );
  assert.equal(vez?.live.id, "b");
  assert.equal(vez?.momento, "ao_vivo");
  assert.equal(liveDaVez([], agora), null);
});

test("os blocos são modos da página e pedem só os dados que usam", () => {
  assert.equal(modoDaSecao({ config: { mode: "faq" }, section_type: "manual_products" }), "faq");
  const pedido = dadosPedidos([{ config: { mode: "coupon_highlight" } }, { config: { mode: "auto_list", lista: "mais_vendidos", dias: 7 } }, { config: { mode: "manual_products" } }]);
  assert.deepEqual(pedido, { cupons: true, lives: false, combos: false, local: false, maisVendidos: [7] });
});

test("lista automática vira seção de produtos nos temas Padrão e Vitrine", () => {
  const produtos = [
    { id: "a", created_at: "2026-01-01" },
    { id: "b", created_at: "2026-10-01" },
    { id: "c", created_at: "2026-05-01" },
  ];
  const [novos, vendidos, vazia] = secoesParaOsTemasAntigos(
    [
      { config: { mode: "auto_list", lista: "lancamentos", quantidade: 2 }, products: [] },
      { config: { mode: "auto_list", lista: "mais_vendidos", dias: 30 }, products: [] },
      { config: { mode: "auto_list", lista: "mais_vendidos", dias: 90 }, products: [] },
    ],
    produtos,
    [],
    { maisVendidos: { "30": ["c", "sumiu", "a"] } }
  );
  assert.deepEqual(novos.products?.map((p) => (p as { id: string }).id), ["b", "c"]);
  assert.equal((novos.config as { mode: string }).mode, "manual_products");
  assert.deepEqual(vendidos.products?.map((p) => (p as { id: string }).id), ["c", "a"]);
  assert.equal((vazia.config as { mode: string }).mode, "auto_list");
  assert.deepEqual(lancamentos([{ id: 1 }], 3), [{ id: 1 }]);
});
