import * as kv from "./kv_store.tsx";
import { createLogger } from "./logger.tsx";
import { buscarColaboradorPorId } from "./colaboradores.tsx";

const logger = createLogger('AutorizacaoHoraExtra');

// Autorizacao PREVIA de trabalho extraordinario — fluxo de pedido/aprovacao
// analogo a ferias.tsx/ausencias.tsx. Escolhe-se aqui, ANTES da hora extra
// ser prestada (ou ate 24h depois, em caso de emergencia — nao bloqueado
// pelo sistema, apenas uma convencao operacional), se a compensacao sera
// paga em dinheiro (majorada, como ja acontecia desde o Grupo B) ou
// creditada como tempo no Banco de Horas (ver banco-horas.tsx).
//
// Decisao de ambito: a autorizacao NAO e ainda bloqueante — trabalho
// extraordinario sem autorizacao continua a ser pago automaticamente
// (comportamento do Grupo B, mantido para nao quebrar processamento ja em
// uso). A autorizacao serve para decidir ANTECIPADAMENTE a forma de
// compensacao (pagamento vs. banco de horas) — ver
// calculo-horas-trabalho.tsx.
export type TipoCompensacaoHoraExtra = "pagamento" | "tempo";
export type EstadoAutorizacaoHoraExtra = "pendente" | "aprovado" | "rejeitado" | "cancelado";

export interface AutorizacaoHoraExtra {
  id: string;
  empresaId: string;
  colaboradorId: string;
  data: string; // YYYY-MM-DD — dia em que a hora extra sera/foi prestada
  horaInicioPrevista?: string;
  horaFimPrevista?: string;
  motivo: string;
  tipoCompensacao: TipoCompensacaoHoraExtra;
  estado: EstadoAutorizacaoHoraExtra;
  motivoRejeicao?: string;
  aprovadoPor?: string;
  dataAprovacao?: string;
  solicitadoPor: string;
  dataCriacao: string;
  dataAtualizacao?: string;
}

const AUTORIZACAO_PREFIX = "autorizacao_hora_extra:";

function validarDados(dados: Partial<AutorizacaoHoraExtra>): string | null {
  if (!dados.empresaId) return "Empresa é obrigatória";
  if (!dados.colaboradorId) return "Colaborador é obrigatório";
  if (!dados.data || !/^\d{4}-\d{2}-\d{2}$/.test(dados.data)) return "Data inválida (formato esperado: AAAA-MM-DD)";
  if (!dados.motivo?.trim()) return "O motivo da hora extraordinária é obrigatório";
  if (dados.tipoCompensacao && !["pagamento", "tempo"].includes(dados.tipoCompensacao)) {
    return "Tipo de compensação inválido";
  }
  return null;
}

