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

/**
 * Helper function para registrar atividades no sistema
 * Use em todas as mutations que modificam dados
 */
export async function registrarAtividade(
  ctx: QueryCtx | MutationCtx,
  usuarioId: Id<"usuarios">,
  acao: string,
  recurso: string,
  detalhes?: string,
  recursoId?: string
) {
  await ctx.db.insert("logsAtividades", {
    usuarioId,
    acao,
    recurso,
    recursoId,
    detalhes,
    timestamp: Date.now(),
  });
}

/**
 * Lista atividades com filtros
 */
export const listarAtividades = query({
  args: {
    usuarioId: v.optional(v.id("usuarios")),
    acao: v.optional(v.string()),
    recurso: v.optional(v.string()),
    dataInicio: v.optional(v.number()),
    dataFim: v.optional(v.number()),
    limite: v.optional(v.number()),
  },
  handler: async (ctx, args) => {
    let query = ctx.db.query("logsAtividades");

    // Aplicar filtros
    if (args.usuarioId) {
      query = query.withIndex("by_usuario", (q) => q.eq("usuarioId", args.usuarioId));
    } else if (args.acao) {
      query = query.withIndex("by_acao", (q) => q.eq("acao", args.acao));
    } else if (args.recurso) {
      query = query.withIndex("by_recurso", (q) => q.eq("recurso", args.recurso));
    } else {
      query = query.withIndex("by_timestamp");
    }

    let atividades = await query.order("desc").take(args.limite || 100);

    // Filtrar por range de datas se fornecido
    if (args.dataInicio || args.dataFim) {
      atividades = atividades.filter((log) => {
        if (args.dataInicio && log.timestamp < args.dataInicio) return false;
        if (args.dataFim && log.timestamp > args.dataFim) return false;
        return true;
      });
    }

    // Buscar informações dos usuários
    const atividadesComUsuarios = await Promise.all(
      atividades.map(async (atividade) => {
        const usuario = await ctx.db.get(atividade.usuarioId);
        return {
          ...atividade,
          usuarioNome: usuario?.nome || "Usuário Desconhecido",
          usuarioMatricula: usuario?.matricula || "N/A",
        };
      })
    );

    return atividadesComUsuarios;
  },
});

/**
 * Obtém estatísticas de atividades
 */
export const obterEstatisticasAtividades = query({
  args: {
    periodo: v.optional(v.number()), // dias (ex: 7, 30)
  },
  handler: async (ctx, args) => {
    const periodo = args.periodo || 30;
    const dataInicio = Date.now() - periodo * 24 * 60 * 60 * 1000;

    const atividades = await ctx.db
      .query("logsAtividades")
      .withIndex("by_timestamp")
      .filter((q) => q.gte(q.field("timestamp"), dataInicio))
      .collect();

    // Agrupar por ação
    const porAcao: Record<string, number> = {};
    atividades.forEach((ativ) => {
      porAcao[ativ.acao] = (porAcao[ativ.acao] || 0) + 1;
    });

    // Agrupar por recurso
    const porRecurso: Record<string, number> = {};
    atividades.forEach((ativ) => {
      porRecurso[ativ.recurso] = (porRecurso[ativ.recurso] || 0) + 1;
    });

    // Agrupar por dia
    const porDia: Record<string, number> = {};
    atividades.forEach((ativ) => {
      const data = new Date(ativ.timestamp);
      const dia = data.toISOString().split("T")[0];
      porDia[dia] = (porDia[dia] || 0) + 1;
    });

    return {
      total: atividades.length,
      porAcao,
      porRecurso,
      porDia,
    };
  },
});

/**
 * Obtém histórico de atividades de um recurso específico
 */
export const obterHistoricoRecurso = query({
  args: {
    recurso: v.string(),
    recursoId: v.string(),
  },
  handler: async (ctx, args) => {
    const atividades = await ctx.db
      .query("logsAtividades")
      .withIndex("by_recurso_id", (q) =>
        q.eq("recurso", args.recurso).eq("recursoId", args.recursoId)
      )
      .order("desc")
      .collect();

    // Buscar informações dos usuários
    const atividadesComUsuarios = await Promise.all(
      atividades.map(async (atividade) => {
        const usuario = await ctx.db.get(atividade.usuarioId);
        return {
          ...atividade,
          usuarioNome: usuario?.nome || "Usuário Desconhecido",
          usuarioMatricula: usuario?.matricula || "N/A",
        };
      })
    );

    return atividadesComUsuarios;
  },
});


