import { test } from "node:test";
import assert from "node:assert/strict";
import {
  chaveDoDia,
  doTexto,
  estiloSituacao,
  horarioDoEvento,
  inicioDaSemana,
  somaDias,
} from "./tipos.ts";

/**
 * Datas e horários da agenda.
 *
 * O erro classico aqui e o fuso: `new Date("2026-08-27")` e interpretado como
 * UTC e vira dia 26 no Brasil, jogando o compromisso para o dia anterior na
 * tela. `doTexto` existe justamente para nao passar por isso, e este teste e o
 * que impede alguem de "simplificar" de volta para `new Date(iso)`.
 */

test("data em texto não anda para trás por causa do fuso", () => {
  /* O bug que estas funcoes existem para evitar. */
  const d = doTexto("2026-08-27");
  assert.equal(d.getDate(), 27);
  assert.equal(d.getMonth(), 7); // agosto
  assert.equal(d.getFullYear(), 2026);
});

test("ida e volta entre texto e data", () => {
  for (const iso of ["2026-01-01", "2026-08-27", "2026-12-31", "2024-02-29"]) {
    assert.equal(chaveDoDia(doTexto(iso)), iso, `falhou em ${iso}`);
  }
});

test("chaveDoDia preenche com zero", () => {
  assert.equal(chaveDoDia(new Date(2026, 0, 5)), "2026-01-05");
});

test("somaDias atravessa mês e ano", () => {
  assert.equal(chaveDoDia(somaDias(doTexto("2026-01-31"), 1)), "2026-02-01");
  assert.equal(chaveDoDia(somaDias(doTexto("2026-12-31"), 1)), "2027-01-01");
  assert.equal(chaveDoDia(somaDias(doTexto("2026-03-01"), -1)), "2026-02-28");
});

test("somaDias acerta o ano bissexto", () => {
  assert.equal(chaveDoDia(somaDias(doTexto("2024-02-28"), 1)), "2024-02-29");
});

test("semana começa na segunda, inclusive quando o dia é domingo", () => {
  /* Domingo e o caso que quebra a conta ingenua com getDay(), porque em
     JavaScript domingo e 0 e viraria "inicio da proxima semana". */
  assert.equal(chaveDoDia(inicioDaSemana(doTexto("2026-08-30"))), "2026-08-24"); // domingo
  assert.equal(chaveDoDia(inicioDaSemana(doTexto("2026-08-24"))), "2026-08-24"); // segunda
  assert.equal(chaveDoDia(inicioDaSemana(doTexto("2026-08-27"))), "2026-08-24"); // quinta
});

test("lê o horário que vem grudado no subtítulo", () => {
  /* O horario chega dentro do subtitulo porque get_agenda_range junta origens
     diferentes numa tabela so. */
  assert.deepEqual(horarioDoEvento({ subtitulo: "14:00 · Cliente X" }), {
    inicioMin: 840,
    fimMin: null,
  });
  assert.deepEqual(horarioDoEvento({ subtitulo: "14:00–15:30 · Cliente X" }), {
    inicioMin: 840,
    fimMin: 930,
  });
});

test("sem horário devolve nulo em vez de zero", () => {
  /* Zero seria meia-noite, e o compromisso apareceria no topo do dia. */
  for (const s of ["Cliente sem hora", "", null]) {
    assert.deepEqual(horarioDoEvento({ subtitulo: s }), { inicioMin: null, fimMin: null });
  }
});

test("meia-noite é 0, e isso não é o mesmo que 'sem hora'", () => {
  assert.deepEqual(horarioDoEvento({ subtitulo: "00:00 · Virada" }), {
    inicioMin: 0,
    fimMin: null,
  });
});

test("situação conhecida vira rótulo e cor", () => {
  assert.equal(estiloSituacao("concluido").texto, "Concluído");
  assert.equal(estiloSituacao("delivered").texto, "Concluído");
  assert.equal(estiloSituacao("overdue").texto, "Vencido");
  assert.equal(estiloSituacao("agendado").texto, "Agendado");
});

test("situação desconhecida aparece legível, sem sumir nem quebrar", () => {
  /* Origem nova do sistema nao pode virar selo vazio: melhor mostrar o que
     veio, capitalizado, do que esconder o estado do registro. */
  assert.equal(estiloSituacao("pending_review").texto, "Pending review");
  assert.equal(estiloSituacao(null).texto, "");
  assert.equal(estiloSituacao("").texto, "");
});
