/**
 * Optimized IP Address Utilities
 * 
 * High-performance versions for hot paths
 */

// CIDR cache for repeated lookups
const cidrCache = new Map();
const CIDR_CACHE_SIZE = 1000;

/**
 * Fast IPv4 check - less strict but much faster
 * Only validates format, not strict numeric ranges
 */
export function isIPv4Fast(ip) {
  if (typeof ip !== 'string') return false;
  
  // Quick length check (min: 7 for "0.0.0.0", max: 15 for "255.255.255.255")
  if (ip.length < 7 || ip.length > 15) return false;
  
  let dots = 0;
  for (let i = 0; i < ip.length; i++) {
    const c = ip.charCodeAt(i);
    if (c === 46) { // '.'
      dots++;
    } else if (c < 48 || c > 57) { // not 0-9
      return false;
    }
  }
  return dots === 3;
}

/**
 * Ultra-fast IP to integer conversion
 * Direct character parsing, no string splitting
 */
export function ipToIntFast(ip) {
  let result = 0;
  let octet = 0;
  let shift = 24;
  
  for (let i = 0; i < ip.length; i++) {
    const c = ip.charCodeAt(i);
    if (c === 46) { // '.'
      result |= (octet << shift);
      octet = 0;
      shift -= 8;
    } else {
      octet = octet * 10 + (c - 48);
    }
  }
  
  return (result | octet) >>> 0;
}

/**
 * Fast CIDR parsing with caching
 */
export function parseCidrCached(cidr) {
  // Check cache first
  let cached = cidrCache.get(cidr);
  if (cached) return cached;
  
  // Parse and cache
  const slashIdx = cidr.indexOf('/');
  if (slashIdx === -1) return null;
  
  const ip = cidr.slice(0, slashIdx);
  const prefix = parseInt(cidr.slice(slashIdx + 1), 10);
  const mask = -1 << (32 - prefix);
  
  cached = { 
    network: ipToIntFast(ip), 
    mask,
    prefix 
  };
  
  // Simple LRU - clear if too big
  if (cidrCache.size >= CIDR_CACHE_SIZE) {
    cidrCache.clear();
  }
  cidrCache.set(cidr, cached);
  
  return cached;
}

/**
 * Ultra-fast IP in CIDR check
 * Uses caching and optimized parsing
 */
export function isIpInCidrFast(ip, cidr) {
  const cached = parseCidrCached(cidr);
  if (!cached) return false;
  
  const ipInt = ipToIntFast(ip);
  return (ipInt & cached.mask) === (cached.network & cached.mask);
}

/**
 * Fast private IP check using bit manipulation
 */
export function isPrivateIpFast(ip) {
  const ipInt = ipToIntFast(ip);
  
  // 10.0.0.0/8: 0x0A000000 to 0x0AFFFFFF
  if ((ipInt >>> 24) === 10) return true;
  
  // 172.16.0.0/12: 0xAC100000 to 0xAC1FFFFF
  const high16 = ipInt >>> 16;
  if (high16 >= 0xAC10 && high16 <= 0xAC1F) return true;
  
  // 192.168.0.0/16: 0xC0A80000 to 0xC0A8FFFF
  if (high16 === 0xC0A8) return true;
  
  // 127.0.0.0/8: 0x7F000000 to 0x7FFFFFFF
  if ((ipInt >>> 24) === 127) return true;
  
  // 169.254.0.0/16: 0xA9FE0000 to 0xA9FEFFFF
  if (high16 === 0xA9FE) return true;
  
  return false;
}

/**
 * Optimized built-in function evaluator
 * Direct dispatch without object lookups
 */
export function evaluateBuiltInFast(name, args) {
  switch (name) {
    case 'ip_in_cidr':
      return isIpInCidrFast(args[0], args[1]);
    case 'ip_is_private':
      return isPrivateIpFast(args[0]);
    case 'ip_is_loopback':
      return (ipToIntFast(args[0]) >>> 24) === 127;
    case 'ip_version':
      return isIPv4Fast(args[0]) ? 4 : (args[0].includes(':') ? 6 : null);
    case 'ip_equals':
      return args[0] === args[1];
    case 'contains':
      return String(args[0]).includes(String(args[1]));
    case 'starts_with':
      return String(args[0]).startsWith(String(args[1]));
    case 'ends_with':
      return String(args[0]).endsWith(String(args[1]));
    case 'equals':
      return args[0] === args[1];
    case 'greater_than':
      return args[0] > args[1];
    case 'less_than':
      return args[0] < args[1];
    case 'in_range':
      return args[0] >= args[1] && args[0] <= args[2];
    case 'hour_of_day':
      return new Date(args[0]).getHours();
    case 'day_of_week':
      return new Date(args[0]).getDay();
    default:
      throw new Error(`Unknown: ${name}`);
  }
}

// Re-export original functions for compatibility
export { isIPv4, isIPv6, isLoopbackIp, getIpVersion, normalizeIp } from './ip-utils.js';
export { isIpInCidr, isPrivateIp } from './ip-utils.js';
