import { test } from "node:test";
import assert from "node:assert/strict";
import {
  EXPEDIENTE_PADRAO,
  expedienteValido,
  segundosUteis,
  segundosUteisDasSessoes,
} from "./expediente.ts";

/* São Paulo é UTC−3 o ano inteiro desde 2019. 1/9/2026 é uma terça-feira. */
const SP = (dia: string, hora: string) => Date.parse(`${dia}T${hora}:00-03:00`);

test("sessão dentro do expediente conta inteira", () => {
  assert.equal(segundosUteis(SP("2026-09-01", "10:00"), SP("2026-09-01", "12:00"), EXPEDIENTE_PADRAO), 7200);
});

test("sessão que atravessa a noite conta só o que cai no expediente", () => {
  /* Terça 17:00 → quarta 09:00: uma hora de terça e uma de quarta. */
  assert.equal(segundosUteis(SP("2026-09-01", "17:00"), SP("2026-09-02", "09:00"), EXPEDIENTE_PADRAO), 7200);
});

test("fim de semana não conta", () => {
  /* Sábado 5/9 08:00 → domingo 6/9 18:00. */
  assert.equal(segundosUteis(SP("2026-09-05", "08:00"), SP("2026-09-06", "18:00"), EXPEDIENTE_PADRAO), 0);
  /* Sexta 15:00 → segunda 10:00: 3 h de sexta + 2 h de segunda. */
  assert.equal(segundosUteis(SP("2026-09-04", "15:00"), SP("2026-09-07", "10:00"), EXPEDIENTE_PADRAO), 5 * 3600);
});

test("sessão fora do horário não conta; intervalo invertido é zero", () => {
  assert.equal(segundosUteis(SP("2026-09-01", "19:00"), SP("2026-09-01", "22:00"), EXPEDIENTE_PADRAO), 0);
  assert.equal(segundosUteis(SP("2026-09-01", "12:00"), SP("2026-09-01", "10:00"), EXPEDIENTE_PADRAO), 0);
});

test("expediente com sábado e outro horário", () => {
  const exp = { dias: [1, 2, 3, 4, 5, 6], inicio: "07:30", fim: "12:00", fuso: "America/Sao_Paulo" };
  /* Sábado 06:00 → 13:00 = 4 h 30. */
  assert.equal(segundosUteis(SP("2026-09-05", "06:00"), SP("2026-09-05", "13:00"), exp), 4.5 * 3600);
});

test("o cronômetro de fila de 23 horas vira o tempo útil de verdade", () => {
  /* Começou terça 16:00, esqueceram ligado, pausaram quarta 15:00. */
  const util = segundosUteis(SP("2026-09-01", "16:00"), SP("2026-09-02", "15:00"), EXPEDIENTE_PADRAO);
  assert.equal(util, 2 * 3600 + 7 * 3600);
});

test("sessões abertas contam até agora", () => {
  const agora = SP("2026-09-01", "11:00");
  const total = segundosUteisDasSessoes(
    [
      { inicio: SP("2026-09-01", "08:00"), fim: SP("2026-09-01", "09:00") },
      { inicio: SP("2026-09-01", "10:30"), fim: null },
    ],
    EXPEDIENTE_PADRAO,
    agora
  );
  assert.equal(total, 3600 + 1800);
});

test("expediente do banco: válido passa, lixo cai no padrão", () => {
  assert.deepEqual(expedienteValido(null), EXPEDIENTE_PADRAO);
  assert.deepEqual(expedienteValido({ dias: "x", inicio: "25:00", fuso: "Marte/Olympus" }), EXPEDIENTE_PADRAO);
  assert.deepEqual(
    expedienteValido({ dias: [6, 1, 1, 9], inicio: "07:00", fim: "16:30", fuso: "America/Manaus" }),
    { dias: [1, 6], inicio: "07:00", fim: "16:30", fuso: "America/Manaus" }
  );
});

test("fuso diferente muda a janela", () => {
  /* Em Manaus (UTC−4), 10:00 de SP são 09:00 locais. Uma sessão 07:00–09:00
     SP é 06:00–08:00 em Manaus: nada dentro de 08–18. */
  const manaus = { ...EXPEDIENTE_PADRAO, fuso: "America/Manaus" };
  assert.equal(segundosUteis(SP("2026-09-01", "07:00"), SP("2026-09-01", "09:00"), manaus), 0);
  assert.equal(segundosUteis(SP("2026-09-01", "07:00"), SP("2026-09-01", "09:00"), EXPEDIENTE_PADRAO), 3600);
});
