import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { validateRequestIP, getClientIP } from './lib/security/ipWhitelist';
import {
  PROTECTED_PATHS,
  BLOCKED_USER_AGENTS,
  BLOCKED_IPS,
  SUSPICIOUS_PATTERNS,
} from './lib/security/config';

export function middleware(request: NextRequest) {
  // Safely get pathname and search
  let pathname = '/';
  let search = '';
  try {
    if (request?.nextUrl) {
      pathname = request.nextUrl.pathname || '/';
      search = request.nextUrl.search || '';
    }
  } catch (e) {
    console.warn('Error getting URL from request:', e);
  }
  
  // Safely get headers
  let headersObj: Record<string, string> = {};
  try {
    if (request?.headers && typeof request.headers.entries === 'function') {
      try {
        headersObj = Object.fromEntries(request.headers.entries());
      } catch (entriesError) {
        // If entries() fails, try to manually extract headers
        console.warn('Error getting header entries, trying alternative method:', entriesError);
        headersObj = {};
      }
    }
  } catch (e) {
    // If headers can't be converted, use empty object
    console.warn('Error converting headers:', e);
  }
  
  // Safely get user agent
  let userAgent = '';
  try {
    if (request?.headers && typeof request.headers.get === 'function') {
      const ua = request.headers.get('user-agent');
      userAgent = ua || '';
    }
  } catch (e) {
    console.warn('Error getting user agent:', e);
  }
  
  const ip = getClientIP(headersObj);

  // Security checks
  const securityChecks: Array<{ check: () => boolean; action: () => NextResponse }> = [];

  // 1. Block malicious user agents
  securityChecks.push({
    check: () => BLOCKED_USER_AGENTS.some(blocked => userAgent.toLowerCase().includes(blocked.toLowerCase())),
    action: () => {
      console.warn(`[SECURITY] Blocked malicious user agent: ${userAgent} from IP: ${ip}`);
      return new NextResponse('Forbidden', { status: 403 });
    },
  });

  // 2. Block known malicious IPs
  securityChecks.push({
    check: () => BLOCKED_IPS.includes(ip),
    action: () => {
      console.warn(`[SECURITY] Blocked known malicious IP: ${ip}`);
      return new NextResponse('Forbidden', { status: 403 });
    },
  });

  // 3. IP whitelist check for protected paths
  if (PROTECTED_PATHS.some(path => pathname.startsWith(path))) {
    const validation = validateRequestIP(headersObj);
    if (!validation.allowed) {
      console.warn(`[SECURITY] Blocked non-whitelisted IP: ${ip} from accessing: ${pathname}`);
      return new NextResponse(
        JSON.stringify({
          error: 'Forbidden',
          message: 'Access denied from this IP address',
        }),
        {
          status: 403,
          headers: { 'Content-Type': 'application/json' },
        }
      );
    }
  }

  // 4. Block suspicious query parameters (potential XSS/SQL injection attempts)
  const fullUrl = pathname + search;
  if (SUSPICIOUS_PATTERNS.some(pattern => pattern.test(fullUrl))) {
    console.warn(`[SECURITY] Blocked suspicious request pattern from IP: ${ip} - URL: ${fullUrl}`);
    return new NextResponse('Bad Request', { status: 400 });
  }

  // 5. Rate limiting headers (basic implementation)
  // In production, use a proper rate limiting service
  const response = NextResponse.next();
  
  // Add security headers (safely check if headers exist)
  try {
    if (response?.headers && typeof response.headers.set === 'function') {
      response.headers.set('X-Content-Type-Options', 'nosniff');
      response.headers.set('X-Frame-Options', 'SAMEORIGIN');
      response.headers.set('X-XSS-Protection', '1; mode=block');
      response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
    }
  } catch (e) {
    console.warn('Error setting response headers:', e);
  }

  // Execute security checks
  for (const { check, action } of securityChecks) {
    if (check()) {
      return action();
    }
  }

  return response;
}

// Configure which routes the middleware runs on
export const config = {
  matcher: [
    /*
     * Match all request paths except:
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.ico (favicon file)
     * - public files (images, etc.)
     */
    '/((?!_next/static|_next/image|favicon.ico|images|icons|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|woff|woff2|ttf|eot)).*)',
  ],
};