export async function criarAutorizacaoHoraExtra(
  dados: Pick<AutorizacaoHoraExtra, "empresaId" | "colaboradorId" | "data" | "motivo" | "tipoCompensacao"> &
    Partial<Pick<AutorizacaoHoraExtra, "horaInicioPrevista" | "horaFimPrevista">>,
  solicitadoPor: string,
): Promise<{ success: boolean; data?: AutorizacaoHoraExtra; error?: string }> {
  try {
    const erro = validarDados(dados);
    if (erro) return { success: false, error: erro };

    if (!solicitadoPor?.trim()) {
      return { success: false, error: "É obrigatório identificar quem solicitou a autorização" };
    }

    const colaborador = await buscarColaboradorPorId(dados.colaboradorId);
    if (!colaborador || colaborador.empresaId !== dados.empresaId) {
      return { success: false, error: "Colaborador não encontrado nesta empresa" };
    }

    const id = `autorizacao_hora_extra_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    const autorizacao: AutorizacaoHoraExtra = {
      id,
      empresaId: dados.empresaId,
      colaboradorId: dados.colaboradorId,
      data: dados.data,
      horaInicioPrevista: dados.horaInicioPrevista,
      horaFimPrevista: dados.horaFimPrevista,
      motivo: dados.motivo.trim(),
      tipoCompensacao: dados.tipoCompensacao,
      estado: "pendente",
      solicitadoPor: solicitadoPor.trim(),
      dataCriacao: new Date().toISOString(),
    };

    await kv.set(`${AUTORIZACAO_PREFIX}${id}`, autorizacao);
    logger.info(`Autorização de hora extra criada: ${colaborador.nome} - ${dados.data}`);

    return { success: true, data: autorizacao };
  } catch (error) {
    logger.error("Erro ao criar autorização de hora extra:", error);
    return { success: false, error: error.message };
  }
}

export async function buscarAutorizacaoHoraExtraPorId(id: string): Promise<AutorizacaoHoraExtra | null> {
  try {
    return (await kv.get(`${AUTORIZACAO_PREFIX}${id}`)) as AutorizacaoHoraExtra | null;
  } catch (error) {
    logger.error("Erro ao buscar autorização de hora extra:", error);
    return null;
  }
}

export async function listarAutorizacoesHoraExtra(
  empresaId: string,
  filtros?: { colaboradorId?: string; estado?: EstadoAutorizacaoHoraExtra; dataInicio?: string; dataFim?: string },
): Promise<AutorizacaoHoraExtra[]> {
  try {
    const todas = await kv.getByPrefix<AutorizacaoHoraExtra>(AUTORIZACAO_PREFIX);
    let autorizacoes = todas.filter((item) => item && item.empresaId === empresaId);

    if (filtros?.colaboradorId) {
      autorizacoes = autorizacoes.filter((item) => item.colaboradorId === filtros.colaboradorId);
    }
    if (filtros?.estado) {
      autorizacoes = autorizacoes.filter((item) => item.estado === filtros.estado);
    }
    if (filtros?.dataInicio) {
      autorizacoes = autorizacoes.filter((item) => item.data >= filtros.dataInicio!);
    }
    if (filtros?.dataFim) {
      autorizacoes = autorizacoes.filter((item) => item.data <= filtros.dataFim!);
    }

    autorizacoes.sort((a, b) => b.data.localeCompare(a.data));
    return autorizacoes;
  } catch (error) {
    logger.error("Erro ao listar autorizações de hora extra:", error);
    return [];
  }
}

// Busca a autorizacao aprovada para um colaborador numa data especifica —
// usado por calculo-horas-trabalho.tsx para decidir pagamento vs. banco de
// horas.
export async function buscarAutorizacaoAprovada(
  empresaId: string,
  colaboradorId: string,
  data: string,
): Promise<AutorizacaoHoraExtra | null> {
  const autorizacoes = await listarAutorizacoesHoraExtra(empresaId, { colaboradorId, dataInicio: data, dataFim: data });
  return autorizacoes.find((item) => item.estado === "aprovado" && item.data === data) || null;
}

export async function aprovarAutorizacaoHoraExtra(
  id: string,
  aprovadoPor: string,
): Promise<{ success: boolean; data?: AutorizacaoHoraExtra; error?: string }> {
  try {
    const autorizacao = await buscarAutorizacaoHoraExtraPorId(id);
    if (!autorizacao) return { success: false, error: "Autorização não encontrada" };
    if (autorizacao.estado !== "pendente") {
      return { success: false, error: `Só é possível aprovar autorizações pendentes (estado actual: ${autorizacao.estado})` };
    }
    if (!aprovadoPor?.trim()) {
      return { success: false, error: "É obrigatório identificar quem aprovou" };
    }

    const atualizada: AutorizacaoHoraExtra = {
      ...autorizacao,
      estado: "aprovado",
      aprovadoPor: aprovadoPor.trim(),
      dataAprovacao: new Date().toISOString(),
      dataAtualizacao: new Date().toISOString(),
    };

    await kv.set(`${AUTORIZACAO_PREFIX}${id}`, atualizada);
    logger.info(`Autorização de hora extra aprovada: ${id}`);

    return { success: true, data: atualizada };
  } catch (error) {
    logger.error("Erro ao aprovar autorização de hora extra:", error);
    return { success: false, error: error.message };
  }
}

export async function rejeitarAutorizacaoHoraExtra(
  id: string,
  motivoRejeicao: string,
  rejeitadoPor: string,
): Promise<{ success: boolean; data?: AutorizacaoHoraExtra; error?: string }> {
  try {
    if (!motivoRejeicao?.trim()) {
      return { success: false, error: "É obrigatório indicar o motivo da rejeição" };
    }

    const autorizacao = await buscarAutorizacaoHoraExtraPorId(id);
    if (!autorizacao) return { success: false, error: "Autorização não encontrada" };
    if (autorizacao.estado !== "pendente") {
      return { success: false, error: `Só é possível rejeitar autorizações pendentes (estado actual: ${autorizacao.estado})` };
    }

    const atualizada: AutorizacaoHoraExtra = {
      ...autorizacao,
      estado: "rejeitado",
      motivoRejeicao: motivoRejeicao.trim(),
      aprovadoPor: rejeitadoPor.trim(),
      dataAprovacao: new Date().toISOString(),
      dataAtualizacao: new Date().toISOString(),
    };

    await kv.set(`${AUTORIZACAO_PREFIX}${id}`, atualizada);
    logger.info(`Autorização de hora extra rejeitada: ${id}`);

    return { success: true, data: atualizada };
  } catch (error) {
    logger.error("Erro ao rejeitar autorização de hora extra:", error);
    return { success: false, error: error.message };
  }
}

export async function cancelarAutorizacaoHoraExtra(id: string): Promise<{ success: boolean; data?: AutorizacaoHoraExtra; error?: string }> {
  try {
    const autorizacao = await buscarAutorizacaoHoraExtraPorId(id);
    if (!autorizacao) return { success: false, error: "Autorização não encontrada" };
    if (autorizacao.estado !== "pendente" && autorizacao.estado !== "aprovado") {
      return { success: false, error: `Não é possível cancelar uma autorização já ${autorizacao.estado}` };
    }

    const atualizada: AutorizacaoHoraExtra = {
      ...autorizacao,
      estado: "cancelado",
      dataAtualizacao: new Date().toISOString(),
    };

    await kv.set(`${AUTORIZACAO_PREFIX}${id}`, atualizada);
    logger.info(`Autorização de hora extra cancelada: ${id}`);

    return { success: true, data: atualizada };
  } catch (error) {
    logger.error("Erro ao cancelar autorização de hora extra:", error);
    return { success: false, error: error.message };
  }
}
