import { NextResponse } from "next/server"

import { Prisma } from "@prisma/client"
import { ConvexHttpClient } from "convex/browser"

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, context: { params: Promise<{ id: string }> }) {
  const { id } = await context.params
  const session = await assertAdminSession()
  if (!session) {
    return NextResponse.json({ error: "Não autorizado" }, { status: 401 })
  }

  const body = (await request.json().catch(() => null)) as Partial<RevokePayload> | null
  const reason = typeof body?.reason === "string" && body.reason.trim() ? body.reason.trim() : null

  const invite = await prisma.authInvite.findUnique({
    where: { 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 } : Prisma.JsonNull,
      actorId: session.user.id ?? null,
    },
  })

  const normalized = normalizeInvite({ ...updated, events: [...invite.events, event] }, now)
  await syncInvite(normalized)

  return NextResponse.json({ invite: normalized })
}
