import { listarGuiasPagamentoINSS } from "./guia-pagamento-inss.tsx";
import { listarComunicacoesINSS } from "./comunicacao-inss.tsx";

// Livro de registo digital de conformidade INSS — organiza cronologicamente
// tudo o que ja fica persistido e auditavel neste modulo: emissao/pagamento/
// anulacao de Guias de Pagamento (guia-pagamento-inss.tsx) e criacao/envio
// de Comunicacoes de admissao/alteracao salarial/cessacao
// (comunicacao-inss.tsx). Nao inclui a geracao da Declaracao de
// Remuneracoes SISSMO porque essa e stateless (gerada a pedido, nao fica
// persistida como evento) — se for necessario auditar tambem esse passo,
// implica passar a persistir um registo de cada geracao.
export type TipoEventoLivroINSS =
  | "guia_emitida"
  | "guia_paga"
  | "guia_anulada"
  | "comunicacao_criada"
  | "comunicacao_enviada";

export interface EventoLivroINSS {
  data: string; // ISO datetime
  tipo: TipoEventoLivroINSS;
  descricao: string;
  responsavel?: string;
  referencia?: string;
}

export interface LivroRegistoINSS {
  empresaId: string;
  dataInicio: string;
  dataFim: string;
  eventos: EventoLivroINSS[];
}

function dentroDoIntervalo(dataIsoCompleta: string | undefined, dataInicio: string, dataFim: string): boolean {
  if (!dataIsoCompleta) return false;
  const data = dataIsoCompleta.slice(0, 10);
  return data >= dataInicio && data <= dataFim;
}

function formatarMoeda(valor: number): string {
  return new Intl.NumberFormat("pt-MZ", { minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(valor || 0);
}

export async function gerarLivroRegistoINSS(
  empresaId: string,
  dataInicio: string,
  dataFim: string,
): Promise<LivroRegistoINSS> {
  const [guias, comunicacoes] = await Promise.all([
    listarGuiasPagamentoINSS(empresaId),
    listarComunicacoesINSS(empresaId),
  ]);

  const eventos: EventoLivroINSS[] = [];

  for (const guia of guias) {
    if (dentroDoIntervalo(guia.dataEmissao, dataInicio, dataFim)) {
      eventos.push({
        data: guia.dataEmissao,
        tipo: "guia_emitida",
        descricao: `Guia ${guia.numeroGuia} emitida para ${guia.mes}/${guia.ano} — total ${formatarMoeda(guia.valorTotal)} MZN (${guia.numeroColaboradores} colaborador(es))`,
        responsavel: guia.geradoPor,
        referencia: guia.numeroGuia,
      });
    }
    if (guia.estado === "paga" && dentroDoIntervalo(guia.dataPagamento, dataInicio, dataFim)) {
      eventos.push({
        data: guia.dataPagamento!,
        tipo: "guia_paga",
        descricao: `Guia ${guia.numeroGuia} paga — ${guia.entidadeBancaria || "entidade não indicada"}`,
        referencia: guia.numeroGuia,
      });
    }
    if (guia.estado === "anulada" && dentroDoIntervalo(guia.dataAtualizacao, dataInicio, dataFim)) {
      eventos.push({
        data: guia.dataAtualizacao!,
        tipo: "guia_anulada",
        descricao: `Guia ${guia.numeroGuia} anulada — ${guia.motivoAnulacao || "sem motivo registado"}`,
        referencia: guia.numeroGuia,
      });
    }
  }

  for (const comunicacao of comunicacoes) {
    if (dentroDoIntervalo(comunicacao.dataCriacao, dataInicio, dataFim)) {
      eventos.push({
        data: comunicacao.dataCriacao,
        tipo: "comunicacao_criada",
        descricao: `Obrigação de comunicação (${comunicacao.tipo}) registada para ${comunicacao.colaboradorNome} — prazo até ${comunicacao.prazoLimite}`,
        referencia: comunicacao.colaboradorNome,
      });
    }
    if (comunicacao.estado === "comunicado" && dentroDoIntervalo(comunicacao.dataComunicacao, dataInicio, dataFim)) {
      eventos.push({
        data: comunicacao.dataComunicacao!,
        tipo: "comunicacao_enviada",
        descricao: `Comunicação de ${comunicacao.tipo} enviada para ${comunicacao.colaboradorNome}${comunicacao.numeroProtocolo ? ` — protocolo ${comunicacao.numeroProtocolo}` : ""}`,
        responsavel: comunicacao.comunicadoPor,
        referencia: comunicacao.colaboradorNome,
      });
    }
  }

  eventos.sort((a, b) => a.data.localeCompare(b.data));

  return { empresaId, dataInicio, dataFim, eventos };
}
