import * as os from 'os';
import * as path from 'path';
import * as fs from 'fs';
import { logger } from './logger';
import {
  DEFAULT_LANE_SERVER,
  DEFAULT_LANE_NAMESPACE,
  DEFAULT_LANE_GROUP_NAME,
  DEFAULT_LANE_HEARTBEAT_INTERVAL,
  DEFAULT_LANE_INSTANCE_TTL,
  DEFAULT_SERVICE_NAME,
  DEFAULT_LANE_ID,
  DEFAULT_HOST,
  DEFAULT_LANE_TARGET_HEADER,
  DEFAULT_LANE_ENABLED,
  DEFAULT_LANE_COOKIE_ENABLED,
  DEFAULT_LANE_PROXY_TIMEOUT,
  DEFAULT_LANE_REGISTRATION_TIMEOUT,
  getEnvOrDefault,
  getBooleanEnv,
  getNumberEnv
} from './defaults';

/**
 * 检查IP地址是否为私有网络地址
 * @param ip IP地址
 * @returns 是否为私有网络地址
 */
function isPrivateIP(ip: string): boolean {
  // 私有网络地址范围：
  // 10.0.0.0/8 (10.0.0.0 - 10.255.255.255)
  // 172.16.0.0/12 (172.16.0.0 - 172.31.255.255)
  // 192.168.0.0/16 (192.168.0.0 - 192.168.255.255)

  const parts = ip.split('.').map(Number);
  if (parts.length !== 4) return false;

  const [a, b] = parts;

  return (
    a === 10 ||
    (a === 172 && b >= 16 && b <= 31) ||
    (a === 192 && b === 168)
  );
}

/**
 * 检查IP地址是否应该被跳过
 * @param ip IP地址
 * @param interfaceName 网络接口名称
 * @returns 是否应该跳过
 */
function shouldSkipIP(ip: string, interfaceName: string): boolean {
  // 跳过Docker桥接网络（通常是172.17.x.x）
  if (ip.startsWith('172.17.')) {
    logger.debug(`⏭️ 跳过Docker桥接网络地址: ${ip} (接口: ${interfaceName})`);
    return true;
  }

  // 跳过Docker默认网络（通常是172.18.x.x到172.31.x.x）
  const parts = ip.split('.').map(Number);
  if (parts[0] === 172 && parts[1] >= 17 && parts[1] <= 31) {
    logger.debug(`⏭️ 跳过Docker网络地址: ${ip} (接口: ${interfaceName})`);
    return true;
  }

  // 跳过某些虚拟接口
  const skipInterfaces = ['docker0', 'br-', 'veth'];
  if (skipInterfaces.some(skip => interfaceName.startsWith(skip))) {
    logger.debug(`⏭️ 跳过虚拟接口: ${interfaceName} (IP: ${ip})`);
    return true;
  }

  return false;
}

/**
 * 自动检测当前实例的IP地址
 * 完全自动化，无需手动配置，遵循容器/K8s最佳实践
 *
 * @returns 检测到的IP地址
 */
