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

import { requireAdmin } from "./rbac";

export const list = query({
  args: { tenantId: v.string(), viewerId: v.id("users") },
  handler: async (ctx, { tenantId, viewerId }) => {
    await requireAdmin(ctx, viewerId, tenantId);

    const invites = await ctx.db
      .query("userInvites")
      .withIndex("by_tenant", (q) => q.eq("tenantId", tenantId))
      .collect();

    return invites
      .sort((a, b) => (b.createdAt ?? 0) - (a.createdAt ?? 0))
      .map((invite) => ({
        id: invite._id,
        inviteId: invite.inviteId,
        email: invite.email,
        name: invite.name ?? null,
        role: invite.role,
        status: invite.status,
        token: invite.token,
        expiresAt: invite.expiresAt,
        createdAt: invite.createdAt,
        createdById: invite.createdById ?? null,
        acceptedAt: invite.acceptedAt ?? null,
        acceptedById: invite.acceptedById ?? null,
        revokedAt: invite.revokedAt ?? null,
        revokedById: invite.revokedById ?? null,
        revokedReason: invite.revokedReason ?? null,
      }));
  },
});

export const sync = mutation({
  args: {
    tenantId: v.string(),
    inviteId: v.string(),
    email: v.string(),
    name: v.optional(v.string()),
    role: v.string(),
    status: v.string(),
    token: v.string(),
    expiresAt: v.number(),
    createdAt: v.number(),
    createdById: v.optional(v.string()),
    acceptedAt: v.optional(v.number()),
    acceptedById: v.optional(v.string()),
    revokedAt: v.optional(v.number()),
    revokedById: v.optional(v.string()),
    revokedReason: v.optional(v.string()),
  },
  handler: async (ctx, args) => {
    const existing = await ctx.db
      .query("userInvites")
      .withIndex("by_invite", (q) => q.eq("tenantId", args.tenantId).eq("inviteId", args.inviteId))
      .first();

    if (!existing) {
      const id = await ctx.db.insert("userInvites", {
        tenantId: args.tenantId,
        inviteId: args.inviteId,
        email: args.email,
        name: args.name,
        role: args.role,
        status: args.status,
        token: args.token,
        expiresAt: args.expiresAt,
        createdAt: args.createdAt,
        createdById: args.createdById,
        acceptedAt: args.acceptedAt,
        acceptedById: args.acceptedById,
        revokedAt: args.revokedAt,
        revokedById: args.revokedById,
        revokedReason: args.revokedReason,
      });
      return await ctx.db.get(id);
    }

    await ctx.db.patch(existing._id, {
      email: args.email,
      name: args.name,
      role: args.role,
      status: args.status,
      token: args.token,
      expiresAt: args.expiresAt,
      createdAt: args.createdAt,
      createdById: args.createdById,
      acceptedAt: args.acceptedAt,
      acceptedById: args.acceptedById,
      revokedAt: args.revokedAt,
      revokedById: args.revokedById,
      revokedReason: args.revokedReason,
    });

    return await ctx.db.get(existing._id);
  },
});

export const remove = mutation({
  args: { tenantId: v.string(), inviteId: v.string() },
  handler: async (ctx, { tenantId, inviteId }) => {
    const existing = await ctx.db
      .query("userInvites")
      .withIndex("by_invite", (q) => q.eq("tenantId", tenantId).eq("inviteId", inviteId))
      .first();

    if (existing) {
      await ctx.db.delete(existing._id);
    }
  },
});
