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

/**
 * Listar todos os perfis customizados
 */
export const listarPerfisCustomizados = query({
  args: {},
  handler: async (ctx) => {
    const perfis = await ctx.db.query("perfisCustomizados").collect();

    // Buscar role correspondente para cada perfil
    const perfisComDetalhes = await Promise.all(
      perfis.map(async (perfil) => {
        const role = await ctx.db.get(perfil.roleId);
        const criador = await ctx.db.get(perfil.criadoPor);
        
        // Contar usuários usando este perfil
        const usuarios = await ctx.db
          .query("usuarios")
          .withIndex("by_role", (q) => q.eq("roleId", perfil.roleId))
          .collect();

        return {
          ...perfil,
          roleNome: role?.nome || "Desconhecido",
          criadorNome: criador?.nome || "Desconhecido",
          numeroUsuarios: usuarios.length,
        };
      })
    );

    return perfisComDetalhes;
  },
});

/**
 * Obter perfil com permissões detalhadas
 */
export const obterPerfilComPermissoes = query({
  args: {
    perfilId: v.id("perfisCustomizados"),
  },
  handler: async (ctx, args) => {
    const perfil = await ctx.db.get(args.perfilId);
    if (!perfil) {
      return null;
    }

    const role = await ctx.db.get(perfil.roleId);
    if (!role) {
      return null;
    }

    // Buscar permissões do role
    const rolePermissoes = await ctx.db
      .query("rolePermissoes")
      .withIndex("by_role", (q) => q.eq("roleId", perfil.roleId))
      .collect();

    const permissoes = await Promise.all(
      rolePermissoes.map(async (rp) => {
        return await ctx.db.get(rp.permissaoId);
      })
    );

    // Buscar permissões de menu
    const menuPermissoes = await ctx.db
      .query("menuPermissoes")
      .withIndex("by_role", (q) => q.eq("roleId", perfil.roleId))
      .collect();

    // Buscar usuários usando este perfil
    const usuarios = await ctx.db
      .query("usuarios")
      .withIndex("by_role", (q) => q.eq("roleId", perfil.roleId))
      .collect();

    return {
      perfil,
      role,
      permissoes: permissoes.filter((p) => p !== null),
      menuPermissoes,
      usuarios,
    };
  },
});

/**
 * Criar perfil customizado (apenas TI_MASTER)
 */
export const criarPerfilCustomizado = mutation({
  args: {
    nome: v.string(),
    descricao: v.string(),
    nivel: v.number(), // >= 3
    clonarDeRoleId: v.optional(v.id("roles")), // role para copiar permissões
    criadoPorId: v.id("usuarios"),
  },
  returns: v.union(
    v.object({ sucesso: v.literal(true), perfilId: v.id("perfisCustomizados") }),
    v.object({ sucesso: v.literal(false), erro: v.string() })
  ),
  handler: async (ctx, args) => {
    // Validar nível (deve ser >= 3)
    if (args.nivel < 3) {
      return { sucesso: false as const, erro: "Perfis customizados devem ter nível >= 3" };
    }

    // Verificar se nome já existe
    const roles = await ctx.db.query("roles").collect();
    const nomeExiste = roles.some((r) => r.nome.toLowerCase() === args.nome.toLowerCase());
    if (nomeExiste) {
      return { sucesso: false as const, erro: "Já existe um perfil com este nome" };
    }

    // Criar role correspondente
    const roleId = await ctx.db.insert("roles", {
      nome: args.nome.toLowerCase().replace(/\s+/g, "_"),
      descricao: args.descricao,
      nivel: args.nivel,
      customizado: true,
      criadoPor: args.criadoPorId,
      editavel: true,
    });

    // Copiar permissões se especificado
    if (args.clonarDeRoleId) {
      // Copiar permissões gerais
      const permissoesClonar = await ctx.db
        .query("rolePermissoes")
        .withIndex("by_role", (q) => q.eq("roleId", args.clonarDeRoleId))
        .collect();

      for (const perm of permissoesClonar) {
        await ctx.db.insert("rolePermissoes", {
          roleId,
          permissaoId: perm.permissaoId,
        });
      }

      // Copiar permissões de menu
      const menuPermsClonar = await ctx.db
        .query("menuPermissoes")
        .withIndex("by_role", (q) => q.eq("roleId", args.clonarDeRoleId))
        .collect();

      for (const menuPerm of menuPermsClonar) {
        await ctx.db.insert("menuPermissoes", {
          roleId,
          menuPath: menuPerm.menuPath,
          podeAcessar: menuPerm.podeAcessar,
          podeConsultar: menuPerm.podeConsultar,
          podeGravar: menuPerm.podeGravar,
        });
      }
    }

    // Criar perfil customizado
    const perfilId = await ctx.db.insert("perfisCustomizados", {
      nome: args.nome,
      descricao: args.descricao,
      nivel: args.nivel,
      roleId,
      criadoPor: args.criadoPorId,
      criadoEm: Date.now(),
      atualizadoEm: Date.now(),
    });

    // Log de atividade
    await registrarAtividade(
      ctx,
      args.criadoPorId,
      "criar",
      "perfis",
      JSON.stringify({ perfilId, nome: args.nome, nivel: args.nivel }),
      perfilId
    );

    return { sucesso: true as const, perfilId };
  },
});

