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

// Criar uma nova solicitação de acesso
export const create = mutation({
  args: {
    nome: v.string(),
    matricula: v.string(),
    email: v.string(),
    telefone: v.string(),
  },
  returns: v.object({
    solicitacaoId: v.id("solicitacoesAcesso"),
  }),
  handler: async (ctx, args) => {
    // Verificar se já existe uma solicitação pendente com a mesma matrícula
    const existingByMatricula = await ctx.db
      .query("solicitacoesAcesso")
      .withIndex("by_matricula", (q) => q.eq("matricula", args.matricula))
      .filter((q) => q.eq(q.field("status"), "pendente"))
      .first();

    if (existingByMatricula) {
      throw new Error("Já existe uma solicitação pendente para esta matrícula.");
    }

    // Verificar se já existe uma solicitação pendente com o mesmo email
    const existingByEmail = await ctx.db
      .query("solicitacoesAcesso")
      .withIndex("by_email", (q) => q.eq("email", args.email))
      .filter((q) => q.eq(q.field("status"), "pendente"))
      .first();

    if (existingByEmail) {
      throw new Error("Já existe uma solicitação pendente para este e-mail.");
    }

    const solicitacaoId = await ctx.db.insert("solicitacoesAcesso", {
      nome: args.nome,
      matricula: args.matricula,
      email: args.email,
      telefone: args.telefone,
      status: "pendente",
      dataSolicitacao: Date.now(),
    });

    return { solicitacaoId };
  },
});

// Listar todas as solicitações (para o painel administrativo)
export const getAll = query({
  args: {},
  returns: v.array(
    v.object({
      _id: v.id("solicitacoesAcesso"),
      _creationTime: v.number(),
      nome: v.string(),
      matricula: v.string(),
      email: v.string(),
      telefone: v.string(),
      status: v.union(
        v.literal("pendente"),
        v.literal("aprovado"),
        v.literal("rejeitado")
      ),
      dataSolicitacao: v.number(),
      dataResposta: v.union(v.number(), v.null()),
      observacoes: v.union(v.string(), v.null()),
    })
  ),
  handler: async (ctx) => {
    const solicitacoes = await ctx.db
      .query("solicitacoesAcesso")
      .order("desc")
      .collect();

    return solicitacoes.map((s) => ({
      _id: s._id,
      _creationTime: s._creationTime,
      nome: s.nome,
      matricula: s.matricula,
      email: s.email,
      telefone: s.telefone,
      status: s.status,
      dataSolicitacao: s.dataSolicitacao,
      dataResposta: s.dataResposta ?? null,
      observacoes: s.observacoes ?? null,
    }));
  },
});

// Listar apenas solicitações pendentes
export const getPendentes = query({
  args: {},
  returns: v.array(
    v.object({
      _id: v.id("solicitacoesAcesso"),
      _creationTime: v.number(),
      nome: v.string(),
      matricula: v.string(),
      email: v.string(),
      telefone: v.string(),
      status: v.union(
        v.literal("pendente"),
        v.literal("aprovado"),
        v.literal("rejeitado")
      ),
      dataSolicitacao: v.number(),
      dataResposta: v.union(v.number(), v.null()),
      observacoes: v.union(v.string(), v.null()),
    })
  ),
  handler: async (ctx) => {
    const solicitacoes = await ctx.db
      .query("solicitacoesAcesso")
      .withIndex("by_status", (q) => q.eq("status", "pendente"))
      .order("desc")
      .collect();

    return solicitacoes.map((s) => ({
      _id: s._id,
      _creationTime: s._creationTime,
      nome: s.nome,
      matricula: s.matricula,
      email: s.email,
      telefone: s.telefone,
      status: s.status,
      dataSolicitacao: s.dataSolicitacao,
      dataResposta: s.dataResposta ?? null,
      observacoes: s.observacoes ?? null,
    }));
  },
});

// Aprovar uma solicitação
export const aprovar = mutation({
  args: {
    solicitacaoId: v.id("solicitacoesAcesso"),
    observacoes: v.optional(v.string()),
  },
  returns: v.null(),
  handler: async (ctx, args) => {
    const solicitacao = await ctx.db.get(args.solicitacaoId);
    if (!solicitacao) {
      throw new Error("Solicitação não encontrada.");
    }

    if (solicitacao.status !== "pendente") {
      throw new Error("Esta solicitação já foi processada.");
    }

    await ctx.db.patch(args.solicitacaoId, {
      status: "aprovado",
      dataResposta: Date.now(),
      observacoes: args.observacoes,
    });

    return null;
  },
});

// Rejeitar uma solicitação
export const rejeitar = mutation({
  args: {
    solicitacaoId: v.id("solicitacoesAcesso"),
    observacoes: v.optional(v.string()),
  },
  returns: v.null(),
  handler: async (ctx, args) => {
    const solicitacao = await ctx.db.get(args.solicitacaoId);
    if (!solicitacao) {
      throw new Error("Solicitação não encontrada.");
    }

    if (solicitacao.status !== "pendente") {
      throw new Error("Esta solicitação já foi processada.");
    }

    await ctx.db.patch(args.solicitacaoId, {
      status: "rejeitado",
      dataResposta: Date.now(),
      observacoes: args.observacoes,
    });

    return null;
  },
});

// Obter uma solicitação por ID
export const getById = query({
  args: {
    solicitacaoId: v.id("solicitacoesAcesso"),
  },
  returns: v.union(
    v.object({
      _id: v.id("solicitacoesAcesso"),
      _creationTime: v.number(),
      nome: v.string(),
      matricula: v.string(),
      email: v.string(),
      telefone: v.string(),
      status: v.union(
        v.literal("pendente"),
        v.literal("aprovado"),
        v.literal("rejeitado")
      ),
      dataSolicitacao: v.number(),
      dataResposta: v.union(v.number(), v.null()),
      observacoes: v.union(v.string(), v.null()),
    }),
    v.null()
  ),
  handler: async (ctx, args) => {
    const solicitacao = await ctx.db.get(args.solicitacaoId);
    if (!solicitacao) {
      return null;
    }

    return {
      _id: solicitacao._id,
      _creationTime: solicitacao._creationTime,
      nome: solicitacao.nome,
      matricula: solicitacao.matricula,
      email: solicitacao.email,
      telefone: solicitacao.telefone,
      status: solicitacao.status,
      dataSolicitacao: solicitacao.dataSolicitacao,
      dataResposta: solicitacao.dataResposta ?? null,
      observacoes: solicitacao.observacoes ?? null,
    };
  },
});

