import { v } from "convex/values";
import { query, mutation } from "./_generated/server";
import { simboloTipo } from "./schema";

// Validadores para campos opcionais
const sexoValidator = v.optional(v.union(v.literal("masculino"), v.literal("feminino"), v.literal("outro")));
const estadoCivilValidator = v.optional(v.union(v.literal("solteiro"), v.literal("casado"), v.literal("divorciado"), v.literal("viuvo"), v.literal("uniao_estavel")));
const grauInstrucaoValidator = v.optional(v.union(v.literal("fundamental"), v.literal("medio"), v.literal("superior"), v.literal("pos_graduacao"), v.literal("mestrado"), v.literal("doutorado")));
const grupoSanguineoValidator = v.optional(v.union(v.literal("A"), v.literal("B"), v.literal("AB"), v.literal("O")));
const fatorRHValidator = v.optional(v.union(v.literal("positivo"), v.literal("negativo")));
const aposentadoValidator = v.optional(v.union(v.literal("nao"), v.literal("funape_ipsep"), v.literal("inss")));

export const getAll = query({
  args: {},
  returns: v.array(v.any()),
  handler: async (ctx) => {
    const funcionarios = await ctx.db.query("funcionarios").collect();
    // Retornar apenas os campos necessários para listagem
    return funcionarios.map((f: any) => ({
      _id: f._id,
      _creationTime: f._creationTime,
      nome: f.nome,
      matricula: f.matricula,
      cpf: f.cpf,
      rg: f.rg,
      nascimento: f.nascimento,
      email: f.email,
      telefone: f.telefone,
      endereco: f.endereco,
      cep: f.cep,
      cidade: f.cidade,
      uf: f.uf,
      simboloId: f.simboloId,
      simboloTipo: f.simboloTipo,
      admissaoData: f.admissaoData,
      desligamentoData: f.desligamentoData,
    }));
  },
});

export const getById = query({
  args: { id: v.id("funcionarios") },
  returns: v.union(v.any(), v.null()),
  handler: async (ctx, args) => {
    return await ctx.db.get(args.id);
  },
});

export const create = mutation({
  args: {
    // Campos obrigatórios
    nome: v.string(),
    matricula: v.optional(v.string()),
    simboloId: v.id("simbolos"),
    nascimento: v.string(),
    rg: v.string(),
    cpf: v.string(),
    endereco: v.string(),
    cep: v.string(),
    cidade: v.string(),
    uf: v.string(),
    telefone: v.string(),
    email: v.string(),
    admissaoData: v.optional(v.string()),
    desligamentoData: v.optional(v.string()),
    simboloTipo: simboloTipo,
    
    // Dados Pessoais Adicionais
    nomePai: v.optional(v.string()),
    nomeMae: v.optional(v.string()),
    naturalidade: v.optional(v.string()),
    naturalidadeUF: v.optional(v.string()),
    sexo: sexoValidator,
    estadoCivil: estadoCivilValidator,
    nacionalidade: v.optional(v.string()),
    
    // Documentos Pessoais
    rgOrgaoExpedidor: v.optional(v.string()),
    rgDataEmissao: v.optional(v.string()),
    carteiraProfissionalNumero: v.optional(v.string()),
    carteiraProfissionalSerie: v.optional(v.string()),
    carteiraProfissionalDataEmissao: v.optional(v.string()),
    reservistaNumero: v.optional(v.string()),
    reservistaSerie: v.optional(v.string()),
    tituloEleitorNumero: v.optional(v.string()),
    tituloEleitorZona: v.optional(v.string()),
    tituloEleitorSecao: v.optional(v.string()),
    pisNumero: v.optional(v.string()),
    
    // Formação e Saúde
    grauInstrucao: grauInstrucaoValidator,
    formacao: v.optional(v.string()),
    formacaoRegistro: v.optional(v.string()),
    grupoSanguineo: grupoSanguineoValidator,
    fatorRH: fatorRHValidator,
    
    // Cargo e Vínculo
    descricaoCargo: v.optional(v.string()),
    nomeacaoPortaria: v.optional(v.string()),
    nomeacaoData: v.optional(v.string()),
    nomeacaoDOE: v.optional(v.string()),
    pertenceOrgaoPublico: v.optional(v.boolean()),
    orgaoOrigem: v.optional(v.string()),
    aposentado: aposentadoValidator,
    
    // Dados Bancários
    contaBradescoNumero: v.optional(v.string()),
    contaBradescoDV: v.optional(v.string()),
    contaBradescoAgencia: v.optional(v.string()),
    
    // Documentos Anexos (Storage IDs)
    certidaoAntecedentesPF: v.optional(v.id("_storage")),
    certidaoAntecedentesJFPE: v.optional(v.id("_storage")),
    certidaoAntecedentesSDS: v.optional(v.id("_storage")),
    certidaoAntecedentesTJPE: v.optional(v.id("_storage")),
    certidaoImprobidade: v.optional(v.id("_storage")),
    rgFrente: v.optional(v.id("_storage")),
    rgVerso: v.optional(v.id("_storage")),
    cpfFrente: v.optional(v.id("_storage")),
    cpfVerso: v.optional(v.id("_storage")),
    situacaoCadastralCPF: v.optional(v.id("_storage")),
    tituloEleitorFrente: v.optional(v.id("_storage")),
    tituloEleitorVerso: v.optional(v.id("_storage")),
    comprovanteVotacao: v.optional(v.id("_storage")),
    carteiraProfissionalFrente: v.optional(v.id("_storage")),
    carteiraProfissionalVerso: v.optional(v.id("_storage")),
    comprovantePIS: v.optional(v.id("_storage")),
    certidaoRegistroCivil: v.optional(v.id("_storage")),
    certidaoNascimentoDependentes: v.optional(v.id("_storage")),
    cpfDependentes: v.optional(v.id("_storage")),
    reservistaDoc: v.optional(v.id("_storage")),
    comprovanteEscolaridade: v.optional(v.id("_storage")),
    comprovanteResidencia: v.optional(v.id("_storage")),
    comprovanteContaBradesco: v.optional(v.id("_storage")),
    
    // Declarações (Storage IDs)
    declaracaoAcumulacaoCargo: v.optional(v.id("_storage")),
    declaracaoDependentesIR: v.optional(v.id("_storage")),
    declaracaoIdoneidade: v.optional(v.id("_storage")),
    termoNepotismo: v.optional(v.id("_storage")),
    termoOpcaoRemuneracao: v.optional(v.id("_storage")),
  },
  returns: v.id("funcionarios"),
  handler: async (ctx, args) => {
    // Unicidade: CPF
    const cpfExists = await ctx.db
      .query("funcionarios")
      .withIndex("by_cpf", (q) => q.eq("cpf", args.cpf))
      .unique();
    if (cpfExists) {
      throw new Error("CPF já cadastrado");
    }

    // Unicidade: Matrícula (apenas se fornecida)
    if (args.matricula) {
      const matriculaExists = await ctx.db
        .query("funcionarios")
        .withIndex("by_matricula", (q) => q.eq("matricula", args.matricula))
        .unique();
      if (matriculaExists) {
        throw new Error("Já existe um funcionário com esta matrícula. Por favor, use outra ou deixe em branco.");
      }
    }

    const novoFuncionarioId = await ctx.db.insert("funcionarios", args as any);
    return novoFuncionarioId;
  },
});

