/**
 * IP Address Utilities
 */

import { createRequire } from 'node:module';

/**
 * Check if string is IPv4
 */
export function isIPv4(ip) {
  if (typeof ip !== 'string') return false;
  const parts = ip.split('.');
  if (parts.length !== 4) return false;
  
  return parts.every(part => {
    const num = parseInt(part, 10);
    return !isNaN(num) && num >= 0 && num <= 255 && part === String(num);
  });
}

/**
 * Check if string is IPv6
 */
export function isIPv6(ip) {
  if (typeof ip !== 'string') return false;
  // Simple check - contains colons and valid hex
  return ip.includes(':') && /^[0-9a-fA-F:]+$/.test(ip);
}

/**
 * Check if IP is in private range (RFC 1918)
 */
export function isPrivateIp(ip) {
  if (!isIPv4(ip)) return false;
  
  const parts = ip.split('.').map(Number);
  const [a, b, c, d] = parts;
  
  // 10.0.0.0/8
  if (a === 10) return true;
  
  // 172.16.0.0/12
  if (a === 172 && b >= 16 && b <= 31) return true;
  
  // 192.168.0.0/16
  if (a === 192 && b === 168) return true;
  
  // 127.0.0.0/8 (loopback)
  if (a === 127) return true;
  
  // 169.254.0.0/16 (link-local)
  if (a === 169 && b === 254) return true;
  
  return false;
}

/**
 * Check if IP is loopback
 */
export function isLoopbackIp(ip) {
  if (!isIPv4(ip)) return false;
  return ip.startsWith('127.');
}

/**
 * Convert IP to integer for range comparison
 */
export function ipToInt(ip) {
  return ip.split('.').reduce((acc, octet) => (acc << 8) + parseInt(octet, 10), 0) >>> 0;
}

/**
 * Parse CIDR notation
 */
export function parseCidr(cidr) {
  const [ip, prefix] = cidr.split('/');
  const mask = -1 << (32 - parseInt(prefix, 10));
  return { ip: ipToInt(ip), mask };
}

/**
 * Check if IP is in CIDR range
 */
export function isIpInCidr(ip, cidr) {
  if (!isIPv4(ip)) return false;
  
  try {
    const ipInt = ipToInt(ip);
    const { ip: networkInt, mask } = parseCidr(cidr);
    
    return (ipInt & mask) === (networkInt & mask);
  } catch (err) {
    return false;
  }
}

/**
 * Check if two IPs are equal
 */
export function ipEquals(ip1, ip2) {
  return ip1 === ip2;
}

/**
 * Get IP version (4 or 6)
 */
export function getIpVersion(ip) {
  if (isIPv4(ip)) return 4;
  if (isIPv6(ip)) return 6;
  return null;
}

/**
 * Normalize IP (remove leading zeros, etc.)
 */
export function normalizeIp(ip) {
  if (!isIPv4(ip)) return ip;
  
  return ip
    .split('.')
    .map(part => parseInt(part, 10).toString())
    .join('.');
}
