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

import {
  centavos,
  ehId,
  escolherPorNome,
  formaNoBanco,
  intervaloDoMes,
  mesAnterior,
  nomeDaForma,
  nomeDoMes,
  normalizarNome,
  porcento,
  situacaoDaContaAPagar,
  situacaoDaContaAReceber,
} from "./ferramentas/financeiro-completo-apoio.ts";

const CONTAS = [
  { id: "e7641366-1e7f-40af-97a6-b5264adaeb6c", name: "Conta principal", bank_name: "Itaú" },
  { id: "7b6f2d28-04af-45ea-8619-6498b47d4136", name: "Caixa da loja", bank_name: null },
  { id: "30fc6dc7-5091-4f0f-9d9b-8b1698d37e23", name: "Mercado Pago", bank_name: null },
];
const nomes = (conta: (typeof CONTAS)[number]) => [conta.name, conta.bank_name];

test("forma de pagamento: o nome falado vira o código do banco", () => {
  assert.equal(formaNoBanco("dinheiro"), "cash");
  assert.equal(formaNoBanco("cartao_de_credito"), "credit_card");
  assert.equal(formaNoBanco("pix"), "pix");
  assert.equal(formaNoBanco("boleto"), null);
  assert.equal(nomeDaForma("cash"), "dinheiro");
  assert.equal(nomeDaForma(null), "sem forma informada");
});

test("nome sem acento e sem maiúscula", () => {
  assert.equal(normalizarNome("  Água & Energia "), "agua energia");
  assert.ok(ehId(CONTAS[0].id));
  assert.ok(!ehId("Conta principal"));
});

test("acha a conta pelo nome, pelo banco, por parte do nome ou pelo id", () => {
  assert.equal((escolherPorNome(CONTAS, "caixa da loja", nomes) as { item: { id: string } }).item.id, CONTAS[1].id);
  assert.equal((escolherPorNome(CONTAS, "itau", nomes) as { item: { id: string } }).item.id, CONTAS[0].id);
  assert.equal((escolherPorNome(CONTAS, "mercado", nomes) as { item: { id: string } }).item.id, CONTAS[2].id);
  assert.equal((escolherPorNome(CONTAS, "pix no Mercado Pago", nomes) as { item: { id: string } }).item.id, CONTAS[2].id);
  assert.equal((escolherPorNome(CONTAS, CONTAS[0].id.toUpperCase(), nomes) as { item: { id: string } }).item.id, CONTAS[0].id);
  assert.equal(escolherPorNome(CONTAS, "bradesco", nomes).tipo, "nenhum");
  assert.equal(escolherPorNome(CONTAS, "00000000-0000-4000-8000-000000000000", nomes).tipo, "nenhum");
});

test("nome que serve a mais de uma conta não é chute", () => {
  const contas = [...CONTAS, { id: "11111111-1111-4111-8111-111111111111", name: "Conta reserva", bank_name: null }];
  const escolha = escolherPorNome(contas, "conta", nomes);
  assert.equal(escolha.tipo, "varios");
  /* Nome igual ganha de parecido. */
  assert.equal(escolherPorNome(contas, "conta principal", nomes).tipo, "achou");
});

test("situação das contas como a tela mostra", () => {
  assert.equal(situacaoDaContaAPagar("PENDING", "2026-10-01", "2026-10-14"), "vencida");
  assert.equal(situacaoDaContaAPagar("PENDING", "2026-10-20", "2026-10-14"), "em aberto");
  assert.equal(situacaoDaContaAPagar("OVERDUE", "2026-10-20", "2026-10-14"), "vencida");
  assert.equal(situacaoDaContaAPagar("PAID", "2026-10-01", "2026-10-14"), "paga");
  assert.equal(situacaoDaContaAReceber("PARTIALLY_PAID", "2026-10-01", "2026-10-14"), "recebida em parte, vencida");
  assert.equal(situacaoDaContaAReceber("CANCELED", "2026-10-01", "2026-10-14"), "cancelada");
});

test("mês: intervalo, mês anterior e nome", () => {
  assert.deepEqual(intervaloDoMes("2026-02"), { inicio: "2026-02-01", fim: "2026-02-28", depois: "2026-03-01" });
  assert.deepEqual(intervaloDoMes("2026-12"), { inicio: "2026-12-01", fim: "2026-12-31", depois: "2027-01-01" });
  assert.equal(intervaloDoMes("2026-13"), null);
  assert.equal(intervaloDoMes("outubro"), null);
  assert.equal(mesAnterior("2026-01"), "2025-12");
  assert.equal(nomeDoMes("2026-09"), "setembro de 2026");
});

test("dinheiro em centavos e porcentagem", () => {
  assert.equal(centavos(0.1 + 0.2), 30);
  assert.equal(centavos(10.005), 1001);
  assert.equal(porcento(1, 3), 33.3);
  assert.equal(porcento(5, 0), 0);
});