function detectInstanceIP(): string {
  logger.info(`🔍 开始自动检测实例IP地址...`);

  // 1. 自动检测网络接口（核心逻辑）
  try {
    const networkInterfaces = os.networkInterfaces();
    logger.debug(`🔍 检测到的网络接口: ${JSON.stringify(Object.keys(networkInterfaces))}`);

    // 容器环境优先的网络接口（按优先级排序）
    const containerInterfaces = [
      'eth0',     // 最常见的容器网络接口
      'eth1',     // 多网卡容器
      'ens3',     // 云环境常见接口
      'ens4',     // 云环境常见接口
    ];

    // 物理机/虚拟机环境的网络接口
    const physicalInterfaces = [
      'ens160',   // VMware虚拟机
      'ens192',   // VMware虚拟机
      'enp0s3',   // VirtualBox
      'enp0s8',   // VirtualBox
      'en0',      // macOS
      'en1',      // macOS
      'wlan0',    // 无线网络
    ];

    // 首先尝试容器环境的网络接口
    for (const interfaceName of containerInterfaces) {
      const networkInterface = networkInterfaces[interfaceName];
      if (networkInterface) {
        for (const addr of networkInterface) {
          if (addr.family === 'IPv4' && !addr.internal && !shouldSkipIP(addr.address, interfaceName)) {
            logger.info(`✅ 从容器网络接口 ${interfaceName} 获取IP地址: ${addr.address}`);
            return addr.address;
          }
        }
      }
    }

    // 然后尝试物理机/虚拟机的网络接口
    for (const interfaceName of physicalInterfaces) {
      const networkInterface = networkInterfaces[interfaceName];
      if (networkInterface) {
        for (const addr of networkInterface) {
          if (addr.family === 'IPv4' && !addr.internal && !shouldSkipIP(addr.address, interfaceName)) {
            logger.info(`✅ 从物理网络接口 ${interfaceName} 获取IP地址: ${addr.address}`);
            return addr.address;
          }
        }
      }
    }

    // 最后遍历所有接口，寻找合适的IP
    const candidateIPs: Array<{ip: string, interface: string, isPrivate: boolean}> = [];

    for (const [interfaceName, addresses] of Object.entries(networkInterfaces)) {
      if (!addresses) continue;

      for (const addr of addresses) {
        if (addr.family === 'IPv4' && !addr.internal && !shouldSkipIP(addr.address, interfaceName)) {
          candidateIPs.push({
            ip: addr.address,
            interface: interfaceName,
            isPrivate: isPrivateIP(addr.address)
          });
        }
      }
    }

    if (candidateIPs.length > 0) {
      // 优先选择私有网络IP（容器/K8s环境通常使用私有网络）
      const privateIPs = candidateIPs.filter(candidate => candidate.isPrivate);
      if (privateIPs.length > 0) {
        const selected = privateIPs[0];
        logger.info(`✅ 选择私有网络IP: ${selected.ip} (接口: ${selected.interface})`);
        return selected.ip;
      }

      // 如果没有私有网络IP，选择第一个可用的IP
      const selected = candidateIPs[0];
      logger.info(`✅ 选择公网IP: ${selected.ip} (接口: ${selected.interface})`);
      return selected.ip;
    }

  } catch (error) {
    logger.warn(`⚠️ 自动检测网络接口失败: ${error instanceof Error ? error.message : String(error)}`);
  }

  // 2. 检查Kubernetes环境变量（作为备选方案）
  if (process.env.POD_IP && process.env.POD_IP !== 'localhost' && process.env.POD_IP !== '127.0.0.1') {
    logger.info(`🎯 网络接口检测失败，使用Kubernetes Pod IP: ${process.env.POD_IP}`);
    return process.env.POD_IP;
  }

  // 3. 检查其他容器环境变量（最后的备选方案）
  if (process.env.CONTAINER_IP && process.env.CONTAINER_IP !== 'localhost' && process.env.CONTAINER_IP !== '127.0.0.1') {
    logger.info(`📦 网络接口检测失败，使用容器环境变量IP: ${process.env.CONTAINER_IP}`);
    return process.env.CONTAINER_IP;
  }

  // 4. 如果都没有找到，使用默认值并记录详细的建议
  logger.error(`❌ 无法自动检测到有效的IP地址！`);
  logger.error(`💡 这通常发生在以下情况：`);
  logger.error(`   1. 容器网络配置异常`);
  logger.error(`   2. 网络接口名称不在预期范围内`);
  logger.error(`   3. 所有检测到的IP都被过滤掉了`);
  logger.error(`🔧 解决方案：`);
  logger.error(`   - 在Kubernetes中使用Downward API注入POD_IP`);
  logger.error(`   - 检查容器网络配置`);
  logger.error(`   - 如果必要，可以设置HOST环境变量作为临时解决方案`);

  return DEFAULT_HOST;
}

/**
 * 泳道管理器配置接口
 * 定义了泳道管理器所需的所有配置项
 */
export interface LaneManagerConfig {
  // Nacos 服务器配置
  nacosServerAddr: string;      // Nacos 服务器地址（从 NACOS_SERVER 解析）
  nacosServerPort: string;      // Nacos 服务器端口（从 NACOS_SERVER 解析）
  nacosUrl: string;             // 完整的 Nacos 服务器 URL
  nacosNamespace: string;       // Nacos 命名空间
  nacosGroupName: string;       // Nacos 分组名称

  // 服务配置
  serviceName: string;          // 当前服务名称
  currentLaneId: string;        // 当前泳道 ID
  host: string;                 // 服务主机名
  port: number | null;          // 服务端口，初始为 null

  // 泳道配置
  targetLaneHeaderKey: string;  // 目标泳道请求头键名（小写形式）
  isLaneEnabled: boolean;       // 是否启用泳道功能
  isLaneCookieEnabled: boolean; // 是否启用从cookie中检测泳道ID

  // 超时配置
  proxyTimeout: number;         // 代理请求超时时间（毫秒）
  registrationTimeout: number;  // 注册请求超时时间（毫秒）
  heartbeatInterval: number;    // 心跳间隔时间（毫秒）
  instanceTtl: number;          // 实例过期时间（毫秒）

