import {
  defaultMode,
  defaultLocale,
  isMode,
  isLocale,
  localeCookie,
  localeCookieMaxAgeSeconds,
  localeFromAcceptLanguage,
  localizedModePath,
  routeIdFromAnyLocaleSlug,
  routeIdFromSlug,
} from '@/lib/localization/config';
import { buildContentSecurityPolicy, createNonce } from '@/lib/security/csp';
import {
  isThemePreference,
  themeCookie,
  themeCookieMaxAgeSeconds,
} from '@/lib/theme/config';
import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server';

const dashboardLanguageCookie = 'rentaldrivego-language';
const reservedProxySegments = new Set(['dashboard', 'admin', 'carplace']);

function applySecurityHeaders(response: NextResponse, contentSecurityPolicy: string): NextResponse {
  response.headers.set('Content-Security-Policy', contentSecurityPolicy);
  response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
  response.headers.set('X-Content-Type-Options', 'nosniff');
  response.headers.set('X-Frame-Options', 'DENY');
  response.headers.set('Cross-Origin-Opener-Policy', 'same-origin');
  response.headers.set('Permissions-Policy', 'camera=(), microphone=(), geolocation=()');
  return response;
}

function resolveApiOrigin(): string | undefined {
  const origins = new Set<string>();
  const urls = [process.env.API_INTERNAL_URL, process.env.NEXT_PUBLIC_API_URL];
  for (const url of urls) {
    if (!url) continue;
    try {
      origins.add(new URL(url).origin);
    } catch {
      // ignore malformed URLs
    }
  }
  return origins.size > 0 ? Array.from(origins).join(' ') : undefined;
}

function resolveRequestLocale(request: NextRequest) {
  const cookieLocale = request.cookies.get(localeCookie)?.value;
  return isLocale(cookieLocale)
    ? cookieLocale
    : localeFromAcceptLanguage(request.headers.get('accept-language')) || defaultLocale;
}

function resolveRequestMode(request: NextRequest) {
  const cookieMode = request.cookies.get(themeCookie)?.value;
  return isThemePreference(cookieMode) ? cookieMode : defaultMode;
}

function setLocaleCookie(response: NextResponse, locale: string): void {
  response.cookies.set(localeCookie, locale, {
    path: '/',
    sameSite: 'lax',
    maxAge: localeCookieMaxAgeSeconds,
    secure: process.env.NODE_ENV === 'production',
    httpOnly: false,
  });
}

function setModeCookie(response: NextResponse, mode: string): void {
  response.cookies.set(themeCookie, mode, {
    path: '/',
    sameSite: 'lax',
    maxAge: themeCookieMaxAgeSeconds,
    secure: process.env.NODE_ENV === 'production',
    httpOnly: false,
  });
}

export function proxy(request: NextRequest): NextResponse {
  const nonce = createNonce();
  const isDev = process.env.NODE_ENV !== 'production';
  const apiOrigin = resolveApiOrigin();
  const csp = buildContentSecurityPolicy(nonce, isDev, apiOrigin);
  const requestHeaders = new Headers(request.headers);
  requestHeaders.set('x-nonce', nonce);
  requestHeaders.set('Content-Security-Policy', csp);

  if (request.nextUrl.pathname === '/') {
    const locale = resolveRequestLocale(request);
    const mode = resolveRequestMode(request);
    const destination = request.nextUrl.clone();
    destination.pathname = `/${locale}/${mode}`;
    const response = NextResponse.redirect(destination);
    setLocaleCookie(response, locale);
    setModeCookie(response, mode);
    return applySecurityHeaders(response, csp);
  }

  const pathSegments = request.nextUrl.pathname.split('/').filter(Boolean);

  // Redirect locale-less paths (e.g. /sign-in → /en/system/sign-in), but not proxied app paths or files.
  const firstSegment = request.nextUrl.pathname.split('/')[1];
  const isFile = /\.\w+$/.test(request.nextUrl.pathname);
  if (firstSegment && !isFile && !isLocale(firstSegment) && !reservedProxySegments.has(firstSegment)) {
    const locale = resolveRequestLocale(request);
    const mode = resolveRequestMode(request);
    const destination = request.nextUrl.clone();
    destination.pathname = `/${locale}/${mode}${request.nextUrl.pathname}`;
    return applySecurityHeaders(NextResponse.redirect(destination), csp);
  }

  if (
    isLocale(pathSegments[0]) &&
    isMode(pathSegments[1]) &&
    request.nextUrl.pathname === `/${pathSegments[0]}/${pathSegments[1]}/subscription`
  ) {
    const destination = request.nextUrl.clone();
    destination.pathname = '/dashboard/subscription';
    const response = NextResponse.redirect(destination);
    setLocaleCookie(response, pathSegments[0]);
    setModeCookie(response, pathSegments[1]);
    response.cookies.set(dashboardLanguageCookie, pathSegments[0], {
      path: '/',
      sameSite: 'lax',
      maxAge: localeCookieMaxAgeSeconds,
      secure: process.env.NODE_ENV === 'production',
      httpOnly: false,
    });
    return applySecurityHeaders(response, csp);
  }

  if (isLocale(pathSegments[0]) && !isMode(pathSegments[1])) {
    const mode = resolveRequestMode(request);
    const slug = pathSegments.slice(1).join('/');
    if (!slug) {
      const destination = request.nextUrl.clone();
      destination.pathname = localizedModePath('home', pathSegments[0], mode);
      return applySecurityHeaders(NextResponse.redirect(destination), csp);
    }
    const routeId = routeIdFromSlug(pathSegments[0], slug) ?? routeIdFromAnyLocaleSlug(slug);
    if (routeId) {
      const destination = request.nextUrl.clone();
      destination.pathname = localizedModePath(routeId, pathSegments[0], mode);
      return applySecurityHeaders(NextResponse.redirect(destination), csp);
    }
    if (slug === 'component-lab') {
      const destination = request.nextUrl.clone();
      destination.pathname = `/${pathSegments[0]}/${mode}/component-lab`;
      return applySecurityHeaders(NextResponse.redirect(destination), csp);
    }
  }

  if (isLocale(pathSegments[0]) && isMode(pathSegments[1])) {
    requestHeaders.set('x-theme-preference', pathSegments[1]);
    const slug = pathSegments.slice(2).join('/');
    if (slug && !routeIdFromSlug(pathSegments[0], slug)) {
      const routeId = routeIdFromAnyLocaleSlug(slug);
      if (routeId) {
        const destination = request.nextUrl.clone();
        destination.pathname = localizedModePath(routeId, pathSegments[0], pathSegments[1]);
        return applySecurityHeaders(NextResponse.redirect(destination), csp);
      }
    }
  }

  const response = NextResponse.next({ request: { headers: requestHeaders } });
  const explicitLocale = pathSegments[0];
  if (isLocale(explicitLocale)) {
    setLocaleCookie(response, explicitLocale);
  }
  const explicitMode = pathSegments[1];
  if (isMode(explicitMode)) {
    setModeCookie(response, explicitMode);
  }
  return applySecurityHeaders(response, csp);
}

export const config = {
  matcher: [
    {
      source: '/((?!api|_next/static|_next/image|assets|favicon.ico|robots.txt|sitemap.xml).*)',
      missing: [
        { type: 'header', key: 'next-router-prefetch' },
        { type: 'header', key: 'purpose', value: 'prefetch' },
      ],
    },
  ],
};
