import { NextResponse } from "next/server"
import { randomBytes } from "crypto"

import { hashPassword } from "better-auth/crypto"
import { ConvexHttpClient } from "convex/browser"

import { api } from "@/convex/_generated/api"
import { prisma } from "@/lib/prisma"
import { DEFAULT_TENANT_ID } from "@/lib/constants"
import { assertAdminSession } from "@/lib/auth-server"
import { ROLE_OPTIONS, type RoleOption } from "@/lib/authz"

export const runtime = "nodejs"

function normalizeRole(input: string | null | undefined): RoleOption {
  const role = (input ?? "agent").toLowerCase() as RoleOption
  return (ROLE_OPTIONS as readonly string[]).includes(role) ? role : "agent"
}

function generatePassword(length = 12) {
  const bytes = randomBytes(length)
  return Array.from(bytes)
    .map((byte) => (byte % 36).toString(36))
    .join("")
}

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

  const users = await prisma.authUser.findMany({
    orderBy: { createdAt: "desc" },
    select: {
      id: true,
      email: true,
      name: true,
      role: true,
      tenantId: true,
      createdAt: true,
      updatedAt: true,
    },
  })

  return NextResponse.json({ users })
}

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

  const payload = await request.json().catch(() => null)
  if (!payload || typeof payload !== "object") {
    return NextResponse.json({ error: "Payload inválido" }, { status: 400 })
  }

  const emailInput = typeof payload.email === "string" ? payload.email.trim().toLowerCase() : ""
  const nameInput = typeof payload.name === "string" ? payload.name.trim() : ""
  const roleInput = typeof payload.role === "string" ? payload.role : undefined
  const tenantInput = typeof payload.tenantId === "string" ? payload.tenantId.trim() : undefined

  if (!emailInput || !emailInput.includes("@")) {
    return NextResponse.json({ error: "Informe um e-mail válido" }, { status: 400 })
  }

  const role = normalizeRole(roleInput)
  const tenantId = tenantInput || session.user.tenantId || DEFAULT_TENANT_ID

  const existing = await prisma.authUser.findUnique({ where: { email: emailInput } })
  if (existing) {
    return NextResponse.json({ error: "Já existe um usuário com este e-mail" }, { status: 409 })
  }

  const password = generatePassword()
  const hashedPassword = await hashPassword(password)

  const user = await prisma.authUser.create({
    data: {
      email: emailInput,
      name: nameInput || emailInput,
      role,
      tenantId,
      accounts: {
        create: {
          providerId: "credential",
          accountId: emailInput,
          password: hashedPassword,
        },
      },
    },
    select: {
      id: true,
      email: true,
      name: true,
      role: true,
      tenantId: true,
      createdAt: true,
    },
  })

  const convexUrl = process.env.NEXT_PUBLIC_CONVEX_URL
  if (convexUrl) {
    try {
      const convex = new ConvexHttpClient(convexUrl)
      await convex.mutation(api.users.ensureUser, {
        tenantId,
        email: emailInput,
        name: nameInput || emailInput,
        avatarUrl: undefined,
        role: role.toUpperCase(),
      })
    } catch (error) {
      console.warn("Falha ao sincronizar usuário no Convex", error)
    }
  }

  return NextResponse.json({ user, temporaryPassword: password })
}