/**
 * Editar perfil customizado (apenas TI_MASTER)
 */
export const editarPerfilCustomizado = mutation({
  args: {
    perfilId: v.id("perfisCustomizados"),
    nome: v.optional(v.string()),
    descricao: v.optional(v.string()),
    editadoPorId: v.id("usuarios"),
  },
  returns: v.union(
    v.object({ sucesso: v.literal(true) }),
    v.object({ sucesso: v.literal(false), erro: v.string() })
  ),
  handler: async (ctx, args) => {
    const perfil = await ctx.db.get(args.perfilId);
    if (!perfil) {
      return { sucesso: false as const, erro: "Perfil não encontrado" };
    }

    // Atualizar perfil
    const updates: any = {
      atualizadoEm: Date.now(),
    };

    if (args.nome !== undefined) updates.nome = args.nome;
    if (args.descricao !== undefined) updates.descricao = args.descricao;

    await ctx.db.patch(args.perfilId, updates);

    // Atualizar role correspondente se nome mudou
    if (args.nome !== undefined) {
      await ctx.db.patch(perfil.roleId, {
        nome: args.nome.toLowerCase().replace(/\s+/g, "_"),
      });
    }

    if (args.descricao !== undefined) {
      await ctx.db.patch(perfil.roleId, {
        descricao: args.descricao,
      });
    }

    // Log de atividade
    await registrarAtividade(
      ctx,
      args.editadoPorId,
      "editar",
      "perfis",
      JSON.stringify(updates),
      args.perfilId
    );

    return { sucesso: true as const };
  },
});

/**
 * Excluir perfil customizado (apenas TI_MASTER)
 */
export const excluirPerfilCustomizado = mutation({
  args: {
    perfilId: v.id("perfisCustomizados"),
    excluidoPorId: v.id("usuarios"),
  },
  returns: v.union(
    v.object({ sucesso: v.literal(true) }),
    v.object({ sucesso: v.literal(false), erro: v.string() })
  ),
  handler: async (ctx, args) => {
    const perfil = await ctx.db.get(args.perfilId);
    if (!perfil) {
      return { sucesso: false as const, erro: "Perfil não encontrado" };
    }

    // Verificar se existem usuários usando este perfil
    const usuarios = await ctx.db
      .query("usuarios")
      .withIndex("by_role", (q) => q.eq("roleId", perfil.roleId))
      .collect();

    if (usuarios.length > 0) {
      return {
        sucesso: false as const,
        erro: `Não é possível excluir. ${usuarios.length} usuário(s) ainda usa(m) este perfil.`,
      };
    }

    // Remover permissões associadas ao role
    const rolePermissoes = await ctx.db
      .query("rolePermissoes")
      .withIndex("by_role", (q) => q.eq("roleId", perfil.roleId))
      .collect();

    for (const rp of rolePermissoes) {
      await ctx.db.delete(rp._id);
    }

    // Remover permissões de menu
    const menuPermissoes = await ctx.db
      .query("menuPermissoes")
      .withIndex("by_role", (q) => q.eq("roleId", perfil.roleId))
      .collect();

    for (const mp of menuPermissoes) {
      await ctx.db.delete(mp._id);
    }

    // Excluir role
    await ctx.db.delete(perfil.roleId);

    // Excluir perfil
    await ctx.db.delete(args.perfilId);

    // Log de atividade
    await registrarAtividade(
      ctx,
      args.excluidoPorId,
      "excluir",
      "perfis",
      JSON.stringify({ perfilId: args.perfilId, nome: perfil.nome }),
      args.perfilId
    );

    return { sucesso: true as const };
  },
});

/**
 * Clonar perfil existente
 */
export const clonarPerfil = mutation({
  args: {
    perfilOrigemId: v.id("perfisCustomizados"),
    novoNome: v.string(),
    novaDescricao: v.string(),
    criadoPorId: v.id("usuarios"),
  },
  returns: v.union(
    v.object({ sucesso: v.literal(true), perfilId: v.id("perfisCustomizados") }),
    v.object({ sucesso: v.literal(false), erro: v.string() })
  ),
  handler: async (ctx, args) => {
    const perfilOrigem = await ctx.db.get(args.perfilOrigemId);
    if (!perfilOrigem) {
      return { sucesso: false as const, erro: "Perfil origem não encontrado" };
    }

    // Criar novo perfil clonando o original
    const resultado = await criarPerfilCustomizado(ctx, {
      nome: args.novoNome,
      descricao: args.novaDescricao,
      nivel: perfilOrigem.nivel,
      clonarDeRoleId: perfilOrigem.roleId,
      criadoPorId: args.criadoPorId,
    });

    return resultado;
  },
});


