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

// Query: Listar todos os times
export const listar = query({
  args: {},
  returns: v.array(v.any()),
  handler: async (ctx) => {
    const times = await ctx.db.query("times").collect();
    
    // Buscar gestor e contar membros de cada time
    const timesComDetalhes = await Promise.all(
      times.map(async (time) => {
        const gestor = await ctx.db.get(time.gestorId);
        const membrosAtivos = await ctx.db
          .query("timesMembros")
          .withIndex("by_time_and_ativo", (q) => q.eq("timeId", time._id).eq("ativo", true))
          .collect();
        
        return {
          ...time,
          gestor,
          totalMembros: membrosAtivos.length,
        };
      })
    );
    
    return timesComDetalhes;
  },
});

// Query: Obter time por ID com membros
export const obterPorId = query({
  args: { id: v.id("times") },
  returns: v.union(v.any(), v.null()),
  handler: async (ctx, args) => {
    const time = await ctx.db.get(args.id);
    if (!time) return null;
    
    const gestor = await ctx.db.get(time.gestorId);
    const membrosRelacoes = await ctx.db
      .query("timesMembros")
      .withIndex("by_time_and_ativo", (q) => q.eq("timeId", args.id).eq("ativo", true))
      .collect();
    
    // Buscar dados completos dos membros
    const membros = await Promise.all(
      membrosRelacoes.map(async (rel) => {
        const funcionario = await ctx.db.get(rel.funcionarioId);
        return {
          ...rel,
          funcionario,
        };
      })
    );
    
    return {
      ...time,
      gestor,
      membros,
    };
  },
});

// Query: Obter time do funcionário
export const obterTimeFuncionario = query({
  args: { funcionarioId: v.id("funcionarios") },
  returns: v.union(v.any(), v.null()),
  handler: async (ctx, args) => {
    const relacao = await ctx.db
      .query("timesMembros")
      .withIndex("by_funcionario", (q) => q.eq("funcionarioId", args.funcionarioId))
      .filter((q) => q.eq(q.field("ativo"), true))
      .first();
    
    if (!relacao) return null;
    
    const time = await ctx.db.get(relacao.timeId);
    if (!time) return null;
    
    const gestor = await ctx.db.get(time.gestorId);
    
    return {
      ...time,
      gestor,
    };
  },
});

// Query: Obter times do gestor
export const listarPorGestor = query({
  args: { gestorId: v.id("usuarios") },
  returns: v.array(v.any()),
  handler: async (ctx, args) => {
    const times = await ctx.db
      .query("times")
      .withIndex("by_gestor", (q) => q.eq("gestorId", args.gestorId))
      .filter((q) => q.eq(q.field("ativo"), true))
      .collect();
    
    const timesComMembros = await Promise.all(
      times.map(async (time) => {
        const membrosRelacoes = await ctx.db
          .query("timesMembros")
          .withIndex("by_time_and_ativo", (q) => q.eq("timeId", time._id).eq("ativo", true))
          .collect();
        
        const membros = await Promise.all(
          membrosRelacoes.map(async (rel) => {
            const funcionario = await ctx.db.get(rel.funcionarioId);
            return {
              ...rel,
              funcionario,
            };
          })
        );
        
        return {
          ...time,
          membros,
        };
      })
    );
    
    return timesComMembros;
  },
});

// Mutation: Criar time
export const criar = mutation({
  args: {
    nome: v.string(),
    descricao: v.optional(v.string()),
    gestorId: v.id("usuarios"),
    cor: v.optional(v.string()),
  },
  returns: v.id("times"),
  handler: async (ctx, args) => {
    const timeId = await ctx.db.insert("times", {
      nome: args.nome,
      descricao: args.descricao,
      gestorId: args.gestorId,
      ativo: true,
      cor: args.cor || "#3B82F6",
    });
    
    return timeId;
  },
});

// Mutation: Atualizar time
export const atualizar = mutation({
  args: {
    id: v.id("times"),
    nome: v.string(),
    descricao: v.optional(v.string()),
    gestorId: v.id("usuarios"),
    cor: v.optional(v.string()),
  },
  returns: v.null(),
  handler: async (ctx, args) => {
    const { id, ...dados } = args;
    await ctx.db.patch(id, dados);
    return null;
  },
});

// Mutation: Desativar time
export const desativar = mutation({
  args: { id: v.id("times") },
  returns: v.null(),
  handler: async (ctx, args) => {
    // Desativar o time
    await ctx.db.patch(args.id, { ativo: false });
    
    // Desativar todos os membros
    const membros = await ctx.db
      .query("timesMembros")
      .withIndex("by_time_and_ativo", (q) => q.eq("timeId", args.id).eq("ativo", true))
      .collect();
    
    for (const membro of membros) {
      await ctx.db.patch(membro._id, {
        ativo: false,
        dataSaida: Date.now(),
      });
    }
    
    return null;
  },
});

// Mutation: Adicionar membro ao time
export const adicionarMembro = mutation({
  args: {
    timeId: v.id("times"),
    funcionarioId: v.id("funcionarios"),
  },
  returns: v.id("timesMembros"),
  handler: async (ctx, args) => {
    // Verificar se já não está em outro time ativo
    const membroExistente = await ctx.db
      .query("timesMembros")
      .withIndex("by_funcionario", (q) => q.eq("funcionarioId", args.funcionarioId))
      .filter((q) => q.eq(q.field("ativo"), true))
      .first();
    
    if (membroExistente) {
      throw new Error("Funcionário já está em um time ativo");
    }
    
    const membroId = await ctx.db.insert("timesMembros", {
      timeId: args.timeId,
      funcionarioId: args.funcionarioId,
      dataEntrada: Date.now(),
      ativo: true,
    });
    
    return membroId;
  },
});

// Mutation: Remover membro do time
export const removerMembro = mutation({
  args: { membroId: v.id("timesMembros") },
  returns: v.null(),
  handler: async (ctx, args) => {
    await ctx.db.patch(args.membroId, {
      ativo: false,
      dataSaida: Date.now(),
    });
    return null;
  },
});

// Mutation: Transferir membro para outro time
export const transferirMembro = mutation({
  args: {
    funcionarioId: v.id("funcionarios"),
    novoTimeId: v.id("times"),
  },
  returns: v.null(),
  handler: async (ctx, args) => {
    // Desativar do time atual
    const relacaoAtual = await ctx.db
      .query("timesMembros")
      .withIndex("by_funcionario", (q) => q.eq("funcionarioId", args.funcionarioId))
      .filter((q) => q.eq(q.field("ativo"), true))
      .first();
    
    if (relacaoAtual) {
      await ctx.db.patch(relacaoAtual._id, {
        ativo: false,
        dataSaida: Date.now(),
      });
    }
    
    // Adicionar ao novo time
    await ctx.db.insert("timesMembros", {
      timeId: args.novoTimeId,
      funcionarioId: args.funcionarioId,
      dataEntrada: Date.now(),
      ativo: true,
    });
    
    return null;
  },
});

