import { buscarColaboradorPorId, isValidNib } from "./colaboradores.tsx";
import { listarFolhasPagamento } from "./folha-pagamento.tsx";
import { obterPeriodoFolhaPagamento } from "./periodo-folha-pagamento.tsx";

// ========== FICHEIRO DE TRANSFERENCIA BANCARIA (generico) ==========
//
// IMPORTANTE: nenhum banco mocambicano publica publicamente o formato exacto
// do seu ficheiro de importacao de pagamentos em massa (ao contrario do
// SISSMO, que tem um "Guia do Contribuinte" oficial ja usado em
// relatorios-fiscais-rh.tsx) — confirmado por pesquisa. Um formato errado
// arrisca pagamentos falhados ou mal direccionados a pessoas reais, por
// isso este ficheiro NAO finge imitar nenhum banco especifico: e um export
// generico, claramente rotulado como tal, com os campos "standard"
// (NUIT, nome, NIB, valor, referencia, data) que o utilizador adapta ao
// formato exigido pelo seu gestor de conta bancaria.
//
// So gera para periodos com estado "aprovado" ou "fechado" (nao "aberto")
// — pagar salarios deve seguir a aprovacao hierarquica do workflow (ver
// periodo-folha-pagamento.tsx), nao ser feito directamente a partir de
// folhas ainda por rever.
//
// "Split de pagamentos" (dividir o salario de um colaborador por varias
// contas) NAO esta implementado nesta iteracao — nao existe ainda um
// modelo de dados para isso.
export interface LinhaFicheiroTransferencia {
  colaboradorNome: string;
  numeroFuncionario: string;
  nuit: string;
  banco?: string;
  nib: string;
  valorLiquido: number;
  referencia: string;
  dataPagamento: string; // dd/mm/aaaa
}

export interface ResultadoFicheiroTransferencia {
  linhas: LinhaFicheiroTransferencia[];
  colaboradoresExcluidos: Array<{ nome: string; motivo: string }>;
  totalValor: number;
  numeroRegistos: number;
  conteudoFicheiro: string;
}

function formatarDataDDMMAAAA(dataIso: string): string {
  const [ano, mes, dia] = dataIso.split("T")[0].split("-");
  return `${dia}/${mes}/${ano}`;
}

function sanitizarCampoTexto(valor: string): string {
  return String(valor || "")
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .replace(/[;\r\n]+/g, " ")
    .trim();
}

export async function gerarFicheiroTransferenciaSalarios(
  empresaId: string,
  ano: number,
  mes: number,
  dataPagamento: string,
): Promise<{ success: boolean; data?: ResultadoFicheiroTransferencia; error?: string }> {
  try {
    if (!dataPagamento) {
      return { success: false, error: "Data de pagamento é obrigatória" };
    }

    const periodo = await obterPeriodoFolhaPagamento(empresaId, ano, mes);
    if (periodo.estado === "aberto") {
      return {
        success: false,
        error: `O período ${mes}/${ano} ainda está "aberto" — aprove-o primeiro em Processamento Salarial antes de gerar o ficheiro de pagamento.`,
      };
    }

    const folhas = await listarFolhasPagamento(empresaId, { ano, mes });
    if (folhas.length === 0) {
      return { success: false, error: `Não existem folhas de pagamento processadas para ${mes}/${ano}` };
    }

    const linhas: LinhaFicheiroTransferencia[] = [];
    const colaboradoresExcluidos: Array<{ nome: string; motivo: string }> = [];

    for (const folha of folhas) {
      const colaborador = await buscarColaboradorPorId(folha.colaboradorId);
      if (!colaborador) continue;

      if (!colaborador.nib?.trim()) {
        colaboradoresExcluidos.push({ nome: colaborador.nome, motivo: "Sem NIB registado" });
        continue;
      }

      if (!isValidNib(colaborador.nib)) {
        colaboradoresExcluidos.push({ nome: colaborador.nome, motivo: "NIB com formato inválido" });
        continue;
      }

      linhas.push({
        colaboradorNome: colaborador.nome,
        numeroFuncionario: colaborador.numeroFuncionario,
        nuit: colaborador.nuit,
        banco: colaborador.banco,
        nib: colaborador.nib.replace(/[\s-]/g, ""),
        valorLiquido: folha.salarioLiquido,
        referencia: `SAL${ano}${String(mes).padStart(2, "0")}-${colaborador.numeroFuncionario}`,
        dataPagamento: formatarDataDDMMAAAA(dataPagamento),
      });
    }

    if (linhas.length === 0) {
      return { success: false, error: "Nenhum colaborador com NIB válido para incluir no ficheiro" };
    }

    const cabecalho = "NUIT;NOME;BANCO;NIB;VALOR;REFERENCIA;DATA_PAGAMENTO";
    const linhasFicheiro = linhas.map((linha) =>
      [
        linha.nuit,
        sanitizarCampoTexto(linha.colaboradorNome),
        sanitizarCampoTexto(linha.banco || ""),
        linha.nib,
        linha.valorLiquido.toFixed(2),
        linha.referencia,
        linha.dataPagamento,
      ].join(";"),
    );

    const totalValor = Math.round(linhas.reduce((soma, l) => soma + l.valorLiquido, 0) * 100) / 100;

    return {
      success: true,
      data: {
        linhas,
        colaboradoresExcluidos,
        totalValor,
        numeroRegistos: linhas.length,
        conteudoFicheiro: [cabecalho, ...linhasFicheiro].join("\r\n"),
      },
    };
  } catch (error: any) {
    return { success: false, error: error.message };
  }
}

export function nomeFicheiroTransferencia(ano: number, mes: number): string {
  return `transferencias_salarios_${ano}_${String(mes).padStart(2, "0")}.csv`;
}