export const update = mutation({
  args: {
    id: v.id("funcionarios"),
    // Campos obrigatórios
    nome: v.string(),
    matricula: v.optional(v.string()),
    simboloId: v.id("simbolos"),
    nascimento: v.string(),
    rg: v.string(),
    cpf: v.string(),
    endereco: v.string(),
    cep: v.string(),
    cidade: v.string(),
    uf: v.string(),
    telefone: v.string(),
    email: v.string(),
    admissaoData: v.optional(v.string()),
    desligamentoData: v.optional(v.string()),
    simboloTipo: simboloTipo,
    
    // Dados Pessoais Adicionais
    nomePai: v.optional(v.string()),
    nomeMae: v.optional(v.string()),
    naturalidade: v.optional(v.string()),
    naturalidadeUF: v.optional(v.string()),
    sexo: sexoValidator,
    estadoCivil: estadoCivilValidator,
    nacionalidade: v.optional(v.string()),
    
    // Documentos Pessoais
    rgOrgaoExpedidor: v.optional(v.string()),
    rgDataEmissao: v.optional(v.string()),
    carteiraProfissionalNumero: v.optional(v.string()),
    carteiraProfissionalSerie: v.optional(v.string()),
    carteiraProfissionalDataEmissao: v.optional(v.string()),
    reservistaNumero: v.optional(v.string()),
    reservistaSerie: v.optional(v.string()),
    tituloEleitorNumero: v.optional(v.string()),
    tituloEleitorZona: v.optional(v.string()),
    tituloEleitorSecao: v.optional(v.string()),
    pisNumero: v.optional(v.string()),
    
    // Formação e Saúde
    grauInstrucao: grauInstrucaoValidator,
    formacao: v.optional(v.string()),
    formacaoRegistro: v.optional(v.string()),
    grupoSanguineo: grupoSanguineoValidator,
    fatorRH: fatorRHValidator,
    
    // Cargo e Vínculo
    descricaoCargo: v.optional(v.string()),
    nomeacaoPortaria: v.optional(v.string()),
    nomeacaoData: v.optional(v.string()),
    nomeacaoDOE: v.optional(v.string()),
    pertenceOrgaoPublico: v.optional(v.boolean()),
    orgaoOrigem: v.optional(v.string()),
    aposentado: aposentadoValidator,
    
    // Dados Bancários
    contaBradescoNumero: v.optional(v.string()),
    contaBradescoDV: v.optional(v.string()),
    contaBradescoAgencia: v.optional(v.string()),
    
    // Documentos Anexos (Storage IDs)
    certidaoAntecedentesPF: v.optional(v.id("_storage")),
    certidaoAntecedentesJFPE: v.optional(v.id("_storage")),
    certidaoAntecedentesSDS: v.optional(v.id("_storage")),
    certidaoAntecedentesTJPE: v.optional(v.id("_storage")),
    certidaoImprobidade: v.optional(v.id("_storage")),
    rgFrente: v.optional(v.id("_storage")),
    rgVerso: v.optional(v.id("_storage")),
    cpfFrente: v.optional(v.id("_storage")),
    cpfVerso: v.optional(v.id("_storage")),
    situacaoCadastralCPF: v.optional(v.id("_storage")),
    tituloEleitorFrente: v.optional(v.id("_storage")),
    tituloEleitorVerso: v.optional(v.id("_storage")),
    comprovanteVotacao: v.optional(v.id("_storage")),
    carteiraProfissionalFrente: v.optional(v.id("_storage")),
    carteiraProfissionalVerso: v.optional(v.id("_storage")),
    comprovantePIS: v.optional(v.id("_storage")),
    certidaoRegistroCivil: v.optional(v.id("_storage")),
    certidaoNascimentoDependentes: v.optional(v.id("_storage")),
    cpfDependentes: v.optional(v.id("_storage")),
    reservistaDoc: v.optional(v.id("_storage")),
    comprovanteEscolaridade: v.optional(v.id("_storage")),
    comprovanteResidencia: v.optional(v.id("_storage")),
    comprovanteContaBradesco: v.optional(v.id("_storage")),
    
    // Declarações (Storage IDs)
    declaracaoAcumulacaoCargo: v.optional(v.id("_storage")),
    declaracaoDependentesIR: v.optional(v.id("_storage")),
    declaracaoIdoneidade: v.optional(v.id("_storage")),
    termoNepotismo: v.optional(v.id("_storage")),
    termoOpcaoRemuneracao: v.optional(v.id("_storage")),
  },
  returns: v.null(),
  handler: async (ctx, args) => {
    // Unicidade: CPF (excluindo o próprio registro)
    const cpfExists = await ctx.db
      .query("funcionarios")
      .withIndex("by_cpf", (q) => q.eq("cpf", args.cpf))
      .unique();
    if (cpfExists && cpfExists._id !== args.id) {
      throw new Error("CPF já cadastrado");
    }

    // Unicidade: Matrícula (apenas se fornecida, excluindo o próprio registro)
    if (args.matricula) {
      const matriculaExists = await ctx.db
        .query("funcionarios")
        .withIndex("by_matricula", (q) => q.eq("matricula", args.matricula))
        .unique();
      if (matriculaExists && matriculaExists._id !== args.id) {
        throw new Error("Já existe um funcionário com esta matrícula. Por favor, use outra ou deixe em branco.");
      }
    }

    const { id, ...updateData } = args;
    await ctx.db.patch(id, updateData as any);
    return null;
  },
});

