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

import { conferirItensNoBanco, disponivelEmUnidadesDoProduto, somarPorCelula } from "./conferir-itens.ts";

/* O outro caminho da conferência (estoque v2): a mesma conta do banco, somando por célula. */

const itens = [
  { product_id: "p1", quantity: 2, title: "Camisetas" },
  { product_id: "p2", quantity: 1, title: "Kit camiseta" },
];
const camiseta = (precisa: number, saldo = 2) => ({ item_id: "i1", celula_id: "c1", rotulo: "Camiseta lisa (G / Preta)", saldo, precisa, permite_negativo: false });

test("dois produtos disputam a mesma célula", () => {
  const r = somarPorCelula(itens, [
    { v2: true, itens: [camiseta(2)] },
    { v2: true, itens: [camiseta(1), { item_id: "i2", celula_id: "c2", rotulo: "Caneca", saldo: -3, precisa: 1, permite_negativo: true }] },
  ]);
  assert.equal(r?.ok, false);
  assert.deepEqual(r?.problemas.map((p) => [p.indice, p.celula_id]), [[0, "c1"], [1, "c1"]]);
  assert.equal(r?.problemas[0].mensagem, 'Acabou o estoque de "Camiseta lisa (G / Preta)" para "Camisetas": tem 2, o pedido precisa de 3.');
});

test("cabe, permite negativo e sem célula", () => {
  assert.equal(somarPorCelula([itens[0]], [{ v2: true, itens: [camiseta(2)] }])?.ok, true);
  const semCelula = somarPorCelula([itens[0]], [{ v2: true, itens: [{ item_id: "i1", celula_id: null, sem_celula: true, falta_escolher: "tamanho e cor", permite_negativo: true }] }]);
  assert.equal(semCelula?.problemas[0].mensagem, 'Escolha tamanho e cor de "Camisetas".');
  /* fora do v2 não há outro caminho */
  assert.equal(somarPorCelula([itens[0]], [{ v2: false, itens: [] }]), null);
});

test("usa a função do banco quando ela responde; senão, o outro caminho", async () => {
  const direto = { rpc: async () => ({ data: { ok: true, problemas: [] }, error: null }) };
  assert.deepEqual(await conferirItensNoBanco(direto, "dono", [itens[0]]), { ok: true, problemas: [] });
  const semDelete = {
    rpc: async (fn: string) =>
      fn === "estoque_conferir_itens"
        ? { data: null, error: { message: "DELETE requires a WHERE clause" } }
        : { data: { v2: true, itens: [camiseta(2, 1)] }, error: null },
  };
  const r = await conferirItensNoBanco(semDelete, "dono", [itens[0]]);
  assert.equal(r?.ok, false);
  assert.equal(r?.problemas[0].disponivel, 1);
});

test("o que dá para levar é em unidades do produto (kit, m²), não em peças da célula", async () => {
  assert.equal(disponivelEmUnidadesDoProduto(5, 6, 3), 2); // kit com 2: saldo 5 peças → 2 kits
  assert.equal(disponivelEmUnidadesDoProduto(2, 4, 2), 1); // banner de 2 m²: 2 m² de lona → 1 banner
  assert.equal(disponivelEmUnidadesDoProduto(3, 4, 4), 3); // 1 por unidade: o mesmo número
  assert.equal(disponivelEmUnidadesDoProduto(-1, 1, 1), 0);
  const kit = {
    rpc: async (fn: string) =>
      fn === "estoque_conferir_itens"
        ? { data: { ok: false, problemas: [{ indice: 0, produto_id: "p1", titulo: "Kit", celula_id: "c1", disponivel: 5, mensagem: "x" }] }, error: null }
        : { data: { v2: true, itens: [{ item_id: "i1", celula_id: "c1", saldo: 5, precisa: 6, permite_negativo: false }] }, error: null },
  };
  const r = await conferirItensNoBanco(kit, "dono", [{ product_id: "p1", quantity: 3, title: "Kit" }]);
  assert.equal(r?.problemas[0].disponivel, 2);
});
