import { NextResponse } from 'next/server';
import { auth } from './lib/auth';
import { hasValidApiKey } from './lib/api-auth';
import { isValidToken } from './app/api/auth/verify/route';

// Node runtime: the auth() wrapper decodes the NextAuth session JWT with the
// AUTH_SECRET that the route layer also uses (auto-generated in-process when
// unset). That secret is NOT visible to the Edge runtime, and lib/auth pulls in
// node:crypto — so this proxy must run in Node. The wrapper populates
// req.auth with the VALIDATED session (null for a forged/unsigned cookie),
// replacing the old presence-only cookie check that let any cookie through.
// (Next 16 renamed middleware.ts → proxy.ts; the auth() handler is exported
// under the `proxy` name the new convention expects.)
export const proxy = auth((req) => {
  // Skip auth entirely in dev mode
  const isDev = process.env.NODE_ENV !== 'production' || process.env.FORGE_DEV === '1';
  if (isDev) {
    return NextResponse.next();
  }

  const { pathname } = req.nextUrl;

  // Allow auth endpoints, version probe (used by IDE plugins to detect a live
  // server before prompting for password), and static assets without login.
  // These /api/auth/* routes self-validate any credential at the handler, so they
  // need no edge check.
  if (
    pathname.startsWith('/login') ||
    pathname.startsWith('/api/auth') ||
    pathname === '/api/version' ||
    pathname === '/api/bridge-info' ||
    pathname.startsWith('/api/telegram') ||
    (pathname.startsWith('/api/workspace') && (pathname.endsWith('/smith') || pathname === '/api/workspace')) ||
    pathname.startsWith('/_next') ||
    pathname === '/favicon.ico' ||
    pathname === '/icon.png'
  ) {
    return NextResponse.next();
  }

  // /api/connector-tool — loopback-only, no auth (used by Forge-internal
  // callers: pipelines via curl, jobs scheduler, CLI). Non-loopback hosts
  // fall through to the normal check.
  if (pathname === '/api/connector-tool') {
    const host = req.headers.get('host') || '';
    if (host.startsWith('127.0.0.1:') || host.startsWith('localhost:')) {
      return NextResponse.next();
    }
  }

  // Validated NextAuth session (browser login). req.auth is the decoded session
  // or null — a forged/unsigned session-token cookie does not pass.
  if (req.auth) {
    return NextResponse.next();
  }

  // A valid API key or admin-minted token authorizes any route; a bare or forged
  // credential does not. Both checks run because x-forge-token/forge-api-token can
  // carry either kind. /api/mcp still re-validates in its own handler.
  if (hasValidApiKey(req) || isValidToken(req)) {
    return NextResponse.next();
  }

  if (pathname.startsWith('/api/')) {
    return NextResponse.json({ error: 'unauthorized' }, { status: 401 });
  }
  return NextResponse.redirect(new URL('/login', req.url));
});

// Next.js 16: Proxy is always Node runtime — declaring `runtime: 'nodejs'`
// here errors out at build time (`Route segment config is not allowed in
// Proxy file`). Keep only the matcher.
export const config = {
  matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
};
