import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

/**
 * Better Auth session cookie name (default prefix + session_token).
 * @see https://www.better-auth.com/docs/concepts/session-management
 */
const SESSION_COOKIE = 'better-auth.session_token';
const SECURE_SESSION_COOKIE = '__Secure-better-auth.session_token';
const SESSION_COOKIE_NAMES = [SESSION_COOKIE, SECURE_SESSION_COOKIE];
const US_COUNTRY_CODE = 'US';
const COUNTRY_HEADER_NAMES = [
  'x-vercel-ip-country',
  'cf-ipcountry',
  'x-country-code',
  'x-geo-country',
];

/**
 * Routes that never require a session cookie.
 * Static assets and Next.js internals are excluded via the matcher config below.
 */
const PUBLIC_PATH_PREFIXES = [
  '/api/auth',   // Better Auth endpoints (sign-in, sign-up, callbacks, etc.)
  '/signin',
  '/signup',
  '/privacy',
];

function isPublicPath(pathname: string): boolean {
  // Root landing page
  if (pathname === '/') return true;

  return PUBLIC_PATH_PREFIXES.some((prefix) => pathname.startsWith(prefix));
}

function isAuthEnabled(): boolean {
  return !!(process.env.AUTH_SECRET && process.env.BASE_URL);
}

function isAnonymousAuthEnabled(): boolean {
  if (!isAuthEnabled()) return false;
  const raw = process.env.USE_ANONYMOUS_AUTH_SESSIONS;
  return raw?.trim().toLowerCase() === 'true';
}

function isRichardrDevProductionInstance(): boolean {
  return process.env.RICHARDRDEV_PRODUCTION?.trim().toLowerCase() === 'true';
}

function getCountryCodeFromHeaders(request: NextRequest): string | null {
  for (const headerName of COUNTRY_HEADER_NAMES) {
    const rawValue = request.headers.get(headerName);
    if (!rawValue) continue;

    const normalized = rawValue.trim().toUpperCase();
    if (normalized) {
      return normalized;
    }
  }

  return null;
}

export function middleware(request: NextRequest) {
  if (isRichardrDevProductionInstance()) {
    const countryCode = getCountryCodeFromHeaders(request);
    const isUnitedStatesRequest = countryCode === US_COUNTRY_CODE;

    // Strict region gate for the official production instance.
    if (!isUnitedStatesRequest) {
      const { pathname } = request.nextUrl;

      if (pathname.startsWith('/api/')) {
        return NextResponse.json(
          { error: 'OpenReader is only available in the United States.' },
          { status: 451, headers: { 'Cache-Control': 'no-store' } },
        );
      }

      return new NextResponse('OpenReader is only available in the United States.', {
        status: 451,
        headers: {
          'Cache-Control': 'no-store',
          'Content-Type': 'text/plain; charset=utf-8',
        },
      });
    }
  }

  // When auth is disabled entirely, let everything through.
  if (!isAuthEnabled()) {
    return NextResponse.next();
  }

  const { pathname } = request.nextUrl;

  // Fast-path redirect for signed-in users hitting the public landing page.
  // This avoids extra server work in the landing page render path.
  if (pathname === '/' && request.nextUrl.searchParams.get('redirect') !== 'false') {
    const hasSession = SESSION_COOKIE_NAMES.some((name) => request.cookies.has(name));
    if (hasSession) {
      const appUrl = request.nextUrl.clone();
      appUrl.pathname = '/app';
      appUrl.search = '';
      return NextResponse.redirect(appUrl);
    }
  }

  // Public routes are always accessible.
  if (isPublicPath(pathname)) {
    return NextResponse.next();
  }

  // When anonymous auth is enabled, unauthenticated users need to reach
  // the page so AuthLoader.tsx can bootstrap an anonymous session client-side.
  if (isAnonymousAuthEnabled()) {
    return NextResponse.next();
  }

  // Check for the presence of a session cookie.
  const hasSession = SESSION_COOKIE_NAMES.some((name) => request.cookies.has(name));

  if (!hasSession) {
    // API routes get a 401 instead of a redirect.
    if (pathname.startsWith('/api/')) {
      return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
    }

    // Page routes redirect to sign-in.
    const signInUrl = request.nextUrl.clone();
    signInUrl.pathname = '/signin';
    return NextResponse.redirect(signInUrl);
  }

  return NextResponse.next();
}

/**
 * Match all routes except static assets and Next.js internals.
 */
export const config = {
  matcher: [
    '/((?!_next/static|_next/image|favicon\\.ico|icon\\.png|icon\\.svg|apple-icon\\.png|manifest\\.json).*)',
  ],
};
