import { NextResponse } from "next/server" import { ConvexHttpClient } from "convex/browser" // @ts-expect-error Convex runtime API lacks generated types at build time in Next routes import { api } from "@/convex/_generated/api" import { assertAdminSession } from "@/lib/auth-server" import { env } from "@/lib/env" import { prisma } from "@/lib/prisma" import { computeInviteStatus, normalizeInvite, type NormalizedInvite } from "@/server/invite-utils" type RevokePayload = { reason?: string } async function syncInvite(invite: NormalizedInvite) { const convexUrl = env.NEXT_PUBLIC_CONVEX_URL if (!convexUrl) return const client = new ConvexHttpClient(convexUrl) await client.mutation(api.invites.sync, { tenantId: invite.tenantId, inviteId: invite.id, email: invite.email, name: invite.name ?? undefined, role: invite.role.toUpperCase(), status: invite.status, token: invite.token, expiresAt: Date.parse(invite.expiresAt), createdAt: Date.parse(invite.createdAt), createdById: invite.createdById ?? undefined, acceptedAt: invite.acceptedAt ? Date.parse(invite.acceptedAt) : undefined, acceptedById: invite.acceptedById ?? undefined, revokedAt: invite.revokedAt ? Date.parse(invite.revokedAt) : undefined, revokedById: invite.revokedById ?? undefined, revokedReason: invite.revokedReason ?? undefined, }) } export async function PATCH(request: Request, { params }: { params: { id: string } }) { const session = await assertAdminSession() if (!session) { return NextResponse.json({ error: "Não autorizado" }, { status: 401 }) } const body = (await request.json().catch(() => null)) as Partial | null const reason = typeof body?.reason === "string" && body.reason.trim() ? body.reason.trim() : null const invite = await prisma.authInvite.findUnique({ where: { id: params.id }, include: { events: { orderBy: { createdAt: "asc" } } }, }) if (!invite) { return NextResponse.json({ error: "Convite não encontrado" }, { status: 404 }) } const now = new Date() const status = computeInviteStatus(invite, now) if (status === "accepted") { return NextResponse.json({ error: "Convite já aceito" }, { status: 400 }) } if (status === "revoked") { const normalized = normalizeInvite(invite, now) await syncInvite(normalized) return NextResponse.json({ invite: normalized }) } const updated = await prisma.authInvite.update({ where: { id: invite.id }, data: { status: "revoked", revokedAt: now, revokedById: session.user.id ?? null, revokedReason: reason, }, }) const event = await prisma.authInviteEvent.create({ data: { inviteId: invite.id, type: "revoked", payload: reason ? { reason } : null, actorId: session.user.id ?? null, }, }) const normalized = normalizeInvite({ ...updated, events: [...invite.events, event] }, now) await syncInvite(normalized) return NextResponse.json({ invite: normalized }) }