import 'server-only'

import { redirect } from 'next/navigation'
import { NextResponse } from 'next/server'
import { getProfile, getSessionUser, type SessionUser } from '@/lib/auth'
import { canAccessSurface, canManageAccess, surfaceByKey, type SurfaceKey } from '@/lib/domain/moderator-access'
import { touchAccess } from '@/lib/data/moderator-access'
import { logSecurityEvent } from '@/lib/security/events'
import type { Profile } from '@/types/db'

/**
 * One gate for every moderator page and its API routes (Nash, 2026-09-23).
 * The platform admin opens everything; anyone else needs a grant for that
 * exact page. A customer who lands on one is sent to their dashboard, and
 * the refusal is logged.
 */
export async function requireSurface(key: SurfaceKey): Promise<{ user: SessionUser; profile: Profile; canManage: boolean }> {
  const surface = surfaceByKey(key)
  const user = await getSessionUser()
  if (!user) redirect(`/login?next=${encodeURIComponent(surface?.path ?? '/dashboard')}`)
  if (!canAccessSurface(user, key)) {
    await logSecurityEvent({ event: 'moderator_access_denied', username: user.email, userId: user.id, actorUserId: user.id, actorLabel: user.name || user.email, detail: { surface: key, path: surface?.path } })
    redirect('/dashboard')
  }
  const profile = (await getProfile())!
  if (user.role !== 'admin') void touchAccess(user.email, key).catch(() => undefined)
  return { user, profile, canManage: canManageAccess(user) }
}

export type SurfaceGuard =
  | { ok: true; user: SessionUser; actor: { id: string; label: string; email: string; ip: string | null }; canManage: boolean }
  | { ok: false; response: NextResponse }

/** The same rule for an API route. Pass the caller's IP when the route has it. */
export async function requireSurfaceApi(key: SurfaceKey, ip: string | null = null): Promise<SurfaceGuard> {
  const user = await getSessionUser()
  if (!user) return { ok: false, response: NextResponse.json({ error: 'Sign in first.' }, { status: 401 }) }
  if (!canAccessSurface(user, key)) {
    await logSecurityEvent({ event: 'moderator_access_denied', username: user.email, userId: user.id, actorUserId: user.id, actorLabel: user.name || user.email, ip, detail: { surface: key, api: true } })
    return { ok: false, response: NextResponse.json({ error: 'You do not have access to this page.' }, { status: 403 }) }
  }
  return { ok: true, user, actor: { id: user.id, label: user.name || user.email, email: user.email, ip }, canManage: canManageAccess(user) }
}
