import { test } from "node:test";
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import {
  contaDaLinha,
  detalheDaConta,
  minimoDaConta,
  precoDoPainel,
  totaisDoOrcamento,
  totalDaLinhaEmCentavos,
  type ProdutoDoOrcamento,
} from "./assistentes/ferramentas/conta-do-orcamento.ts";

/*
 * O valor mínimo do item (migration 194) na conta que o assistente divide com
 * as telas do orçamento. A regra em si está em adicionais.test.ts.
 */

const LONA: ProdutoDoOrcamento = {
  id: "lona",
  name: "Lona",
  price: 125,
  cost_total: 0,
  unit_type: "square_meter",
  valor_minimo_item: 70,
  valor_minimo_orcamentos: true,
  valor_minimo_loja: true,
  valor_minimo_pdv: true,
};

test("as duas cópias de adicionais.ts continuam iguais", () => {
  const admin = readFileSync(fileURLToPath(new URL("./adicionais.ts", import.meta.url)), "utf8").replace(/\r\n/g, "\n");
  const loja = readFileSync(fileURLToPath(new URL("../../../public/src/lib/adicionais.ts", import.meta.url)), "utf8").replace(/\r\n/g, "\n");
  assert.equal(admin, loja);
});

test("assistente: lona pequena sai pelo mínimo, e a linha grava 70,00", () => {
  const medidas = { quantidade: 1, largura: 0.6, altura: 0.4 };
  const conta = contaDaLinha(LONA, medidas, {});
  assert.equal(conta.total, 70);
  const minimo = minimoDaConta(conta);
  assert.deepEqual(minimo, { valor_minimo_aplicado: 70, valor_sem_minimo: 30 });
  const precoUnitario = Math.round(precoDoPainel(LONA, medidas, {}) * 1e6) / 1e6;
  const linha = {
    quantity: 1, unit_type: "square_meter", width_m: 0.6, height_m: 0.4, length_m: null,
    unit_price: precoUnitario, unit_cost: 0, ...minimo,
  };
  assert.equal(totalDaLinhaEmCentavos(linha), 70);
  /* Duas linhas diferentes: cada uma paga o seu mínimo; o desconto vem depois. */
  const totais = totaisDoOrcamento([linha, { ...linha }], { desconto: 20 });
  assert.equal(totais.subtotal, 140);
  assert.equal(totais.total, 120);
  const detalhe = detalheDaConta(LONA, medidas, {});
  assert.equal(detalhe.valor_minimo_aplicado, 70);
  assert.equal(detalhe.total_sem_minimo, 30);
});

test("assistente: sem o mínimo, ou desligado nos orçamentos, a conta é a de antes", () => {
  const medidas = { quantidade: 1, largura: 0.6, altura: 0.4 };
  for (const produto of [{ ...LONA, valor_minimo_item: null }, { ...LONA, valor_minimo_orcamentos: false }]) {
    const conta = contaDaLinha(produto, medidas, {});
    assert.equal(Math.round(conta.total * 100) / 100, 30);
    assert.deepEqual(minimoDaConta(conta), { valor_minimo_aplicado: null, valor_sem_minimo: null });
  }
  /* Linha sem a coluna (gravada antes da migration): quantidade × preço. */
  const antiga = { quantity: 2, unit_type: "square_meter", width_m: 1, height_m: 0.5, length_m: null, unit_price: 125, unit_cost: 0 };
  assert.equal(totalDaLinhaEmCentavos(antiga), 125);
  assert.equal(totaisDoOrcamento([antiga], {}).subtotal, 125);
});

test("assistente: produto por unidade ignora o mínimo", () => {
  const caneca = { ...LONA, unit_type: "unit", price: 10 };
  const conta = contaDaLinha(caneca, { quantidade: 1 }, {});
  assert.equal(conta.total, 10);
  assert.equal(conta.minimoAplicado, null);
});
