import { Request } from 'express';

/**
 * Extract client IP address from request
 * Handles proxies and load balancers via x-forwarded-for header
 * Normalizes IPv6 loopback (::1) to IPv4 loopback (127.0.0.1)
 */
export function getClientIp(req: Request | any): string | null {
  let ip: string | null = null;
  
  // Priority 1: Check x-forwarded-for header (for proxies/load balancers)
  const forwardedFor = req.headers['x-forwarded-for'];
  if (forwardedFor) {
    // x-forwarded-for can contain multiple IPs, take the first one
    const ips = Array.isArray(forwardedFor) ? forwardedFor[0] : forwardedFor;
    ip = ips.split(',')[0].trim();
  }
  
  // Priority 2: Check x-real-ip header (some proxies use this)
  if (!ip) {
    const realIp = req.headers['x-real-ip'];
    if (realIp) {
      ip = Array.isArray(realIp) ? realIp[0] : realIp;
    }
  }
  
  // Priority 3: Check cf-connecting-ip (Cloudflare)
  if (!ip) {
    const cfIp = req.headers['cf-connecting-ip'];
    if (cfIp) {
      ip = Array.isArray(cfIp) ? cfIp[0] : cfIp;
    }
  }
  
  // Priority 4: Fallback to req.ip (requires trust proxy to be set)
  if (!ip && req.ip) {
    ip = req.ip;
  }
  
  // Priority 5: Check connection remote address
  if (!ip && req.socket?.remoteAddress) {
    ip = req.socket.remoteAddress;
  }
  
  // Normalize IPv6 loopback to IPv4 loopback for consistency
  if (ip === '::1' || ip === '::ffff:127.0.0.1') {
    ip = '127.0.0.1';
  }
  
  // Remove IPv6 prefix if present (::ffff:)
  if (ip && ip.startsWith('::ffff:')) {
    ip = ip.substring(7);
  }
  
  return ip;
}

/**
 * Extract user agent from request
 */
export function getUserAgent(req: Request | any): string | null {
  return req.headers['user-agent'] || null;
}

/**
 * Extract both IP and user agent from request
 * Returns undefined instead of null to match TypeScript optional property types
 */
export function getRequestMetadata(req: Request | any): {
  ipAddress: string | undefined;
  userAgent: string | undefined;
} {
  const ip = getClientIp(req);
  const ua = getUserAgent(req);
  return {
    ipAddress: ip || undefined,
    userAgent: ua || undefined
  };
}

