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

import { mudancasDaRemarcacao } from "../agenda/remarcar.ts";
import {
  acharEtapa,
  celulaCsv,
  codigoDoCupom,
  diaEmBrasilia,
  ehVendaDoPdv,
  erroDoCupom,
  etapasDoQuadro,
  etiquetasLimpas,
  marcasDoCliente,
  mensagemParaPessoa,
  montarCsv,
  situacaoDoCupom,
  whatsappNoPadrao,
} from "./ferramentas/operacao-regras.ts";

describe("cupons", () => {
  it("código em maiúsculas, só letras, números e hífen", () => {
    assert.equal(codigoDoCupom(" bemvindo10 "), "BEMVINDO10");
    assert.equal(codigoDoCupom("BLACK-FRIDAY"), "BLACK-FRIDAY");
    assert.equal(codigoDoCupom("com espaco"), null);
    assert.equal(codigoDoCupom("A_B"), null);
    assert.equal(codigoDoCupom("AB"), null);
  });
  it("porcentagem até 100 e valor maior que zero", () => {
    const base = { type: "percent" as const, value: 10, min_total: 0, min_items: 0, starts_at: null, ends_at: null };
    assert.equal(erroDoCupom(base), null);
    assert.match(String(erroDoCupom({ ...base, value: 101 })), /100%/);
    assert.equal(erroDoCupom({ ...base, type: "value", value: 150 }), null);
    assert.match(String(erroDoCupom({ ...base, value: 0 })), /maior que zero/);
    assert.match(String(erroDoCupom({ ...base, starts_at: "2026-10-10T00:00:00-03:00", ends_at: "2026-10-01T23:59:59-03:00" })), /antes/);
  });
  it("situação pela data e pela chave", () => {
    const agora = Date.parse("2026-10-14T12:00:00Z");
    assert.equal(situacaoDoCupom({ active: false, starts_at: null, ends_at: null }, agora), "desligado");
    assert.equal(situacaoDoCupom({ active: true, starts_at: "2026-11-01T00:00:00-03:00", ends_at: null }, agora), "ainda não começou");
    assert.equal(situacaoDoCupom({ active: true, starts_at: null, ends_at: "2026-10-01T23:59:59-03:00" }, agora), "vencido");
    assert.equal(situacaoDoCupom({ active: null, starts_at: null, ends_at: null }, agora), "valendo");
  });
  it("dia de Brasília de um instante", () => {
    assert.equal(diaEmBrasilia("2026-10-31T23:59:59-03:00"), "2026-10-31");
    assert.equal(diaEmBrasilia(null), null);
  });
});

describe("pedidos", () => {
  it("reconhece venda do PDV como a tela", () => {
    assert.equal(ehVendaDoPdv({ quoteTitle: "Venda PDV #12" }), true);
    assert.equal(ehVendaDoPdv({ quoteInternalNotes: "origem:pdv" }), true);
    assert.equal(ehVendaDoPdv({ internal_notes: "Pedido da loja" }), false);
  });
  it("etapas do quadro e busca sem acento", () => {
    const etapas = etapasDoQuadro([
      { id: "b", label: "Acabamento", status: "in_production", position: 2 },
      { id: "a", label: "Impressão", status: "in_production", position: 1 },
      { label: "Sem id", status: "finished" },
      { id: "c", label: "Pronto p/ retirar", status: "qualquer", position: 3 },
    ]);
    assert.deepEqual(etapas.map((e) => e.id), ["a", "b", "c"]);
    assert.equal(etapas[2].status, "in_production");
    assert.equal(acharEtapa(etapas, "impressao")?.id, "a");
    assert.equal(acharEtapa(etapas, "corte"), null);
    assert.deepEqual(etapasDoQuadro(null), []);
  });
  it("mensagem técnica não passa para a pessoa", () => {
    assert.equal(mensagemParaPessoa("Já existe um pedido para este orçamento.", "x"), "Já existe um pedido para este orçamento.");
    assert.equal(mensagemParaPessoa('duplicate key value violates unique constraint "x"', "reserva"), "reserva");
    assert.equal(mensagemParaPessoa("", "reserva"), "reserva");
  });
});

describe("clientes", () => {
  it("WhatsApp no padrão do painel", () => {
    assert.equal(whatsappNoPadrao("(81) 99999-0000"), "+5581999990000");
    assert.equal(whatsappNoPadrao("5581999990000"), "+5581999990000");
    assert.equal(whatsappNoPadrao("123"), "invalido");
    assert.equal(whatsappNoPadrao(""), null);
  });
  it("marcas de repetição: documento, e-mail e fim do telefone", () => {
    const marcas = marcasDoCliente({ document: "123.456.789-09", email: " Ana@X.com ", whatsapp: "+5581999990000", phone: null }).map((m) => m.valor);
    assert.deepEqual(marcas, ["d:12345678909", "e:ana@x.com", "t:99990000"]);
    assert.deepEqual(marcasDoCliente({ document: "123" }), []);
  });
  it("etiquetas sem repetição", () => {
    assert.deepEqual(etiquetasLimpas(["VIP", "vip", " Atacado ", ""]), ["VIP", "Atacado"]);
  });
  it("CSV com ponto e vírgula, aspas e proteção contra fórmula", () => {
    assert.equal(celulaCsv('a;"b"'), '"a;""b"""');
    assert.equal(celulaCsv("=SOMA(A1)"), "'=SOMA(A1)");
    assert.equal(celulaCsv(-5.5), "-5,5");
    assert.equal(celulaCsv(null), "");
    const csv = montarCsv(["Nome", "Cidade"], [["Ana", "Recife"]]);
    assert.ok(csv.startsWith("﻿Nome;Cidade\r\nAna;Recife"));
  });
});

describe("remarcar compromisso", () => {
  const atual = { status: "agendado", recurrence: "none", recurrence_until: null, start_time: "09:30:00", end_time: "11:00:00" };
  it("não leva agendado para o passado", () => {
    const r = mudancasDaRemarcacao(atual, { dia: "2026-10-01", hoje: "2026-10-14", inicioNovo: null });
    assert.equal(r.ok, false);
  });
  it("move o fim junto, mantendo a duração", () => {
    const r = mudancasDaRemarcacao(atual, { dia: "2026-10-20", hoje: "2026-10-14", inicioNovo: "14:00" });
    assert.ok(r.ok);
    if (r.ok) {
      assert.equal(r.mudancas.event_date, "2026-10-20");
      assert.equal(r.mudancas.start_time, "14:00");
      assert.equal(r.mudancas.end_time, "15:30");
    }
  });
  it("respeita o fim da repetição", () => {
    const r = mudancasDaRemarcacao({ ...atual, recurrence: "weekly", recurrence_until: "2026-10-18" }, { dia: "2026-10-20", hoje: "2026-10-14", inicioNovo: null });
    assert.equal(r.ok, false);
  });
});
