import { test } from "node:test";
import assert from "node:assert/strict";
import { custoHoraDeMaquina, custoHoraDeTrabalho } from "./custo-por-hora.ts";

/* Os mesmos casos que rodei contra as funções do banco. Se as duas contas
   divergirem, a prévia da tela mente sobre o que vai ser gravado. */

test("máquina: depreciação + manutenção pelas horas, mais energia por hora", () => {
  /* Plotter de 25 mil, 5 anos, residual 2 mil, 1,5 kW, 300 de manutenção,
     80 horas por mês. Conferido à mão: (23000/60 + 300)/80 + 1,5×0,95 */
  const r = custoHoraDeMaquina({
    valorDeCompra: 25000, vidaUtilAnos: 5, valorResidual: 2000,
    potenciaKw: 1.5, custoKwh: 0.95, manutencaoMensal: 300, horasProdutivasMes: 80,
  });
  assert.equal(r, 9.97);
});

test("o divisor é onde se erra: 220 horas fazem a mesma máquina custar metade", () => {
  const comum = { valorDeCompra: 25000, vidaUtilAnos: 5, valorResidual: 2000,
                  potenciaKw: 1.5, custoKwh: 0.95, manutencaoMensal: 300 };
  assert.equal(custoHoraDeMaquina({ ...comum, horasProdutivasMes: 80 }), 9.97);
  assert.equal(custoHoraDeMaquina({ ...comum, horasProdutivasMes: 220 }), 4.53);
});

test("sem horas produtivas não inventa número", () => {
  for (const horas of [0, null, undefined, -5, "abc"]) {
    assert.equal(
      custoHoraDeMaquina({ valorDeCompra: 25000, vidaUtilAnos: 5, horasProdutivasMes: horas }),
      null,
      `horas ${String(horas)} deveriam impedir o cálculo`
    );
  }
});

test("máquina quitada e sem vida útil informada ainda tem custo de operar", () => {
  /* Depreciação zero não significa hora de graça: energia e manutenção
     continuam existindo. */
  const r = custoHoraDeMaquina({
    potenciaKw: 2, custoKwh: 1, manutencaoMensal: 200, horasProdutivasMes: 100,
  });
  assert.equal(r, 4);
});

test("residual maior que o valor de compra não vira depreciação negativa", () => {
  const r = custoHoraDeMaquina({
    valorDeCompra: 10000, valorResidual: 15000, vidaUtilAnos: 5, horasProdutivasMes: 100,
  });
  assert.equal(r, 0);
});

test("trabalho: salário com encargos pelas horas produtivas", () => {
  assert.equal(custoHoraDeTrabalho({ salarioMensal: 2000, encargosPct: 70, horasProdutivasMes: 150 }), 22.67);
});

test("ignorar encargos subestima a hora em 41%", () => {
  const comEncargos = custoHoraDeTrabalho({ salarioMensal: 2000, encargosPct: 70, horasProdutivasMes: 150 })!;
  const sem = custoHoraDeTrabalho({ salarioMensal: 2000, encargosPct: 0, horasProdutivasMes: 150 })!;
  assert.equal(sem, 13.33);
  assert.ok(sem < comEncargos * 0.6, "a diferença precisa ser grande o bastante para importar");
});

test("horas contratadas em vez de produtivas barateiam a hora", () => {
  assert.equal(custoHoraDeTrabalho({ salarioMensal: 2000, encargosPct: 70, horasProdutivasMes: 220 }), 15.45);
});

test("a eficiencia encarece a hora util: 80% custa 25% a mais", () => {
  /* O salario e o mesmo; rendem menos horas que produzem. */
  const cheia = custoHoraDeTrabalho({ salarioMensal: 2000, encargosPct: 70, horasProdutivasMes: 150, eficienciaPct: 100 });
  const oitenta = custoHoraDeTrabalho({ salarioMensal: 2000, encargosPct: 70, horasProdutivasMes: 150, eficienciaPct: 80 });
  assert.equal(cheia, 22.67);
  assert.equal(oitenta, 28.33);
});

test("eficiencia ausente ou invalida vale 100: o comportamento de sempre", () => {
  const semCampo = custoHoraDeTrabalho({ salarioMensal: 2000, encargosPct: 70, horasProdutivasMes: 150 });
  const zerada = custoHoraDeTrabalho({ salarioMensal: 2000, encargosPct: 70, horasProdutivasMes: 150, eficienciaPct: 0 });
  const acima = custoHoraDeTrabalho({ salarioMensal: 2000, encargosPct: 70, horasProdutivasMes: 150, eficienciaPct: 150 });
  assert.equal(semCampo, 22.67);
  assert.equal(zerada, 22.67);
  assert.equal(acima, 22.67);
});

test("o exemplo do dono com eficiencia: 1618 + 60% em 180h a 80%", () => {
  assert.equal(
    custoHoraDeTrabalho({ salarioMensal: 1618, encargosPct: 60, horasProdutivasMes: 180, eficienciaPct: 80 }),
    17.98
  );
});
