import * as kv from "./kv_store.tsx";
import { createLogger } from "./logger.tsx";
import { isValidNuit, normalizeNuit } from "./nuit.tsx";
import { buscarColaboradorPorId } from "./colaboradores.tsx";
import { criarComunicacaoDependenteIRPS } from "./comunicacao-dependentes-irps.tsx";

const logger = createLogger('Dependentes');

// Dependentes de um Colaborador (conjuge, filhos, etc.) — Grupo 1 da
// especificacao de Colaboradores. `elegivelDeducaoIrps` fica sempre como
// marcacao manual: as regras de elegibilidade de deducao de dependentes no
// IRPS dependem da mesma confirmacao fiscal profissional que bloqueia os
// escaloes de IRPS (ver parametros-fiscais-rh.tsx) — o sistema nao decide
// isto sozinho.
export type GrauParentescoDependente =
  | "conjuge"
  | "filho"
  | "enteado"
  | "pai"
  | "mae"
  | "outro";

export interface Dependente {
  id: string;
  empresaId: string;
  colaboradorId: string;
  nome: string;
  dataNascimento: string;
  grauParentesco: GrauParentescoDependente;
  nuit?: string;
  numeroIdentificacao?: string;
  elegivelDeducaoIrps: boolean;
  dataInicioDependencia?: string;
  dataFimDependencia?: string;
  observacoes?: string;
  ativo: boolean;
  dataCriacao: string;
  dataAtualizacao?: string;
}

const DEPENDENTE_PREFIX = "dependente:";

