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

import {
  corDoRotulo,
  corPrecisaDeAnel,
  estiloDoAtributo,
  nomeLimpo,
  pareceCampoTecnico,
  variacoesDaVitrine,
} from "./variacoes-da-loja.ts";

/*
  A decisão de como desenhar uma variação mora fora da tela de propósito: é
  ela que decide se 4.271 atributos de produção viram bolinha, chip, lista ou
  nada. Testar pelo navegador exigiria um produto de cada formato — e o que
  quebra aqui quebra calado, numa vitrine de cliente.
*/

const opcao = (label: string, extras: Record<string, unknown> = {}) => ({ label, price: 0, ...extras });

test("cor comum vira a tinta certa", () => {
  assert.equal(corDoRotulo("Preto")?.fundo, "#101014");
  assert.equal(corDoRotulo("azul")?.fundo, "#1f5fd0");
  /* Gênero não muda a tinta: a loja escreve "Preta" e "Vermelha". */
  assert.equal(corDoRotulo("Preta")?.fundo, corDoRotulo("Preto")?.fundo);
  assert.equal(corDoRotulo("Vermelha")?.fundo, corDoRotulo("Vermelho")?.fundo);
});

test("cor terminada em A não é confundida com masculino", () => {
  /* O primeiro desenho virava "laranja" em "laranjo" e "cinza" em "cinzo" —
     as duas saíam cinza-claro de "cor desconhecida" na vitrine. */
  assert.equal(corDoRotulo("Laranja")?.fundo, "#f1701f");
  assert.equal(corDoRotulo("Cinza")?.fundo, "#8b8f98");
});

test("modificador escurece, clareia e satura a partir da base", () => {
  const claro = corDoRotulo("Azul claro");
  const escuro = corDoRotulo("Azul escuro");
  const bebe = corDoRotulo("Azul bebê");
  assert.ok(claro && escuro && bebe);
  assert.notEqual(claro.fundo, escuro.fundo);
  /* Bebê é mais claro que claro; escuro é mais escuro que os dois. */
  const luz = (hex: string) => parseInt(hex.slice(1, 3), 16) + parseInt(hex.slice(3, 5), 16) + parseInt(hex.slice(5, 7), 16);
  assert.ok(luz(bebe.fundo) > luz(claro.fundo));
  assert.ok(luz(escuro.fundo) < luz(claro.fundo));
});

test("metálico brilha, transparente é xadrez e sortido é arco-íris", () => {
  assert.equal(corDoRotulo("Dourado")?.tipo, "brilho");
  assert.equal(corDoRotulo("Transparente")?.tipo, "xadrez");
  assert.equal(corDoRotulo("Gel colorida")?.tipo, "arcoiris");
});

test("o que não é cor não vira bolinha", () => {
  assert.equal(corDoRotulo("Slim 13 cm"), null);
  assert.equal(corDoRotulo("Soft Touch emborrachado"), null);
  assert.equal(corDoRotulo(""), null);
});

test("cor clara ganha anel para não sumir no branco da vitrine", () => {
  assert.equal(corPrecisaDeAnel({ tipo: "chapada", fundo: "#ffffff" }), true);
  assert.equal(corPrecisaDeAnel({ tipo: "chapada", fundo: "#101014" }), false);
});

test("o dois-pontos da importação sai do nome", () => {
  assert.equal(nomeLimpo("Tamanho:"), "Tamanho");
  assert.equal(nomeLimpo("Cor: "), "Cor");
  assert.equal(nomeLimpo("Acabamento"), "Acabamento");
});

test("atributo de cor vira bolinha; de sabor, não", () => {
  const cor = { name: "Cor" };
  assert.equal(estiloDoAtributo(cor, [opcao("Preto"), opcao("Azul"), opcao("Verde")].map(normalizar)), "cores");

  /* "Uva" e "Limão" ficam fora do dicionário justamente para isto: num
     atributo Sabor, bolinha roxa não diz nada. */
  const sabor = { name: "Sabor" };
  assert.equal(estiloDoAtributo(sabor, [opcao("Uva"), opcao("Limão"), opcao("Morango")].map(normalizar)), "botoes");
});

test("a escolha do lojista vence o automático", () => {
  const cor = { name: "Cor", display_style: "botoes" };
  assert.equal(estiloDoAtributo(cor, [opcao("Preto"), opcao("Azul")].map(normalizar)), "botoes");

  const tamanho = { name: "Tamanho", display_style: "cores" };
  assert.equal(estiloDoAtributo(tamanho, [opcao("P"), opcao("M")].map(normalizar)), "cores");
});

