import test from "node:test";
import assert from "node:assert/strict";
import { PRODUCTS, fromQuery, serialize, deserialize, search, filterModel, applyFilter, chips, removeChip, totals, brl, blank, understood, getProduct } from "../src";

test("catálogo: 36 produtos, ids únicos, atributos preenchidos", () => {
  assert.equal(PRODUCTS.length, 36);
  assert.equal(new Set(PRODUCTS.map((p) => p.id)).size, 36);
  assert.ok(PRODUCTS.every((p) => p.cat && Object.keys(p.attrs).length));
});
test("busca por intenção: “celular vento 256gb”", () => {
  const s = fromQuery("celular vento 256gb");
  assert.equal(s.c, "Celulares"); assert.deepEqual(s.brand, ["vento"]); assert.deepEqual(s.attr.storage, ["256"]);
  const r = search(s); assert.equal(r.length, 1); assert.equal(r[0]!.id, 3);
  assert.deepEqual(understood("celular vento 256gb"), ["Celulares", "Vento", "256 GB"]);
});
test("plural e sinônimos", () => {
  assert.ok(search(fromQuery("fones")).length > 0);
  assert.equal(search(fromQuery("laptop")).every((p) => p.art === "p-laptop"), true);
});
test("URL ida e volta preserva o estado", () => {
  const s = applyFilter(applyFilter(blank(), "cat", "Celulares"), "brand", "vento", true);
  const s2 = deserialize(new URLSearchParams(serialize(s)));
  assert.equal(s2.c, "Celulares"); assert.deepEqual(s2.brand, ["vento"]);
  assert.equal(search(s2).length, search(s).length);
});
test("facetas: contagens somam os resultados (sem filtro da própria faceta)", () => {
  const s = applyFilter(blank(), "cat", "Moda");
  const brand = filterModel(s).find((g) => g.id === "brand");
  assert.ok(brand && brand.type === "check");
  const sum = (brand as { options: { count?: number }[] }).options.reduce((a: number, o) => a + (o.count ?? 0), 0);
  assert.equal(sum, search(s).length);
});
test("filtros dinâmicos mudam por categoria", () => {
  const ids = (c: string) => filterModel(applyFilter(blank(), "cat", c)).map((g) => g.id);
  assert.ok(ids("Celulares").includes("aram")); assert.ok(ids("Moda").includes("atamanho")); assert.ok(!ids("Moda").includes("aram"));
});
test("preço, avaliação e chips removíveis", () => {
  let s = applyFilter(blank(), "price", "100,300"); assert.ok(search(s).every((p) => p.priceCents >= 10000 && p.priceCents <= 30000));
  s = applyFilter(s, "rating", "4"); assert.ok(search(s).every((p) => p.rating >= 4));
  assert.equal(chips(s).length, 2); s = removeChip(s, "price|"); assert.equal(chips(s).length, 1);
});
test("ordenação por preço", () => {
  const r = search({ ...blank(), sort: "pa" }); for (let i = 1; i < r.length; i++) assert.ok(r[i - 1]!.priceCents <= r[i]!.priceCents);
});
test("carrinho: frete grátis a partir de R$ 99, cupom e Pix", () => {
  assert.equal(totals([{ priceCents: 5000, q: 1 }]).ship, 1290);
  assert.equal(totals([{ priceCents: 9900, q: 1 }]).ship, 0);
  const t = totals([{ priceCents: 20000, q: 1 }], { coupon: "bemvindo" });
  assert.equal(t.dc, 2000); assert.equal(t.tot, 18000); assert.equal(t.pix, 17100);
  assert.equal(totals([{ priceCents: 20000, q: 1 }], { coupon: "XXX" }).dc, 0);
});
test("dinheiro em BRL e produto por id", () => {
  assert.equal(brl(189900), "R$ 1.899,00"); assert.equal(getProduct("3")!.brand, "vento");
});
import { isEmail, passwordStrength, validateLogin, validateRegister, isCPF, hasErrors } from "../src";
test("conta: e-mail, senha e validação de cadastro", () => {
  assert.ok(isEmail("maria@email.com")); assert.ok(!isEmail("maria@")); assert.ok(!isEmail("maria email@x.com"));
  assert.equal(passwordStrength("abc").ok, false); assert.equal(passwordStrength("Abcdef12").ok, true); assert.equal(passwordStrength("Abcdef12!xyz").score, 4);
  assert.ok(hasErrors(validateLogin({ email: "", senha: "" }))); assert.equal(hasErrors(validateLogin({ email: "a@b.co", senha: "x" })), false);
  const ok = { nome: "Maria Souza", email: "maria@email.com", senha: "Senha1234", confirmar: "Senha1234", aceite: true };
  assert.equal(hasErrors(validateRegister(ok)), false);
  const bad = validateRegister({ ...ok, nome: "Maria", confirmar: "x", aceite: false });
  assert.ok(bad.nome && bad.confirmar && bad.aceite);
});
test("CPF: dígitos verificadores", () => { assert.ok(isCPF("529.982.247-25")); assert.ok(!isCPF("111.111.111-11")); assert.ok(!isCPF("529.982.247-24")); });

import { isCNPJ, isCEP } from "../src";
test("CNPJ e CEP", () => { assert.ok(isCNPJ("11.222.333/0001-81")); assert.ok(!isCNPJ("11.222.333/0001-82")); assert.ok(!isCNPJ("00000000000000")); assert.ok(isCEP("01310-100")); assert.ok(isCEP("01310100")); assert.ok(!isCEP("1310-100")); });
