/*
 * O calendário de 2027 (rodar: npx tsx --test src/lib/banner-editor/modelos-calendarios.test.ts).
 */
import assert from "node:assert/strict";
import { test } from "node:test";
import { MODELOS_DE_CALENDARIO, semanasDoMes } from "./modelos-calendarios";
import type { PecaDeTexto } from "./documento";

test("o dia 1 de cada mês de 2027 cai no dia da semana certo", () => {
  /* 0 = domingo: jan sexta, fev segunda, mar segunda, abr quinta, mai sábado, jun terça, jul quinta, ago domingo, set quarta, out sexta, nov segunda, dez quarta. */
  const esperado = [5, 1, 1, 4, 6, 2, 4, 0, 3, 5, 1, 3];
  esperado.forEach((coluna, mes) => assert.equal(semanasDoMes(2027, mes)[0][coluna], 1, `mês ${mes + 1}`));
});

test("todo mês cabe em 5 semanas e tem todos os dias uma vez só", () => {
  for (let mes = 0; mes < 12; mes += 1) {
    const semanas = semanasDoMes(2027, mes);
    assert.equal(semanas.length, 5);
    const dias = semanas.flat().flatMap((d) => (Array.isArray(d) ? d : d ? [d] : []));
    const total = new Date(Date.UTC(2027, mes + 1, 0)).getUTCDate();
    assert.deepEqual(dias.sort((a, b) => a - b), Array.from({ length: total }, (_, i) => i + 1), `mês ${mes + 1}`);
  }
});

test("janeiro, maio e outubro dobram a sexta semana (24/31, 23/30)", () => {
  assert.deepEqual(semanasDoMes(2027, 0)[4], [[24, 31], 25, 26, 27, 28, 29, 30]);
  assert.deepEqual(semanasDoMes(2027, 4)[4], [[23, 30], [24, 31], 25, 26, 27, 28, 29]);
  assert.deepEqual(semanasDoMes(2027, 9)[4], [[24, 31], 25, 26, 27, 28, 29, 30]);
  assert.deepEqual(semanasDoMes(2027, 1)[4], [28, 0, 0, 0, 0, 0, 0]);
});

const doc = MODELOS_DE_CALENDARIO[0].montar({ largura: 3508, altura: 2480, cor: "#7C3AED", logo: null, proporcaoDoLogo: null, foto: null });
const textos = doc.pecas.filter((p): p is PecaDeTexto => p.tipo === "texto");
const doMes = (mes: number) => textos.filter((p) => p.grupo === `calendario-2027-${String(mes).padStart(2, "0")}`);

test("A4 deitada em 300 ppp, 12 blocos de 5 cm e a arte leve", () => {
  assert.equal(doc.largura, 3508);
  assert.equal(doc.altura, 2480);
  assert.deepEqual(doc.impressao, { dpi: 300 });
  assert.equal(new Set(doc.pecas.map((p) => p.grupo).filter(Boolean)).size, 12);
  /* Linhas de corte: 5 em pé e 4 deitadas, a 590,55 px (5 cm) uma da outra. */
  const emPe = doc.pecas.filter((p) => p.nome === "Linha de corte" && p.h > p.w).map((p) => p.x + p.w / 2);
  assert.equal(emPe.length, 5);
  emPe.slice(1).forEach((x, i) => assert.ok(Math.abs(x - emPe[i] - (50 / 25.4) * 300) < 0.01));
  assert.ok(doc.pecas.length < 450, `${doc.pecas.length} peças`);
});

test("domingos e feriados em vermelho", () => {
  /* Janeiro: a coluna do domingo é vermelha; o dia 1 (sexta) é feriado. */
  const sexta = doMes(1).find((p) => p.nome?.endsWith("Dias de sexta"))!;
  assert.match(sexta.html || "", /<span style="color:#E3262E">1<\/span>/);
  const domingo = doMes(1).find((p) => p.nome?.endsWith("Dias de domingo"))!;
  assert.equal(domingo.texto, "3\n10\n17");
  assert.equal(domingo.pintura.cor, "#E3262E");
  /* Novembro: 2, 15 e 20 em vermelho; o "2 - DIA DE FINADOS" no canto. */
  const nov = doMes(11);
  const vermelhos = nov.flatMap((p) => [...(p.html || "").matchAll(/color:#E3262E">(\d+)</g)].map((m) => Number(m[1])));
  assert.deepEqual(vermelhos.sort((a, b) => a - b), [2, 15, 20]);
  assert.ok(nov.some((p) => p.texto === "2 - DIA DE FINADOS"));
  /* Fevereiro: só o 9 (carnaval); a quarta de cinzas fica preta. */
  const fev = doMes(2).flatMap((p) => [...(p.html || "").matchAll(/color:#E3262E">(\d+)</g)].map((m) => Number(m[1])));
  assert.deepEqual(fev, [9]);
});

test("as datas e as luas de cada mês", () => {
  assert.ok(doMes(3).some((p) => p.texto === "8 - DIA DA MULHER / 26 - PAIXÃO DE CRISTO / 28 - PÁSCOA"));
  /* Agosto tem 5 luas (duas novas); setembro começa na crescente. */
  const luas = (mes: number) => doMes(mes).filter((p) => p.nome?.includes("· Lua")).map((p) => p.texto.replace("\n", " "));
  assert.deepEqual(luas(8), ["02 NOVA", "09 CRESC.", "17 CHEIA", "24 MING.", "31 NOVA"]);
  assert.deepEqual(luas(9), ["07 CRESC.", "15 CHEIA", "23 MING.", "29 NOVA"]);
  assert.deepEqual(luas(1), ["07 NOVA", "15 CRESC.", "22 CHEIA", "29 MING."]);
});
