import type { Request } from 'express';
import { env } from '../config/env.js';

/**
 * Resolve the real client IP.
 * `TRUST_PROXY` must only be enabled when a proxy you control sets
 * X-Forwarded-For — otherwise a client can spoof its own location.
 */
export function clientIp(req: Request | { headers: Record<string, any>; socket?: any }): string {
  const headers = req.headers as Record<string, string | string[] | undefined>;
  if (env.TRUST_PROXY) {
    const xff = headers['x-forwarded-for'];
    const first = Array.isArray(xff) ? xff[0] : xff;
    if (first) {
      const ip = first.split(',')[0]?.trim();
      if (ip) return normalize(ip);
    }
    const real = headers['x-real-ip'];
    if (typeof real === 'string' && real) return normalize(real);
  }
  const raw =
    (req as any).ip ??
    (req as any).socket?.remoteAddress ??
    (req as any).handshake?.address ??
    '';
  return normalize(String(raw));
}

/** Strips the IPv4-mapped-IPv6 prefix (::ffff:1.2.3.4 -> 1.2.3.4). */
function normalize(ip: string): string {
  return ip.replace(/^::ffff:/i, '');
}

/** Loopback / RFC1918 / link-local addresses have no meaningful geo data. */
export function isPrivateIp(ip: string): boolean {
  if (!ip) return true;
  if (ip === '::1' || ip === '127.0.0.1' || ip.startsWith('127.')) return true;
  if (ip.startsWith('10.') || ip.startsWith('192.168.')) return true;
  if (/^172\.(1[6-9]|2\d|3[01])\./.test(ip)) return true;
  if (ip.startsWith('169.254.') || ip.startsWith('fc') || ip.startsWith('fd')) return true;
  return false;
}
