import createMiddleware from 'next-intl/middleware';
import { NextRequest, NextResponse } from 'next/server';

// Create the internationalization middleware
const intlMiddleware = createMiddleware({
  // A list of all locales that are supported
  locales: ['en', 'de'],

  // Used when no locale matches
  defaultLocale: 'en',
});

export default async function middleware(request: NextRequest) {
  const { method, url, headers } = request;
  const { pathname } = request.nextUrl;

  // Explicit bypass for infrastructure, Payload CMS, and Server Actions
  // Next-Action header is present for all Next.js Server Actions
  const isServerAction = headers.has('next-action');

  if (
    isServerAction ||
    pathname.startsWith('/admin') ||
    pathname.startsWith('/api') ||
    pathname.startsWith('/stats') ||
    pathname.startsWith('/errors') ||
    pathname.startsWith('/health') ||
    pathname.startsWith('/uploads') ||
    pathname.includes('/api/og') ||
    pathname.includes('opengraph-image') ||
    pathname.endsWith('sitemap.xml') ||
    pathname.endsWith('manifest.webmanifest')
  ) {
    return NextResponse.next();
  }

  // Build header object for logging
  const headerObj: Record<string, string> = {};
  headers.forEach((value, key) => {
    headerObj[key] = value;
  });

  // Defensive URL correction for internal container leakage (0.0.0.0, klz-app, localhost)
  // This prevents hydration mismatches and host poisoning in generated links/metadata.
  const urlObj = new URL(url);
  const internalHosts = ['0.0.0.0', 'klz-app', 'localhost', '127.0.0.1'];

  let effectiveRequest = request;
  if (internalHosts.includes(urlObj.hostname)) {
    const proto = headers.get('x-forwarded-proto') || 'https';
    // Prioritize x-forwarded-host (passed by Traefik) over the local Host header
    const fallbackHost = process.env.NEXT_PUBLIC_BASE_URL
      ? new URL(process.env.NEXT_PUBLIC_BASE_URL).host
      : 'klz-cables.com';
    const hostHeader = headers.get('x-forwarded-host') || headers.get('host') || fallbackHost;

    urlObj.protocol = proto;

    // Only create a new request for GET/HEAD to avoid consuming the body stream on POST/PUT
    // This resolves the "failed to pipe response" error (160k occurrences in GlitchTip)
    if (['GET', 'HEAD'].includes(request.method)) {
      // Clone headers to ensure all Next.js internal headers (like router state) are preserved
      const clonedHeaders = new Headers(request.headers);
      
      effectiveRequest = new NextRequest(urlObj, {
        headers: clonedHeaders,
        method: request.method,
      });

      if (process.env.NODE_ENV !== 'production' || !process.env.CI) {
        console.log(
          `🛡️ Proxy: Fixed internal URL leak: ${url} -> ${urlObj.toString()} | Proto: ${proto} | Host: ${hostHeader}`,
        );
      }
    }
  }

  try {
    // Apply internationalization middleware
    const response = intlMiddleware(effectiveRequest);

    // Upgrade 307 (Temporary Redirect) to 308 (Permanent Redirect)
    // This improves compatibility with scanners (Website Carbon, PageSpeed) and SEO.
    if (response.status === 307) {
      const location = response.headers.get('Location');
      if (location) {
        const url = new URL(location, request.url);
        return Response.redirect(url, 308);
      }
    }

    // Allow iframe embedding from recorder domains
    const referer = headers.get('referer') || '';
    const recorderDomains = ['recorder.localhost', 'recorder.mintel.me'];
    const isRecorderRequest = recorderDomains.some((domain) => referer.includes(domain));

    if (isRecorderRequest) {
      response.headers.delete('x-frame-options');
      response.headers.delete('content-security-policy');
      response.headers.set('Access-Control-Allow-Origin', '*');
    }

    return response;
  } catch (error) {
    console.error(
      `Request failed: method=${method} url=${url} headers=${JSON.stringify(headerObj)}`,
      error,
    );
    throw error;
  }
}

export const config = {
  matcher: [
    '/((?!api|_next/static|_next/image|favicon.ico|admin|manifest.webmanifest|.*\\.(?:svg|png|jpg|jpeg|gif|webp|pdf|txt|vcf|xml|webm|mp4|map)$).*)',
    '/(de|en)/:path*',
  ],
};
