import { NextResponse, type NextRequest } from 'next/server'
import { jwtVerify } from 'jose'
import { API_LIMITS, clientIp, rateLimit } from '@/lib/security/rate-limit'

const SESSION_COOKIE = 'hha_session'

/** Routes that require a signed-in session. */
const PROTECTED_PREFIXES = [
  '/dashboard',
  '/trips',
  '/history',
  '/billing',
  '/purchases',
  // Role routes (2026-09-13): <abbr>-dashboard and <abbr>-trip-workspace/<trip number>.
  '/fb-dashboard', '/cd-dashboard', '/pd-dashboard', '/ct-dashboard', '/pc-dashboard', '/fb-new-trip-request', '/fb-new-trip', '/cd-new-trip', '/pd-new-trip',
  '/fb-trip-workspace', '/cd-trip-workspace', '/pd-trip-workspace', '/ct-trip-workspace', '/pc-trip-workspace',
]

async function hasValidSession(request: NextRequest): Promise<boolean> {
  const token = request.cookies.get(SESSION_COOKIE)?.value
  if (!token || !process.env.AUTH_SECRET) return false
  try {
    await jwtVerify(token, new TextEncoder().encode(process.env.AUTH_SECRET))
    return true
  } catch {
    return false
  }
}

/**
 * Runs on every request except static assets (2026-09-22):
 *
 *   1. HTTPS only in production — the app sits behind Apache; when the proxy
 *      says the visitor came in over plain http, send them to https. Apache
 *      should redirect too (docs/SECURITY-CONTROLS.md); this is the backstop.
 *   2. API rate limit per IP across /api/* (429 with Retry-After).
 *   3. Protected pages need a validly-signed session cookie.
 *
 * The proxy only checks that a session cookie is a validly-signed JWT. It
 * cannot see revocation (an admin password reset or role change, 2026-09-11)
 * without a database call on every request, so it deliberately does NOT send
 * `/login` visitors to the dashboard any more: a revoked-but-well-signed
 * cookie would have bounced /login → /dashboard → /login forever. The
 * "already signed in" redirect lives in `app/(auth)/login/layout.tsx`, which
 * uses getSessionUser and therefore respects revocation.
 */
export async function proxy(request: NextRequest) {
  const { pathname } = request.nextUrl

  if (process.env.NODE_ENV === 'production' && request.headers.get('x-forwarded-proto') === 'http') {
    const secure = request.nextUrl.clone()
    secure.protocol = 'https:'
    return NextResponse.redirect(secure, 308)
  }

  if (pathname.startsWith('/api/')) {
    const r = rateLimit(`api:${clientIp(request.headers)}`, API_LIMITS.perIp, API_LIMITS.windowMs)
    if (!r.allowed) {
      return NextResponse.json({ error: 'Too many requests. Slow down and try again.' }, { status: 429, headers: { 'Retry-After': String(r.retryAfterSeconds) } })
    }
    return NextResponse.next()
  }

  const needsAuth = PROTECTED_PREFIXES.some((p) => pathname === p || pathname.startsWith(`${p}/`))
  if (!needsAuth) return NextResponse.next()
  if (await hasValidSession(request)) return NextResponse.next()

  const login = request.nextUrl.clone()
  login.pathname = '/login'
  login.search = `?next=${encodeURIComponent(pathname)}`
  return NextResponse.redirect(login)
}

export const config = {
  // Everything except Next's static assets and the favicon.
  matcher: ['/((?!_next/static|_next/image|favicon.ico|.*\\.(?:png|jpg|jpeg|svg|ico|webp|txt|xml)$).*)'],
}
