import { test } from "node:test";
import assert from "node:assert/strict";
import { lerAjustesArmazenados, validarAjustesDePermissao } from "./ajustes-de-permissao.ts";

test("aceita ação com verdadeiro/falso e módulo com nível", () => {
  const r = validarAjustesDePermissao({
    "orders.edit": true,
    "financial.read": false,
    orders: "operar",
    suppliers: "nenhum",
  });
  assert.equal(r.ok, true);
  assert.deepEqual(r.ok && r.ajustes, {
    "orders.edit": true,
    "financial.read": false,
    orders: "operar",
    suppliers: "nenhum",
  });
});

test("vazio e ausente são válidos", () => {
  assert.deepEqual(validarAjustesDePermissao({}), { ok: true, ajustes: {} });
  assert.deepEqual(validarAjustesDePermissao(null), { ok: true, ajustes: {} });
  assert.deepEqual(validarAjustesDePermissao(undefined), { ok: true, ajustes: {} });
});

test("recusa chave que não existe, em vez de limpar calado", () => {
  /* O caso que motiva o arquivo: o admin marca, some, e ninguém entende por
     quê. Recusar faz a tela avisar na hora. */
  const r = validarAjustesDePermissao({ "orders.editar": true });
  assert.equal(r.ok, false);
  assert.match(r.ok === false ? r.erro : "", /orders\.editar/);
});

test("recusa nível escrito errado", () => {
  for (const lixo of ["tudo", "ler", "sim", "1", ""]) {
    const r = validarAjustesDePermissao({ orders: lixo });
    assert.equal(r.ok, false, `"${lixo}" não podia passar`);
  }
});

test("nível aceita maiúsculas e volta normalizado", () => {
  const r = validarAjustesDePermissao({ orders: "OPERAR" });
  assert.equal(r.ok, true);
  assert.equal(r.ok && r.ajustes.orders, "operar");
});

test("recusa tipo trocado entre módulo e ação", () => {
  /* Módulo esperando nível, ação esperando booleano. Trocar os dois é o erro
     mais fácil de cometer escrevendo o corpo na mão. */
  assert.equal(validarAjustesDePermissao({ orders: true }).ok, false);
  assert.equal(validarAjustesDePermissao({ "orders.edit": "total" }).ok, false);
});

test("recusa o que não é objeto", () => {
  for (const lixo of [[], ["orders.edit"], "orders.edit", 42, true]) {
    assert.equal(validarAjustesDePermissao(lixo).ok, false, `${JSON.stringify(lixo)} passou`);
  }
});

test("recusa valor aninhado", () => {
  assert.equal(validarAjustesDePermissao({ "orders.edit": { valor: true } }).ok, false);
  assert.equal(validarAjustesDePermissao({ orders: ["operar"] }).ok, false);
});

test("a leitura descarta o inválido em vez de recusar tudo", () => {
  /* Dados gravados antes de existir validação precisam abrir o modal. */
  const lido = lerAjustesArmazenados({
    "orders.edit": true,
    "chave.que.nao.existe": true,
    orders: "operar",
    quotes: "nivel-inventado",
    financial: 3,
    "products.read": "sim",
  });
  assert.deepEqual(lido, { "orders.edit": true, orders: "operar" });
});

test("a leitura aguenta o que não é objeto", () => {
  for (const lixo of [null, undefined, [], "x", 7]) {
    assert.deepEqual(lerAjustesArmazenados(lixo), {});
  }
});
