import { getServerSession } from 'next-auth'
import { authOptions } from './auth-options'
import { NextResponse } from 'next/server'
import { hasPermission } from './permissions'

export async function getSession() {
  return await getServerSession(authOptions)
}

export async function requireAuth(allowedRoles?: string[]) {
  const session = await getSession()

  if (!session?.user) {
    throw new AuthError('Unauthorized', 401)
  }

  if (allowedRoles && !allowedRoles.includes((session.user as any).role)) {
    throw new AuthError('Forbidden: insufficient permissions', 403)
  }

  return { session, userId: (session.user as any).id as string, role: (session.user as any).role as string }
}

export async function requirePermission(module: string, action: string) {
  const ctx = await requireAuth()

  if (!hasPermission(ctx.role, module as any, action as any)) {
    throw new AuthError('Forbidden: insufficient permissions for this action', 403)
  }

  return ctx
}

export class AuthError extends Error {
  status: number
  constructor(message: string, status: number = 401) {
    super(message)
    this.name = 'AuthError'
    this.status = status
  }
}

export function safeHandler(
  handler: (req: Request, context?: any) => Promise<NextResponse>
) {
  return async (req: Request, context?: any): Promise<NextResponse> => {
    try {
      return await handler(req, context)
    } catch (error: unknown) {
      if (error instanceof AuthError) {
        return NextResponse.json(
          { message: error.message },
          { status: error.status }
        )
      }

      if (error && typeof error === 'object' && 'code' in error) {
        const prismaError = error as { code: string }
        if (prismaError.code === 'P2025') {
          return NextResponse.json({ message: 'Record not found' }, { status: 404 })
        }
        if (prismaError.code === 'P2002') {
          return NextResponse.json({ message: 'A record with this value already exists' }, { status: 409 })
        }
      }

      console.error(`[API Error] ${req.method} ${req.url}:`, error instanceof Error ? error.message : 'Unknown error')
      return NextResponse.json(
        { message: 'An internal error occurred' },
        { status: 500 }
      )
    }
  }
}
