import { test } from "node:test";
import assert from "node:assert/strict";
import {
  conteudoDaEmbalagem,
  converterCompra,
  formatoValido,
  ocupacaoNaBobina,
  perdaDeRodagem,
} from "./formato-de-compra.ts";

test("o exemplo da resma: 2 resmas de 500 folhas por R$ 45 cada", () => {
  /* A conta que não é viável fazer na calculadora toda compra. */
  const conteudo = conteudoDaEmbalagem({ formato: "resma", conteudoDaEmbalagem: 500 });
  assert.equal(conteudo, 500);

  const compra = converterCompra(2, conteudo, 45);
  assert.deepEqual(compra, { quantidade: 1000, custoUnitario: 0.09 });
});

test("o exemplo da bobina: 1,60 x 50 m por R$ 800", () => {
  const conteudo = conteudoDaEmbalagem({ formato: "bobina", larguraM: 1.6, comprimentoM: 50 });
  assert.equal(conteudo, 80);

  const compra = converterCompra(1, conteudo, 800);
  assert.deepEqual(compra, { quantidade: 80, custoUnitario: 10 });
});

test("chapa deriva das dimensoes: ACM 1,22 x 2,44 por R$ 190", () => {
  const conteudo = conteudoDaEmbalagem({ formato: "chapa", folhaLarguraM: 1.22, folhaAlturaM: 2.44 });
  assert.equal(conteudo, 2.9768);

  const compra = converterCompra(1, conteudo, 190)!;
  assert.equal(compra.quantidade, 2.9768);
  /* 190 / 2,9768 = 63,8269... — quatro casas para o custo nao derrapar em
     insumo barato de consumo alto. */
  assert.equal(compra.custoUnitario, 63.8269);
});

test("rolo, galao, pacote e caixa: conteudo declarado na unidade de consumo", () => {
  assert.equal(conteudoDaEmbalagem({ formato: "rolo", comprimentoM: 500 }), 500);
  assert.equal(conteudoDaEmbalagem({ formato: "galao", conteudoDaEmbalagem: 2000 }), 2000);
  assert.equal(conteudoDaEmbalagem({ formato: "pacote", conteudoDaEmbalagem: 1 }), 1);
  assert.equal(conteudoDaEmbalagem({ formato: "caixa", conteudoDaEmbalagem: 36 }), 36);

  /* Caixa de 36 canecas por R$ 288: cada caneca R$ 8. */
  assert.deepEqual(converterCompra(1, 36, 288), { quantidade: 36, custoUnitario: 8 });
});

test("unidade avulsa: conteudo 1, a compra e o proprio consumo", () => {
  assert.equal(conteudoDaEmbalagem({ formato: "unidade" }), 1);
  assert.deepEqual(converterCompra(500, 1, 0.4), { quantidade: 500, custoUnitario: 0.4 });
});

test("conteudo desconhecido nao converte: melhor pedir o dado que inventar um", () => {
  assert.equal(conteudoDaEmbalagem({ formato: "resma" }), 0);
  assert.equal(conteudoDaEmbalagem({ formato: "bobina", larguraM: 1.6 }), 0);
  assert.equal(converterCompra(2, 0, 45), null);
  assert.equal(converterCompra(0, 500, 45), null);
  assert.equal(converterCompra(2, 500, NaN), null);
});

test("formato desconhecido cai em unidade, nunca estoura", () => {
  assert.equal(formatoValido("bobina"), "bobina");
  assert.equal(formatoValido("banana"), "unidade");
  assert.equal(formatoValido(null), "unidade");
});

test("o exemplo do banner: 1,00 x 0,70 na bobina de 1,60 ocupa 1,12 m2", () => {
  /* A impressora ocupa a largura inteira. O sistema escolhe a orientacao que
     gasta menos: o lado de 1,00 na largura, 0,70 correndo no comprimento. */
  assert.equal(ocupacaoNaBobina(1.6, 1.0, 0.7), 1.12);
  /* 1,12 para uma peca de 0,70 m²: 60% de perda — calculada, nao chutada. */
  assert.equal(perdaDeRodagem(1.6, 1.0, 0.7), 60);
});

test("peca que aproveita a largura quase toda perde quase nada", () => {
  /* 1,50 x 3,00 na bobina de 1,60: rodando o 1,50 na largura, 4,8 m² para
     4,5 m² de peca. */
  assert.equal(ocupacaoNaBobina(1.6, 1.5, 3), 4.8);
  assert.equal(perdaDeRodagem(1.6, 1.5, 3), 6.7);
});

test("peca maior que a bobina nos dois lados sai em faixas de emenda", () => {
  /* Fachada 5 x 3 na bobina de 1,60: duas faixas de 1,60 x 5. */
  assert.equal(ocupacaoNaBobina(1.6, 5, 3), 16);
  assert.equal(perdaDeRodagem(1.6, 5, 3), 6.7);
});

test("a orientacao otima e escolhida sozinha", () => {
  /* 0,70 x 1,00 e 1,00 x 0,70 sao a mesma peca: mesma ocupacao. */
  assert.equal(ocupacaoNaBobina(1.6, 0.7, 1.0), ocupacaoNaBobina(1.6, 1.0, 0.7));
});

test("sem largura de bobina ou sem medida, ocupacao zero: nao inventa", () => {
  assert.equal(ocupacaoNaBobina(0, 1, 0.7), 0);
  assert.equal(ocupacaoNaBobina(1.6, 0, 0.7), 0);
  assert.equal(perdaDeRodagem(0, 1, 0.7), 0);
});
