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

import { areaDaImagem, lerRecadoDaCaneta, QuadroDeAnotacoes } from "./anotacoes.ts";
import { momentoDaSala, podePublicar } from "./regras.ts";

test("caneta: recado de fora só passa conferido e cortado", () => {
  assert.deepEqual(lerRecadoDaCaneta({ k: "limpar" }), { k: "limpar" });
  assert.deepEqual(lerRecadoDaCaneta({ k: "l", p: [0.5, 0.25] }), { k: "l", p: [0.5, 0.25] });
  assert.deepEqual(lerRecadoDaCaneta({ k: "l", p: [] }), { k: "l", p: [] });
  /* Cor fora da paleta, ponto fora da tela, id estranho: recusa. */
  assert.equal(lerRecadoDaCaneta({ k: "r", id: "abcd1", f: "caneta", c: "#123456", p: [0.1, 0.1] }), null);
  assert.equal(lerRecadoDaCaneta({ k: "r", id: "abcd1", f: "caneta", c: "#ea4335", p: [3, 0.1] }), null);
  assert.equal(lerRecadoDaCaneta({ k: "r", id: "<script>", f: "caneta", c: "#ea4335", p: [0.1, 0.1] }), null);
  assert.equal(lerRecadoDaCaneta({ k: "r", id: "abcd1", f: "spray", c: "#ea4335", p: [0.1, 0.1] }), null);
  assert.equal(lerRecadoDaCaneta({ k: "r", id: "abcd1", f: "caneta", c: "#ea4335", p: [0.1] }), null);
  assert.equal(lerRecadoDaCaneta({ k: "r", id: "abcd1", f: "caneta", c: "#ea4335", p: new Array(402).fill(0.5) }), null);
  assert.equal(lerRecadoDaCaneta("limpar"), null);
  const ok = lerRecadoDaCaneta({ k: "r", id: "abcd1", f: "marca", c: "#fbbc04", p: [0.123456, 0.5], de: 4, fim: true });
  assert.deepEqual(ok, { k: "r", id: "abcd1", f: "marca", c: "#fbbc04", p: [0.1235, 0.5], de: 4, fim: true });
});

test("caneta: o mesmo pedaço chegando duas vezes não duplica o risco", () => {
  const q = new QuadroDeAnotacoes();
  q.aplicar({ k: "r", id: "risco1", f: "caneta", c: "#ea4335", p: [0.1, 0.1, 0.2, 0.2], de: 0 });
  q.aplicar({ k: "r", id: "risco1", f: "caneta", c: "#ea4335", p: [0.3, 0.3], de: 4 });
  const copia = new QuadroDeAnotacoes();
  for (const r of q.exportar()) copia.aplicar(r);
  /* Quem já tinha recebe a cópia de novo: nada muda. */
  for (const r of q.exportar()) q.aplicar(r);
  assert.deepEqual(q.exportar(), copia.exportar());
  assert.equal((q.exportar()[0] as { p: number[] }).p.length, 6);
  q.aplicar({ k: "desfazer", id: "risco1" });
  assert.equal(q.exportar().length, 0);
  assert.equal(q.ultimoRisco(), null);
});

test("caneta: risco comprido sai em pedaços de até 400 números", () => {
  const q = new QuadroDeAnotacoes();
  const pontos = Array.from({ length: 1000 }, (_, i) => (i % 100) / 100);
  for (let de = 0; de < pontos.length; de += 200) q.aplicar({ k: "r", id: "longo1", f: "caneta", c: "#ea4335", p: pontos.slice(de, de + 200), de });
  const pedacos = q.exportar();
  assert.equal(pedacos.length, 3);
  assert.ok(pedacos.every((p) => p.k === "r" && p.p.length <= 400));
});

test("a imagem dentro da caixa com contain", () => {
  /* Tela 16:9 numa caixa quadrada: faixas em cima e embaixo. */
  const area = areaDaImagem(1000, 1000, 1920, 1080);
  const redondo = Object.fromEntries(Object.entries(area).map(([k, v]) => [k, Math.round(v * 100) / 100 || 0]));
  assert.deepEqual(redondo, { x: 0, y: 218.75, l: 1000, a: 562.5 });
  /* Sem tamanho ainda: a caixa toda. */
  assert.deepEqual(areaDaImagem(800, 600, 0, 0), { x: 0, y: 0, l: 800, a: 600 });
});

test("reunião: todo mundo manda tudo e a sala abre a qualquer hora", () => {
  const sala = { status: "agendada" as const, comeca_em: "2026-10-16T23:00:00.000Z", duracao_min: 60, espera_min: 0, participacao: "livre" as const, cameras_alunos: true };
  assert.equal(podePublicar("visitante", "tela", sala, false), true);
  assert.equal(podePublicar("visitante", "mic", sala, false), true);
  assert.equal(podePublicar("visitante", "tela", { ...sala, participacao: "mao" }, true), false);
  const doisDiasAntes = new Date("2026-10-14T23:00:00.000Z").getTime();
  assert.equal(momentoDaSala({ ...sala, categoria: "reuniao" }, doisDiasAntes), "espera");
  assert.equal(momentoDaSala({ ...sala, categoria: "venda" }, doisDiasAntes), "cedo");
});