export async function criarDependente(
  dados: Omit<Dependente, "id" | "dataCriacao" | "ativo"> & { ativo?: boolean },
): Promise<{ success: boolean; data?: Dependente; error?: string }> {
  try {
    if (!dados.empresaId || !dados.colaboradorId || !dados.nome?.trim()) {
      return { success: false, error: "Empresa, colaborador e nome do dependente são obrigatórios" };
    }

    if (!dados.dataNascimento) {
      return { success: false, error: "Data de nascimento do dependente é obrigatória" };
    }

    if (!dados.grauParentesco) {
      return { success: false, error: "Grau de parentesco é obrigatório" };
    }

    const nuitNormalizado = dados.nuit ? normalizeNuit(dados.nuit) : undefined;
    if (nuitNormalizado && !isValidNuit(nuitNormalizado)) {
      return { success: false, error: "NUIT do dependente inválido. Deve conter exatamente 9 dígitos numéricos" };
    }

    const id = `dependente_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    const dependente: Dependente = {
      id,
      ...dados,
      nuit: nuitNormalizado,
      elegivelDeducaoIrps: Boolean(dados.elegivelDeducaoIrps),
      ativo: dados.ativo !== undefined ? dados.ativo : true,
      dataCriacao: new Date().toISOString(),
    };

    await kv.set(`${DEPENDENTE_PREFIX}${id}`, dependente);
    logger.info(`Dependente criado: ${dependente.nome} (colaborador ${dados.colaboradorId})`);

    const colaborador = await buscarColaboradorPorId(dados.colaboradorId);
    await criarComunicacaoDependenteIRPS({
      empresaId: dependente.empresaId,
      colaboradorId: dependente.colaboradorId,
      colaboradorNome: colaborador?.nome || "Colaborador",
      dependenteId: dependente.id,
      dependenteNome: dependente.nome,
      tipo: "adicao",
      dataEvento: new Date().toISOString().slice(0, 10),
      detalhes: { grauParentesco: dependente.grauParentesco, elegivelDeducaoIrps: dependente.elegivelDeducaoIrps },
    });

    return { success: true, data: dependente };
  } catch (error) {
    logger.error("Erro ao criar dependente:", error);
    return { success: false, error: error.message };
  }
}

export async function buscarDependentePorId(id: string): Promise<Dependente | null> {
  try {
    return (await kv.get(`${DEPENDENTE_PREFIX}${id}`)) as Dependente | null;
  } catch (error) {
    logger.error("Erro ao buscar dependente:", error);
    return null;
  }
}

export async function listarDependentes(
  empresaId: string,
  filtros?: { colaboradorId?: string; ativo?: boolean },
): Promise<Dependente[]> {
  try {
    const todos = await kv.getByPrefix<Dependente>(DEPENDENTE_PREFIX);
    let lista = todos.filter((item) => item && item.empresaId === empresaId);

    if (filtros?.colaboradorId) {
      lista = lista.filter((item) => item.colaboradorId === filtros.colaboradorId);
    }

    if (filtros?.ativo !== undefined) {
      lista = lista.filter((item) => item.ativo === filtros.ativo);
    }

    lista.sort((a, b) => a.nome.localeCompare(b.nome));

    return lista;
  } catch (error) {
    logger.error("Erro ao listar dependentes:", error);
    return [];
  }
}

export async function atualizarDependente(
  id: string,
  dados: Partial<Dependente>,
): Promise<{ success: boolean; data?: Dependente; error?: string }> {
  try {
    const dependente = await buscarDependentePorId(id);
    if (!dependente) {
      return { success: false, error: "Dependente não encontrado" };
    }

    const nuitAtualizado = dados.nuit !== undefined ? (dados.nuit ? normalizeNuit(dados.nuit) : undefined) : undefined;
    if (dados.nuit !== undefined && nuitAtualizado && !isValidNuit(nuitAtualizado)) {
      return { success: false, error: "NUIT do dependente inválido. Deve conter exatamente 9 dígitos numéricos" };
    }

    const dependenteAtualizado: Dependente = {
      ...dependente,
      ...dados,
      ...(dados.nuit !== undefined ? { nuit: nuitAtualizado } : {}),
      id: dependente.id,
      empresaId: dependente.empresaId,
      colaboradorId: dependente.colaboradorId,
      dataCriacao: dependente.dataCriacao,
      dataAtualizacao: new Date().toISOString(),
    };

    await kv.set(`${DEPENDENTE_PREFIX}${id}`, dependenteAtualizado);
    logger.info(`Dependente atualizado: ${id}`);

    const tornouSeInativo = dependente.ativo && dados.ativo === false;
    const mudouElegibilidadeOuParentesco =
      (dados.elegivelDeducaoIrps !== undefined && dados.elegivelDeducaoIrps !== dependente.elegivelDeducaoIrps) ||
      (dados.grauParentesco !== undefined && dados.grauParentesco !== dependente.grauParentesco);

    if (tornouSeInativo || mudouElegibilidadeOuParentesco) {
      const colaborador = await buscarColaboradorPorId(dependenteAtualizado.colaboradorId);
      await criarComunicacaoDependenteIRPS({
        empresaId: dependenteAtualizado.empresaId,
        colaboradorId: dependenteAtualizado.colaboradorId,
        colaboradorNome: colaborador?.nome || "Colaborador",
        dependenteId: dependenteAtualizado.id,
        dependenteNome: dependenteAtualizado.nome,
        tipo: tornouSeInativo ? "remocao" : "alteracao",
        dataEvento: new Date().toISOString().slice(0, 10),
        detalhes: {
          grauParentescoAnterior: dependente.grauParentesco,
          grauParentescoNovo: dependenteAtualizado.grauParentesco,
          elegivelDeducaoIrpsAnterior: dependente.elegivelDeducaoIrps,
          elegivelDeducaoIrpsNovo: dependenteAtualizado.elegivelDeducaoIrps,
        },
      });
    }

    return { success: true, data: dependenteAtualizado };
  } catch (error) {
    logger.error("Erro ao atualizar dependente:", error);
    return { success: false, error: error.message };
  }
}

export async function deletarDependente(id: string): Promise<{ success: boolean; error?: string }> {
  try {
    const dependente = await buscarDependentePorId(id);
    if (!dependente) {
      return { success: false, error: "Dependente não encontrado" };
    }

    await kv.del(`${DEPENDENTE_PREFIX}${id}`);
    logger.info(`Dependente deletado: ${id}`);

    const colaborador = await buscarColaboradorPorId(dependente.colaboradorId);
    await criarComunicacaoDependenteIRPS({
      empresaId: dependente.empresaId,
      colaboradorId: dependente.colaboradorId,
      colaboradorNome: colaborador?.nome || "Colaborador",
      dependenteId: dependente.id,
      dependenteNome: dependente.nome,
      tipo: "remocao",
      dataEvento: new Date().toISOString().slice(0, 10),
      detalhes: { grauParentesco: dependente.grauParentesco },
    });

    return { success: true };
  } catch (error) {
    logger.error("Erro ao deletar dependente:", error);
    return { success: false, error: error.message };
  }
}