  // 元数据
  metadata: Record<string, any>; // 服务实例元数据
}

// 配置缓存，避免重复创建配置对象
let configCache: LaneManagerConfig | null = null;

/**
 * 获取配置，优先使用缓存
 * @returns 泳道管理器配置对象
 */
export function getConfig(): LaneManagerConfig {
  if (configCache) {
    return configCache;
  }

  // 创建新配置
  configCache = createConfig();
  return configCache;
}

/**
 * 清除配置缓存，强制下次获取时重新创建
 * 在配置需要重新加载时调用
 */
export function clearConfigCache(): void {
  configCache = null;
  logger.debug('🔄 配置缓存已清除');
}

/**
 * 创建配置对象
 * 从环境变量中读取配置，并设置默认值
 * @returns 新创建的配置对象
 */
function createConfig(): LaneManagerConfig {
  // 从环境变量读取基本配置，并设置默认值
  const nacosServer = process.env.LANE_SERVER || process.env.NACOS_SERVER || DEFAULT_LANE_SERVER;
  logger.debug(`🔍 Nacos服务器配置: LANE_SERVER=${process.env.LANE_SERVER}, NACOS_SERVER=${process.env.NACOS_SERVER}, DEFAULT_LANE_SERVER=${DEFAULT_LANE_SERVER}`);
  logger.debug(`🔍 最终使用的Nacos服务器: ${nacosServer}`);

  // 解析Nacos服务器地址和端口
  const parts = nacosServer.split(':');
  const nacosServerAddr = parts[0] || 'localhost';
  const nacosServerPort = parts.length > 1 ? parts[1] : '8848';
  logger.debug(`🔍 解析后的Nacos地址: ${nacosServerAddr}, 端口: ${nacosServerPort}`);

  // 服务名称获取详细过程
  logger.debug(`🔍 服务名称获取过程开始...`);
  logger.debug(`🔍 环境变量 SERVICE_NAME=${process.env.SERVICE_NAME}`);
  logger.debug(`🔍 DEFAULT_SERVICE_NAME=${DEFAULT_SERVICE_NAME}`);

  // 检查 package.json 中的 name
  let packageJsonName = '未检测';
  try {
    // 尝试从多个可能的位置读取 package.json
    const possiblePaths = [
      // 优先检查 server/package.json (适用于 node server/index.mjs 启动方式)
      path.resolve(process.cwd(), 'server', 'package.json'),

      // 当前工作目录
      path.resolve(process.cwd(), 'package.json'),

      // 当前工作目录的父目录（可能是项目根目录）
      path.resolve(process.cwd(), '..', 'package.json'),

      // 常见的服务器输出目录
      path.resolve(process.cwd(), 'server', '..', 'package.json'),
      path.resolve(process.cwd(), '.output', 'server', '..', 'package.json'),
      path.resolve(process.cwd(), 'dist', '..', 'package.json'),
      path.resolve(process.cwd(), 'build', '..', 'package.json'),

      // Nuxt输出目录
      path.resolve(process.cwd(), '.output', 'package.json'),

      // 应用根目录（如果设置了APP_ROOT环境变量）
      ...(process.env.APP_ROOT ? [path.resolve(process.env.APP_ROOT, 'package.json')] : []),

      // 向上查找两级目录
      path.resolve(process.cwd(), '..', '..', 'package.json'),
    ];

    // 尝试每个可能的路径
    for (const packageJsonPath of possiblePaths) {
      if (fs.existsSync(packageJsonPath)) {
        logger.debug(`🔍 尝试读取 package.json: ${packageJsonPath}`);
        const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
        if (packageJson && packageJson.name) {
          packageJsonName = packageJson.name;
          logger.debug(`✅ 成功从 ${packageJsonPath} 读取到 package.json，name: ${packageJsonName}`);

          // 如果是从 server/package.json 获取的，特别标记一下
          if (packageJsonPath.includes('server/package.json')) {
            logger.info(`🚀 从 server/package.json 获取服务名称，适用于 node server/index.mjs 启动方式`);
          }

          break;
        } else {
          logger.debug(`⚠️ 从 ${packageJsonPath} 读取到 package.json，但没有 name 字段`);
        }
      }
    }
  } catch (error) {
    packageJsonName = `检测出错: ${error instanceof Error ? error.message : String(error)}`;
    logger.debug(`❌ 读取 package.json 失败: ${packageJsonName}`);
  }
  logger.debug(`🔍 package.json name=${packageJsonName}`);

  // 首先尝试从 package.json 获取服务名称，然后从环境变量获取
  let serviceName = '';
  if (packageJsonName && packageJsonName !== '未检测' && packageJsonName !== '未设置' && !packageJsonName.startsWith('检测出错')) {
    serviceName = packageJsonName;
    logger.info(`✅ 从 package.json 获取服务名称: ${serviceName}`);
  } else if (process.env.SERVICE_NAME) {
    serviceName = process.env.SERVICE_NAME;
    logger.info(`✅ 从环境变量 SERVICE_NAME 获取服务名称: ${serviceName}`);
  } else if (process.env.NITRO_APP_NAME) {
    serviceName = process.env.NITRO_APP_NAME;
    logger.info(`✅ 从环境变量 NITRO_APP_NAME 获取服务名称: ${serviceName}`);
  } else if (process.env.APP_NAME) {
    serviceName = process.env.APP_NAME;
    logger.info(`✅ 从环境变量 APP_NAME 获取服务名称: ${serviceName}`);
  } else if (process.env.npm_package_name) {
    serviceName = process.env.npm_package_name;
    logger.info(`✅ 从环境变量 npm_package_name 获取服务名称: ${serviceName}`);
  } else {
    // 没有找到服务名称
    serviceName = '';
    logger.error(`❌ 警告: 无法获取服务名称，泳道功能将被禁用`);
    logger.error(`❌ 请通过以下方式之一设置服务名称:`);
    logger.error(`   1. 确保 server/package.json 或项目根目录的 package.json 中有 name 字段`);
    logger.error(`   2. 设置环境变量 SERVICE_NAME`);
    logger.error(`   3. 设置环境变量 NITRO_APP_NAME, APP_NAME 或 npm_package_name`);
  }
  logger.debug(`🔍 最终使用的服务名称: ${serviceName || '未设置 (泳道功能将被禁用)'}`);
  const currentLaneId = getEnvOrDefault('LANE_ID', DEFAULT_LANE_ID);

  // 使用智能IP检测
  logger.debug(`🔍 开始检测实例IP地址...`);
  const host = detectInstanceIP();
  logger.info(`🌐 最终使用的IP地址: ${host}`);

  // 创建服务实例元数据
  const metadata = {
    laneId: currentLaneId,                           // 泳道 ID
    environment: getEnvOrDefault('NODE_ENV', 'development'), // 环境
    registeredAt: new Date().toISOString(),          // 注册时间
    framework: 'nuxt3',                              // 框架
    version: getEnvOrDefault('npm_package_version', 'unknown'), // 版本
    hostname: os.hostname(),                         // 主机名
    nodeVersion: process.versions.node,              // Node.js 版本
  };

  // 检查服务名称是否有效
  const hasValidServiceName = !!serviceName;

  // 检查泳道功能是否启用
  const isLaneEnabled = hasValidServiceName ? getBooleanEnv('LANE_ENABLE', DEFAULT_LANE_ENABLED) : false;

  // 如果泳道功能启用但没有有效的服务名称，则停止应用
  if (isLaneEnabled && !hasValidServiceName) {
    logger.error(`❌ 错误: 泳道功能已启用，但无法获取有效的服务名称，应用将停止启动`);
    logger.error(`❌ 请通过以下方式之一设置服务名称:`);
    logger.error(`   1. 确保 server/package.json 或项目根目录的 package.json 中有 name 字段`);
    logger.error(`   2. 设置环境变量 SERVICE_NAME`);
    logger.error(`   3. 设置环境变量 NITRO_APP_NAME, APP_NAME 或 npm_package_name`);

    // 停止应用
    process.exit(1);
  }

  // 如果没有有效的服务名称但泳道功能未启用，则只显示警告
  if (!hasValidServiceName && !isLaneEnabled) {
    logger.error(`❌ 警告: 无法获取有效的服务名称，已自动禁用泳道功能`);
    logger.error(`❌ 请通过以下方式之一设置服务名称:`);
    logger.error(`   1. 确保 server/package.json 或项目根目录的 package.json 中有 name 字段`);
    logger.error(`   2. 设置环境变量 SERVICE_NAME`);
    logger.error(`   3. 设置环境变量 NITRO_APP_NAME, APP_NAME 或 npm_package_name`);
  }

  // 创建完整配置对象
  const config: LaneManagerConfig = {
    // Nacos 服务器配置
    nacosServerAddr,
    nacosServerPort,
    nacosUrl: `http://${nacosServerAddr}:${nacosServerPort}`,
    nacosNamespace: getEnvOrDefault('LANE_NAMESPACE', process.env.NACOS_NAMESPACE || DEFAULT_LANE_NAMESPACE),
    nacosGroupName: getEnvOrDefault('LANE_GROUP_NAME', process.env.NACOS_GROUP_NAME || DEFAULT_LANE_GROUP_NAME),

    // 服务配置
    serviceName,
    currentLaneId,
    host,
    port: null, // 初始为 null，将在服务启动时设置

    // 泳道配置
    targetLaneHeaderKey: (() => {
      // 详细记录 targetLaneHeaderKey 的获取过程
      logger.debug(`🔍 目标泳道请求头键名获取过程开始...`);
      logger.debug(`🔍 环境变量 LANE_TARGET_HEADER=${process.env.LANE_TARGET_HEADER}`);
      logger.debug(`🔍 环境变量 TARGET_LANE_HEADER=${process.env.TARGET_LANE_HEADER}`);
      logger.debug(`🔍 默认值 DEFAULT_LANE_TARGET_HEADER=${DEFAULT_LANE_TARGET_HEADER}`);

      const headerKey = getEnvOrDefault('LANE_TARGET_HEADER', process.env.TARGET_LANE_HEADER || DEFAULT_LANE_TARGET_HEADER);
      logger.debug(`🔍 最终使用的目标泳道请求头键名: ${headerKey}`);

      return headerKey;
    })(),
    // 使用前面计算的 isLaneEnabled 值
    isLaneEnabled: (() => {
      logger.debug(`🔍 泳道功能启用状态: ${isLaneEnabled} (hasValidServiceName=${hasValidServiceName}, LANE_ENABLE=${process.env.LANE_ENABLE}, DEFAULT_LANE_ENABLED=${DEFAULT_LANE_ENABLED})`);
      return isLaneEnabled;
    })(),
    isLaneCookieEnabled: (() => {
      const enabled = getBooleanEnv('LANE_COOKIE_ENABLE', DEFAULT_LANE_COOKIE_ENABLED);
      logger.debug(`🔍 Cookie泳道检测启用状态: ${enabled} (LANE_COOKIE_ENABLE=${process.env.LANE_COOKIE_ENABLE}, DEFAULT_LANE_COOKIE_ENABLED=${DEFAULT_LANE_COOKIE_ENABLED})`);
      return enabled;
    })(),

    // 超时配置
    proxyTimeout: getNumberEnv('LANE_PROXY_TIMEOUT', process.env.PROXY_TIMEOUT ? parseInt(process.env.PROXY_TIMEOUT) : DEFAULT_LANE_PROXY_TIMEOUT),
    registrationTimeout: getNumberEnv('LANE_REGISTRATION_TIMEOUT', process.env.REGISTRATION_TIMEOUT ? parseInt(process.env.REGISTRATION_TIMEOUT) : DEFAULT_LANE_REGISTRATION_TIMEOUT),
    heartbeatInterval: getNumberEnv('LANE_HEARTBEAT_INTERVAL', process.env.NACOS_HEARTBEAT_INTERVAL ? parseInt(process.env.NACOS_HEARTBEAT_INTERVAL) : DEFAULT_LANE_HEARTBEAT_INTERVAL),
    instanceTtl: getNumberEnv('LANE_INSTANCE_TTL', process.env.NACOS_INSTANCE_TTL ? parseInt(process.env.NACOS_INSTANCE_TTL) : DEFAULT_LANE_INSTANCE_TTL),

    // 元数据
    metadata,
  };

  // 记录配置信息
  logger.debug('🔧 已创建配置对象:', config);

  return config;
}

/**
 * 更新配置中的端口信息
 * 在服务启动后调用，设置实际的服务端口
 * @param port 服务端口
 */
export function updateConfigPort(port: number): void {
  if (!configCache) {
    configCache = createConfig();
  }

  configCache.port = port;
  logger.debug(`🔌 配置端口已更新: ${port}`);
}

/**
 * 全局状态接口
 * 定义了在全局对象上存储的泳道管理器状态
 */
export interface GlobalWithLaneManager {
  _laneMgrRegistered?: boolean;       // 是否已注册服务
  _laneMgrPort?: number;              // 服务端口
  _laneMgrHeartbeatTimer?: NodeJS.Timeout; // 心跳定时器
  _laneMgrHeartbeatCount?: number;    // 心跳计数器，用于控制日志打印频率
}

/**
 * 获取全局状态对象
 * 用于在不同模块间共享状态
 * @returns 全局状态对象
 */
export function getGlobalState(): GlobalWithLaneManager {
  return global as unknown as GlobalWithLaneManager;
}
