import { NextResponse } from "next/server"

import type { Id } from "@/convex/_generated/dataModel"
import { api } from "@/convex/_generated/api"
import { DEFAULT_TENANT_ID } from "@/lib/constants"
import { assertStaffSession } from "@/lib/auth-server"
import { isAdmin } from "@/lib/authz"
import { prisma } from "@/lib/prisma"
import { createConvexClient } from "@/server/convex-client"

const DEFAULT_KEEP_EMAILS = ["renan.pac@paulicon.com.br"]

type CleanupSummary = {
  removedPortalUserIds: string[]
  removedPortalEmails: string[]
  removedAuthUserIds: string[]
  removedConvexUserIds: string[]
  removedTicketIds: string[]
  convictTicketsDeleted: number
  keepEmails: string[]
}

export const runtime = "nodejs"

export async function POST(request: Request) {
  const session = await assertStaffSession()
  if (!session) {
    return NextResponse.json({ error: "Não autorizado" }, { status: 401 })
  }

  if (!isAdmin(session.user.role)) {
    return NextResponse.json({ error: "Apenas administradores podem remover dados." }, { status: 403 })
  }

  const tenantId = session.user.tenantId ?? DEFAULT_TENANT_ID
  const sessionEmail = session.user.email?.toLowerCase()
  if (!sessionEmail) {
    return NextResponse.json({ error: "Administrador sem e-mail associado." }, { status: 400 })
  }

  const body = await request.json().catch(() => ({})) as { keepEmails?: string[] }
  const keepEmailsInput = Array.isArray(body.keepEmails) ? body.keepEmails : []
  const keepEmailsSet = new Set<string>()
  DEFAULT_KEEP_EMAILS.forEach((email) => keepEmailsSet.add(email.toLowerCase()))
  keepEmailsInput
    .map((email) => (typeof email === "string" ? email.trim().toLowerCase() : ""))
    .filter((email) => email.length > 0)
    .forEach((email) => keepEmailsSet.add(email))

  keepEmailsSet.add(sessionEmail)
  const viewerEmail = sessionEmail

  const portalUsers = await prisma.user.findMany({
    where: { tenantId },
    select: { id: true, email: true },
  })

  const portalToRemove = portalUsers.filter((user) => !keepEmailsSet.has(user.email.toLowerCase()))
  const portalIdsToRemove = portalToRemove.map((user) => user.id)
  const portalEmailsToRemove = portalToRemove.map((user) => user.email.toLowerCase())

  const responseSummary: CleanupSummary = {
    removedPortalUserIds: portalIdsToRemove,
    removedPortalEmails: portalEmailsToRemove,
    removedAuthUserIds: [],
    removedConvexUserIds: [],
    removedTicketIds: [],
    convictTicketsDeleted: 0,
    keepEmails: Array.from(keepEmailsSet),
  }

  if (portalIdsToRemove.length > 0) {
    const ticketsToRemove = await prisma.ticket.findMany({
      where: {
        tenantId,
        OR: [{ requesterId: { in: portalIdsToRemove } }, { assigneeId: { in: portalIdsToRemove } }],
      },
      select: { id: true },
    })
    responseSummary.removedTicketIds = ticketsToRemove.map((ticket) => ticket.id)

    await prisma.$transaction(async (tx) => {
      if (ticketsToRemove.length > 0) {
        await tx.ticket.deleteMany({
          where: { id: { in: ticketsToRemove.map((ticket) => ticket.id) } },
        })
      }

      if (portalEmailsToRemove.length > 0) {
        const authUsers = await tx.authUser.findMany({
          where: { email: { in: portalEmailsToRemove } },
          select: { id: true },
        })
        if (authUsers.length > 0) {
          const authIds = authUsers.map((item) => item.id)
          responseSummary.removedAuthUserIds = authIds
          await tx.authSession.deleteMany({ where: { userId: { in: authIds } } })
          await tx.authAccount.deleteMany({ where: { userId: { in: authIds } } })
          await tx.authUser.deleteMany({ where: { id: { in: authIds } } })
        }
      }

      await tx.user.deleteMany({
        where: { id: { in: portalIdsToRemove } },
      })
    })
  }

  try {
    const client = createConvexClient()
    const actor =
      (await client.query(api.users.findByEmail, { tenantId, email: sessionEmail })) ??
      (await client.mutation(api.users.ensureUser, {
        tenantId,
        email: sessionEmail,
        name: session.user.name ?? sessionEmail,
      }))

    const actorId = actor?._id as Id<"users"> | undefined
    if (actorId) {
      const convexCustomers = await client.query(api.users.listCustomers, {
        tenantId,
        viewerId: actorId,
      })

      const convexToRemove = convexCustomers.filter(
        (customer) => !keepEmailsSet.has(customer.email.toLowerCase()),
      )

      const removedConvexIds: Id<"users">[] = []
      for (const customer of convexToRemove) {
        const userId = customer.id as Id<"users">
        try {
          await client.mutation(api.users.deleteUser, { userId, actorId })
          removedConvexIds.push(userId)
        } catch (error) {
          console.error("[users.cleanup] Falha ao remover usuário do Convex", customer.email, error)
        }
      }
      responseSummary.removedConvexUserIds = removedConvexIds.map((id) => id as unknown as string)

      if (removedConvexIds.length > 0) {
        try {
          const result = await client.mutation(api.tickets.purgeTicketsForUsers, {
            tenantId,
            actorId,
            userIds: removedConvexIds,
          })
          responseSummary.convictTicketsDeleted = typeof result?.deleted === "number" ? result.deleted : 0
        } catch (error) {
          console.error("[users.cleanup] Falha ao remover tickets no Convex", error)
        }
      }
    }
  } catch (error) {
    console.error("[users.cleanup] Convex indisponível", error)
  }

  return NextResponse.json(responseSummary)
}