test("cor pintada à mão liga a bolinha mesmo sem o nome ajudar", () => {
  const estampa = { name: "Estampa" };
  const opcoes = [normalizar(opcao("Onça", { swatch: "#c98b2e" })), normalizar(opcao("Zebra"))];
  assert.equal(estiloDoAtributo(estampa, opcoes), "cores");
});

test("muitas opções viram lista com busca", () => {
  const muitas = Array.from({ length: 12 }, (_, i) => normalizar(opcao(`Modelo ${i + 1}`)));
  assert.equal(estiloDoAtributo({ name: "Modelo" }, muitas), "lista");
  assert.equal(estiloDoAtributo({ name: "Modelo" }, muitas.slice(0, 5)), "botoes");
});

test("a maioria com foto vira miniatura", () => {
  const comFoto = [
    normalizar(opcao("Onça", { image_id: "a" })),
    normalizar(opcao("Zebra", { image_id: "b" })),
    normalizar(opcao("Liso")),
  ];
  assert.equal(estiloDoAtributo({ name: "Estampa" }, comFoto), "miniaturas");
});

test("uma opção só e sem preço é informação, não escolha", () => {
  const { escolhas, informativos } = variacoesDaVitrine([
    { name: "Acabamento", options: [opcao("Fosco")], position: 0 },
    { name: "Cor", options: [opcao("Preto"), opcao("Azul")], position: 1 },
  ]);
  assert.equal(informativos.length, 1);
  assert.equal(informativos[0].nome, "Acabamento");
  assert.equal(escolhas.length, 1);
  assert.equal(escolhas[0].nome, "Cor");
});

test("uma opção só, mas com preço, continua sendo escolha", () => {
  const { escolhas, informativos } = variacoesDaVitrine([
    { name: "Embalagem", options: [opcao("Caixa presente", { price: 4 })], position: 0 },
  ]);
  assert.equal(informativos.length, 0);
  assert.equal(escolhas.length, 1);
});

test("o que o lojista escondeu não volta pela vitrine", () => {
  const { escolhas, informativos } = variacoesDaVitrine([
    { name: "ncm_8", options: [opcao("39269090")], show_in_store: false, position: 0 },
    { name: "Cor", options: [opcao("Preto"), opcao("Azul")], position: 1 },
  ]);
  assert.equal(escolhas.length, 1);
  assert.equal(informativos.length, 0);
});

test("atributo sem opção nenhuma não desenha nada", () => {
  const { escolhas, informativos } = variacoesDaVitrine([{ name: "Vazio", options: [], position: 0 }]);
  assert.equal(escolhas.length + informativos.length, 0);
});

test("as opções saem na ordem que o lojista deixou", () => {
  const { escolhas } = variacoesDaVitrine([
    {
      name: "Tamanho",
      options: [opcao("Grande", { position: 2 }), opcao("Pequeno", { position: 0 }), opcao("Médio", { position: 1 })],
      position: 0,
    },
  ]);
  assert.deepEqual(escolhas[0].opcoes.map((o) => o.label), ["Pequeno", "Médio", "Grande"]);
});

test("campo de planilha é reconhecido para o admin sugerir", () => {
  assert.equal(pareceCampoTecnico("ncm_8", 1), true);
  assert.equal(pareceCampoTecnico("id_fornecedor", 1), true);
  assert.equal(pareceCampoTecnico("COFINS", 1), true);
  assert.equal(pareceCampoTecnico("origem_0_a_8", 1), true);
  /* Cor e Tamanho nunca podem cair nesta rede. */
  assert.equal(pareceCampoTecnico("Cor", 12), false);
  assert.equal(pareceCampoTecnico("Tamanho", 5), false);
  /* Um nome de planilha com várias opções é escolha de verdade: não sugere. */
  assert.equal(pareceCampoTecnico("modelo_2024", 6), false);
});

/* O normalizador da lib é interno; aqui só se monta a opção como ela sai de lá. */
function normalizar(bruta: { label: string; price?: number; swatch?: string; image_id?: string }) {
  return {
    id: null,
    label: bruta.label,
    preco: bruta.price ?? 0,
    precoPorPeca: true,
    estoque: null,
    obrigatoria: false,
    posicao: 0,
    imageId: bruta.image_id ?? null,
    swatch: bruta.swatch ?? null,
  };
}
