import { NextResponse } from "next/server"
import { getSession } from "@/server/session"
import { prisma } from "@/server/db"
import { editSmtpUser, emailBounces, removeSmtpUser, viewSmtpUsers } from "@/server/smtp2go"
import { cnpjMatches } from "@/server/cnpj"

const SMTP_DESCRIPTION_MAX = 120

async function enrichUsersWithBouncesLimited(users: Array<Record<string, unknown>>) {
  const results: Array<Record<string, unknown>> = []
  const queue = [...users]
  const workers = Array.from({ length: 3 }).map(async () => {
    while (queue.length > 0) {
      const user = queue.shift()
      if (!user) continue
      const username = typeof user.username === "string" ? user.username : ""
      if (!username) {
        results.push({ ...user })
        continue
      }
      try {
        const stats = await emailBounces({ username })
        results.push({ ...user, spam: stats })
      } catch {
        results.push({ ...user, spam: null })
      }
    }
  })
  await Promise.all(workers)
  return results
}

async function ensureClientSubaccountAccess(subaccountId: string) {
  const session = await getSession()
  const user = session.user
  if (!user) {
    return { error: "UNAUTHORIZED", status: 401 as const }
  }
  if (user.role === "ADMIN" || user.role === "SUPPORT") {
    return { error: "FORBIDDEN", status: 403 as const }
  }
  const cnpj = user.cnpj?.trim()
  if (!cnpj) {
    return { error: "FORBIDDEN_NO_CNPJ", status: 403 as const }
  }

  if (!subaccountId) {
    return { error: "MISSING_SUBACCOUNT_ID", status: 400 as const }
  }

  const meta = await prisma.subaccountMeta.findUnique({
    where: { subaccountId },
  })
  if (!meta || !cnpjMatches(meta.cnpj, cnpj)) {
    return { error: "FORBIDDEN_SUBACCOUNT", status: 403 as const }
  }

  return { ok: true as const }
}

export async function GET(
  _req: Request,
  { params }: { params: Promise<{ subaccountId: string }> }
) {
  const { subaccountId } = await params
  const access = await ensureClientSubaccountAccess(subaccountId)
  if (!("ok" in access)) {
    return NextResponse.json({ error: access.error }, { status: access.status })
  }

  try {
    const data = await viewSmtpUsers({ subaccount_id: subaccountId })
    const users = data?.results ?? []
    const enriched = await enrichUsersWithBouncesLimited(users as Array<Record<string, unknown>>)
    return NextResponse.json({ results: enriched })
  } catch (e: unknown) {
    const msg = e instanceof Error ? e.message : String(e ?? "")
    return NextResponse.json({ error: msg || "SMTP_USERS_ERROR" }, { status: 500 })
  }
}

export async function PATCH(
  req: Request,
  { params }: { params: Promise<{ subaccountId: string }> }
) {
  const { subaccountId } = await params
  const access = await ensureClientSubaccountAccess(subaccountId)
  if (!("ok" in access)) {
    return NextResponse.json({ error: access.error }, { status: access.status })
  }

  const body = await req.json().catch(() => null)
  const username = String(body?.username ?? "").trim()
  const description = body?.description ? String(body.description).trim() : null
  if (!username) {
    return NextResponse.json({ error: "MISSING_USERNAME" }, { status: 400 })
  }
  if (description && description.length > SMTP_DESCRIPTION_MAX) {
    return NextResponse.json({ error: `DESCRIPTION_TOO_LONG_${SMTP_DESCRIPTION_MAX}` }, { status: 400 })
  }

  try {
    const data = await editSmtpUser({
      subaccount_id: subaccountId,
      username,
      email_password: body?.email_password ? String(body.email_password) : null,
      description,
    })
    return NextResponse.json({ ok: true, data })
  } catch (e: unknown) {
    const msg = e instanceof Error ? e.message : String(e ?? "")
    const status = msg.includes("SMTP2GO_HTTP_400") ? 400 : 500
    return NextResponse.json({ error: msg || "SMTP_EDIT_USER_ERROR" }, { status })
  }
}

export async function DELETE(
  req: Request,
  { params }: { params: Promise<{ subaccountId: string }> }
) {
  const { subaccountId } = await params
  const access = await ensureClientSubaccountAccess(subaccountId)
  if (!("ok" in access)) {
    return NextResponse.json({ error: access.error }, { status: access.status })
  }

  const body = await req.json().catch(() => null)
  const username = String(body?.username ?? "").trim()
  if (!username) {
    return NextResponse.json({ error: "MISSING_USERNAME" }, { status: 400 })
  }

  try {
    const data = await removeSmtpUser({ subaccount_id: subaccountId, username })
    return NextResponse.json({ ok: true, data })
  } catch (e: unknown) {
    const msg = e instanceof Error ? e.message : String(e ?? "")
    const status = msg.includes("SMTP2GO_HTTP_400") ? 400 : 500
    return NextResponse.json({ error: msg || "SMTP_REMOVE_USER_ERROR" }, { status })
  }
}
