import { test } from "node:test";
import assert from "node:assert/strict";
import { janelaDoMesAnterior, nomeDoMes, parteDoTotal, somaDasFatias, variacaoDoMes } from "./parte-do-total.ts";

/*
  A Visao Geral do Financeiro mostrava "Pix: 984,7% do total". Estes testes
  usam os numeros reais daquela tela, da empresa de demonstracao.
*/

const METODOS_DA_AURORA = [
  { method: "pix", amount: 120838.5 },
  { method: "cash", amount: 27528.84 },
  { method: "credit_card", amount: 23226.95 },
  { method: "transfer", amount: 9637.7 },
  { method: "unknown", amount: 6860.0 },
  { method: "debit_card", amount: 5058.35 },
];

test("o defeito de antes: dividir o historico pelo mes da mais de 100%", () => {
  /* Registro do que acontecia, para ninguem achar que 984,7% era exagero. */
  const recebidoNoMes = 12271.35;
  assert.equal(parteDoTotal(120838.5, recebidoNoMes), "984,7%");
});

test("dividindo pela soma das proprias fatias, o Pix pesa o que pesa", () => {
  const total = somaDasFatias(METODOS_DA_AURORA);
  assert.equal(parteDoTotal(120838.5, total), "62,6%");
});

test("as fatias somam 100%, que e a prova de que o todo esta certo", () => {
  const total = somaDasFatias(METODOS_DA_AURORA);
  const soma = METODOS_DA_AURORA.reduce((s, m) => s + (m.amount / total) * 100, 0);
  assert.ok(Math.abs(soma - 100) < 0.0001, `somaram ${soma}`);
});

test("nenhuma fatia passa de 100% quando o todo e a soma delas", () => {
  const total = somaDasFatias(METODOS_DA_AURORA);
  for (const m of METODOS_DA_AURORA) {
    const valor = Number(parteDoTotal(m.amount, total).replace("%", "").replace(",", "."));
    assert.ok(valor <= 100, `${m.method} deu ${valor}%`);
  }
});

test("escreve com virgula, como o resto da tela", () => {
  /* toFixed da "62.6"; ao lado de "R$ 120.838,50" o ponto parece outro numero. */
  assert.match(parteDoTotal(1, 3), /^33,3%$/);
});

test("sem total nao inventa proporcao", () => {
  assert.equal(parteDoTotal(50, 0), "—");
  assert.equal(parteDoTotal(50, NaN), "—");
  assert.equal(parteDoTotal(50, -10), "—");
  assert.equal(somaDasFatias(null), 0);
  assert.equal(somaDasFatias([{ amount: null }, { amount: 10 }]), 10);
});


/* ------------------------------------------- o cartao "Recebido no Mes" */

test("a variacao e calculada, e nao aquele +12% fixo de antes", () => {
  assert.deepEqual(variacaoDoMes(112, 100), { value: "+12%", isPositive: true });
  assert.deepEqual(variacaoDoMes(80, 100), { value: "-20%", isPositive: false });
  /* O mesmo valor dos dois lados: nem cresceu nem caiu. */
  assert.deepEqual(variacaoDoMes(100, 100), { value: "0%", isPositive: true });
});

test("sem mes anterior nao existe percentual para mostrar", () => {
  /* Empresa nova, ou mes anterior sem nenhuma entrada. "+100%" seria mentira. */
  assert.equal(variacaoDoMes(500, 0), null);
  assert.equal(variacaoDoMes(500, NaN), null);
});

test("o nome do mes sai da data, e nao de um Janeiro 2026 escrito a mao", () => {
  assert.equal(nomeDoMes(new Date(2026, 8, 16)), "Setembro de 2026");
  assert.equal(nomeDoMes(new Date(2027, 0, 1)), "Janeiro de 2027");
});

test("compara com o MESMO PEDACO do mes anterior, e nao com ele inteiro", () => {
  /* O erro que esta funcao evita: no dia 16 de setembro, os 16 dias do mes
     contra os 31 de agosto davam -53% para a empresa de demonstracao. */
  const agora = new Date(2026, 8, 16, 9, 0, 0);
  const { inicio, fim } = janelaDoMesAnterior(agora);
  assert.equal(inicio.getTime(), new Date(2026, 7, 1, 0, 0, 0).getTime());
  assert.equal(fim.getTime(), new Date(2026, 7, 16, 9, 0, 0).getTime());
});

test("no dia 1 a janela e quase vazia, e nao o mes passado inteiro", () => {
  /* Sem isso o cartao mostraria quase -100% no primeiro dia de todo mes. */
  const agora = new Date(2026, 8, 1, 8, 0, 0);
  const { inicio, fim } = janelaDoMesAnterior(agora);
  assert.equal(inicio.getTime(), new Date(2026, 7, 1, 0, 0, 0).getTime());
  assert.equal(fim.getTime(), new Date(2026, 7, 1, 8, 0, 0).getTime());
});

test("mes anterior mais curto: a janela para no fim dele", () => {
  /* 31 de marco contra fevereiro, que nao tem dia 31. */
  const agora = new Date(2026, 2, 31, 12, 0, 0);
  const { fim } = janelaDoMesAnterior(agora);
  assert.equal(fim.getTime(), new Date(2026, 2, 1, 0, 0, 0).getTime(), "nao invade marco");
});

test("janeiro compara com dezembro do ano anterior", () => {
  const { inicio } = janelaDoMesAnterior(new Date(2027, 0, 10));
  assert.equal(inicio.getTime(), new Date(2026, 11, 1).getTime());
});