export const remove = mutation({
  args: { id: v.id("funcionarios") },
  returns: v.null(),
  handler: async (ctx, args) => {
    // TODO: Talvez queiramos também remover os arquivos do storage
    await ctx.db.delete(args.id);
    return null;
  },
});

// Query para obter ficha completa para impressão
export const getFichaCompleta = query({
  args: { id: v.id("funcionarios") },
  returns: v.union(v.any(), v.null()),
  handler: async (ctx, args) => {
    const funcionario = await ctx.db.get(args.id);
    if (!funcionario) {
      return null;
    }
    
    // Buscar informações do símbolo
    const simbolo = await ctx.db.get(funcionario.simboloId);
    
    // Buscar cursos do funcionário
    const cursos = await ctx.db
      .query("cursos")
      .withIndex("by_funcionario", (q) => q.eq("funcionarioId", args.id))
      .collect();
    
    // Buscar URLs dos certificados
    const cursosComUrls = await Promise.all(
      cursos.map(async (curso) => {
        let certificadoUrl = null;
        if (curso.certificadoId) {
          certificadoUrl = await ctx.storage.getUrl(curso.certificadoId);
        }
        return {
          ...curso,
          certificadoUrl,
        };
      })
    );
    
    return {
      ...funcionario,
      simbolo: simbolo ? {
        nome: simbolo.nome,
        descricao: simbolo.descricao,
        tipo: simbolo.tipo,
        vencValor: simbolo.vencValor,
        repValor: simbolo.repValor,
        valor: simbolo.valor,
      } : null,
      cursos: cursosComUrls,
    };
  },
});

// Mutation: Configurar gestor (apenas para TI_MASTER)
export const configurarGestor = mutation({
  args: {
    funcionarioId: v.id("funcionarios"),
    gestorId: v.optional(v.id("usuarios")),
  },
  returns: v.null(),
  handler: async (ctx, args) => {
    await ctx.db.patch(args.funcionarioId, {
      gestorId: args.gestorId,
    });
    return null;
  },
});
