import axios from 'axios';
import type { ServiceInstanceInfo } from '../types';
import { getConfig, getGlobalState, updateConfigPort } from './config';
import { logger } from './logger';

/**
 * Nacos 实例查询缓存项
 */
interface NacosCacheItem {
  data: ServiceInstanceInfo[];     // 缓存的实例数据
  timestamp: number;               // 缓存时间戳
  promise?: Promise<ServiceInstanceInfo[]>; // 正在进行的请求 Promise（用于去重）
}

/**
 * Nacos 实例查询缓存
 * 使用 Map 存储缓存，key 为 "serviceName:targetLaneId" 格式
 */
const nacosInstanceCache = new Map<string, NacosCacheItem>();

/**
 * 生成缓存键
 * @param serviceName 服务名称
 * @param targetLaneId 目标泳道ID
 * @returns 缓存键
 */
function getCacheKey(serviceName: string, targetLaneId: string): string {
  return `${serviceName}:${targetLaneId}`;
}

/**
 * 检查缓存是否有效
 * @param cacheItem 缓存项
 * @param ttl 缓存过期时间（毫秒）
 * @returns 是否有效
 */
function isCacheValid(cacheItem: NacosCacheItem, ttl: number): boolean {
  return Date.now() - cacheItem.timestamp < ttl;
}

/**
 * 清理过期的缓存项
 * @param ttl 缓存过期时间（毫秒）
 */
function cleanExpiredCache(ttl: number): void {
  const now = Date.now();
  for (const [key, item] of nacosInstanceCache.entries()) {
    if (now - item.timestamp >= ttl) {
      nacosInstanceCache.delete(key);
      logger.debug(`🗑️ 清理过期缓存: ${key}`);
    }
  }
}

/**
 * Nacos 实例接口
 * 定义了从 Nacos 服务器返回的实例数据结构
 */
export interface NacosInstance {
  instanceId: string;           // 实例 ID
  ip: string;                   // 实例 IP 地址
  port: number;                 // 实例端口
  weight: number;               // 实例权重
  healthy: boolean;             // 实例是否健康
  enabled: boolean;             // 实例是否启用
  ephemeral: boolean;           // 是否为临时实例
  clusterName: string;          // 集群名称
  serviceName: string;          // 服务名称
  metadata: Record<string, string>; // 实例元数据
  instanceHeartBeatInterval?: number; // 心跳间隔
}

/**
 * Nacos 服务列表响应接口
 * 定义了 Nacos 服务实例列表查询的响应结构
 */
export interface NacosServiceListResponse {
  name?: string;                // 服务名称
  groupName?: string;           // 分组名称
  clusters?: string;            // 集群名称
  cacheMillis?: number;         // 缓存时间
  hosts: NacosInstance[];       // 实例列表
  lastRefTime?: number;         // 最后刷新时间
  checksum?: string;            // 校验和
  allIPs?: boolean;             // 是否包含所有 IP
  env?: string;                 // 环境
}

/**
 * 注册服务实例到 Nacos
 * 将当前服务实例注册到 Nacos 服务注册中心
 *
 * @param port 服务端口
 * @returns 注册是否成功
 */
export async function registerServiceInstance(port: number): Promise<boolean> {
  const config = getConfig();

  // 检查泳道功能是否启用
  if (!config.isLaneEnabled) {
    logger.debug('🚫 泳道功能未启用，跳过服务注册');
    return true;
  }

  try {
    logger.debug(`🚀 开始服务注册流程，时间戳: ${new Date().toISOString()}`);

    // 更新配置中的端口
    updateConfigPort(port);

    // 构建注册请求
    const registrationUrl = `${config.nacosUrl}/nacos/v1/ns/instance`;
    const params = new URLSearchParams();

    // 设置基本参数
    params.append('serviceName', config.serviceName);
    params.append('ip', config.host);
    params.append('port', port.toString());
    params.append('weight', '1.0');
    params.append('healthy', 'true');
    params.append('metadata', JSON.stringify(config.metadata));
    params.append('clusterName', config.currentLaneId || 'DEFAULT');
    params.append('ephemeral', 'true');

    // 添加过期时间参数
    params.append('ipDeleteTimeout', config.instanceTtl.toString());
    params.append('instanceHeartBeatInterval', config.heartbeatInterval.toString());
    params.append('instanceHeartBeatTimeOut', (config.heartbeatInterval * 2).toString());

    // 发送注册请求
    logger.debug(`📤 发送注册请求到 Nacos: ${registrationUrl}`);

    const response = await axios.post(registrationUrl, params, {
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent': 'Nuxt3-LaneManager/1.0',
      },
      timeout: config.registrationTimeout,
    });

    // 记录响应结果
    logger.debug(`📥 注册响应状态码: ${response.status}, 数据: ${JSON.stringify(response.data)}`);

    if (response.status === 200 && response.data === 'ok') {
      logger.success(`✅ 服务注册成功: ${config.serviceName}@${config.host}:${port} (泳道: ${config.currentLaneId})`);

      // 设置全局状态
      const globalState = getGlobalState();
      globalState._laneMgrRegistered = true;
      globalState._laneMgrPort = port;

      // 启动心跳
      startHeartbeat(port);

      return true;
    } else {
      logger.error(`❌ 服务注册失败: ${response.data}`);
      return false;
    }
  } catch (error) {
    logger.error(`❌ 服务注册错误: ${error instanceof Error ? error.message : String(error)}`);
    if (axios.isAxiosError(error) && error.response) {
      logger.error(`🔴 HTTP状态码: ${error.response.status}, 响应: ${JSON.stringify(error.response.data)}`);
    }
    return false;
  }
}

/**
 * 从 Nacos 注销服务实例
 * 从 Nacos 服务注册中心注销当前服务实例
 *
 * @param port 服务端口
 * @returns 注销是否成功
 */
export async function deregisterServiceInstance(port: number): Promise<boolean> {
  const config = getConfig();

  // 检查泳道功能是否启用
  if (!config.isLaneEnabled) {
    logger.debug('🚫 泳道功能未启用，跳过服务注销');
    return true;
  }

  try {
    // 停止心跳
    stopHeartbeat();

    // 构建注销请求
    const deregistrationUrl = `${config.nacosUrl}/nacos/v1/ns/instance`;
    const params = new URLSearchParams();
    params.append('serviceName', config.serviceName);
    params.append('ip', config.host);
    params.append('port', port.toString());
    params.append('ephemeral', 'true');

    // 发送注销请求
    logger.debug(`📤 发送注销请求到 Nacos: ${deregistrationUrl}`);

    const response = await axios.delete(`${deregistrationUrl}?${params.toString()}`, {
      timeout: config.registrationTimeout,
    });

    // 记录响应结果
    logger.debug(`📥 注销响应状态码: ${response.status}, 数据: ${JSON.stringify(response.data)}`);

    if (response.status === 200 && response.data === 'ok') {
      logger.success(`✅ 服务注销成功: ${config.serviceName}@${config.host}:${port}`);

      // 更新全局状态
      const globalState = getGlobalState();
      globalState._laneMgrRegistered = false;
      globalState._laneMgrPort = undefined;

      return true;
    } else {
      logger.error(`❌ 服务注销失败: ${response.data}`);
      return false;
    }
  } catch (error) {
    logger.error(`❌ 服务注销错误: ${error instanceof Error ? error.message : String(error)}`);
    return false;
  }
}

/**
 * 发送心跳到 Nacos
 * 定期向 Nacos 发送心跳，保持服务实例的活跃状态
 *
 * @param port 服务端口
 * @param logDetails 是否打印详细日志，默认为 false
 * @returns 心跳是否成功
 */
export async function sendHeartbeat(port: number, logDetails: boolean = false): Promise<boolean> {
  const config = getConfig();

  // 检查泳道功能是否启用
  if (!config.isLaneEnabled) {
    if (logDetails) {
      logger.debug('🚫 泳道功能未启用，跳过心跳');
    }
    return true;
  }

  try {
    // 构建心跳请求
    const heartbeatUrl = `${config.nacosUrl}/nacos/v1/ns/instance/beat`;
    const params = new URLSearchParams();
    params.append('serviceName', config.serviceName);
    params.append('ip', config.host);
    params.append('port', port.toString());

    // 构建心跳数据
    const now = new Date();
    const beat = {
      serviceName: config.serviceName,
      ip: config.host,
      port: port,
      weight: 1.0,
      metadata: {
        ...config.metadata,
        lastHeartbeat: now.toISOString(), // 添加心跳时间戳
        heartbeatTimestamp: now.getTime().toString(), // 添加时间戳（毫秒）
      },
      cluster: config.currentLaneId,
      scheduled: false
    };

    params.append('beat', JSON.stringify(beat));

    // 发送心跳请求（只在需要时打印日志）
    if (logDetails) {
      logger.debug(`💓 发送心跳到 Nacos: ${heartbeatUrl}`);
    }

    const response = await axios.put(`${heartbeatUrl}?${params.toString()}`, null, {
      headers: {
        'User-Agent': 'Nuxt3-LaneManager/1.0',
      },
      timeout: config.registrationTimeout / 2, // 心跳超时时间应该比注册短
    });

    // 记录响应结果（只在需要时打印日志）
    if (logDetails) {
      logger.debug(`📥 心跳响应状态码: ${response.status}, 数据: ${JSON.stringify(response.data)}`);
    }

    if (response.status === 200) {
      if (logDetails) {
        logger.debug(`✅ 心跳成功: ${config.serviceName}@${config.host}:${port}`);
      }
      return true;
    } else {
      // 失败总是打印日志，无论 logDetails 如何设置
      logger.warn(`⚠️ 心跳失败: ${response.data}`);
      return false;
    }
  } catch (error) {
    logger.error(`❌ 心跳错误: ${error instanceof Error ? error.message : String(error)}`);
    return false;
  }
}

/**
 * 启动心跳定时器
 * 创建一个定时器，定期向 Nacos 发送心跳
 *
 * @param port 服务端口
 */
export function startHeartbeat(port: number): void {
  const config = getConfig();
  const globalState = getGlobalState();

  // 如果已经有心跳定时器，先停止
  stopHeartbeat();

  // 初始化心跳计数器
  globalState._laneMgrHeartbeatCount = 0;

  // 创建新的心跳定时器
  logger.info(`⏱️ 启动心跳定时器，间隔: ${config.heartbeatInterval}毫秒，每30次心跳打印一次日志`);

  globalState._laneMgrHeartbeatTimer = setInterval(async () => {
    try {
      // 增加心跳计数器
      if (globalState._laneMgrHeartbeatCount !== undefined) {
        globalState._laneMgrHeartbeatCount++;
      } else {
        globalState._laneMgrHeartbeatCount = 1;
      }

      // 是否打印详细日志（每30次打印一次）
      const shouldLogDetails = globalState._laneMgrHeartbeatCount % 30 === 0;

      // 发送心跳
      await sendHeartbeat(port, shouldLogDetails);

      // 如果达到30次，在日志中显示计数器状态
      if (shouldLogDetails) {
        logger.info(`💓 心跳计数: ${globalState._laneMgrHeartbeatCount}，继续保持连接...`);
      }
    } catch (error) {
      logger.error(`❌ 心跳定时器错误: ${error instanceof Error ? error.message : String(error)}`);
    }
  }, config.heartbeatInterval);
}

/**
 * 停止心跳定时器
 * 清除心跳定时器，通常在服务注销时调用
 */
export function stopHeartbeat(): void {
  const globalState = getGlobalState();

  if (globalState._laneMgrHeartbeatTimer) {
    logger.info('⏹️ 停止心跳定时器');
    clearInterval(globalState._laneMgrHeartbeatTimer);
    globalState._laneMgrHeartbeatTimer = undefined;
    globalState._laneMgrHeartbeatCount = 0; // 重置心跳计数器
  }
}

/**
 * 内部函数：直接从 Nacos 查询实例（不使用缓存）
 * @param serviceName 服务名称
 * @param targetLaneId 目标泳道ID
 * @param sortByHeartbeat 是否按心跳时间排序
 * @returns 健康服务实例列表
 */
async function fetchNacosLaneInstancesFromServer(
  serviceName: string,
  targetLaneId: string,
  sortByHeartbeat: boolean = true
): Promise<ServiceInstanceInfo[]> {
  const config = getConfig();

  logger.debug(`📡 直接从 Nacos 服务器查询实例，服务名: ${serviceName}, 目标泳道: ${targetLaneId}`);

  try {
    // 构建查询 URL
    const nacosListUrl = `${config.nacosUrl}/nacos/v1/ns/instance/list`;

    // 设置查询参数
    const params = new URLSearchParams({
      serviceName,
      healthyOnly: 'true', // 只获取健康实例
      groupName: config.nacosGroupName,
    });

    // 添加命名空间参数（如果有）
    if (config.nacosNamespace) {
      params.append('namespaceId', config.nacosNamespace);
    }

    logger.debug(`📤 Nacos 实例查询 URL: ${nacosListUrl}?${params.toString()}`);

    // 发送查询请求
    const response = await axios.get<NacosServiceListResponse>(`${nacosListUrl}?${params.toString()}`, {
      timeout: config.registrationTimeout,
    });

    logger.debug(`📥 Nacos 实例查询响应状态: ${response.status}`);

    // 处理响应数据
    if (response.data && response.data.hosts) {
      // 过滤出目标泳道的健康实例
      const filteredInstances = response.data.hosts
        .filter(
          (instance) =>
            instance.healthy && instance.enabled && instance.metadata && instance.metadata.laneId === targetLaneId,
        )
        .map(
          (instance): ServiceInstanceInfo => {
            // 尝试从元数据中获取最后心跳时间
            let lastHeartbeat = Date.now();

            // 检查实例元数据中是否有心跳时间信息
            if (instance.metadata?.heartbeatTimestamp) {
              // 优先使用数字时间戳（毫秒）
              try {
                const timestamp = parseInt(instance.metadata.heartbeatTimestamp, 10);
                if (!isNaN(timestamp) && timestamp > 0) {
                  lastHeartbeat = timestamp;
                }
              } catch (error) {
                logger.debug(`⚠️ 解析实例 ${instance.ip}:${instance.port} 数字时间戳失败: ${error}`);
              }
            } else if (instance.metadata?.lastHeartbeat) {
              // 备选：使用ISO字符串时间戳
              try {
                const heartbeatTime = new Date(instance.metadata.lastHeartbeat).getTime();
                if (!isNaN(heartbeatTime)) {
                  lastHeartbeat = heartbeatTime;
                }
              } catch (error) {
                logger.debug(`⚠️ 解析实例 ${instance.ip}:${instance.port} ISO时间戳失败: ${error}`);
              }
            }

            // 如果Nacos返回了实例的心跳间隔信息，可以估算最后心跳时间
            if (instance.instanceHeartBeatInterval && !instance.metadata?.lastHeartbeat) {
              // 使用当前时间减去心跳间隔的一半作为估算值
              lastHeartbeat = Date.now() - (instance.instanceHeartBeatInterval / 2);
            }

            return {
              ip: instance.ip,
              port: instance.port,
              serviceName: instance.serviceName,
              clusterName: instance.clusterName,
              ephemeral: instance.ephemeral,
              metadata: instance.metadata,
              status: 'UP',
              lastHeartbeat,
              version: instance.metadata?.version || 'unknown',
            };
          },
        );

      // 如果需要按心跳时间排序
      if (sortByHeartbeat) {
        filteredInstances.sort((a, b) => {
          // 按最后心跳时间降序排列（最近心跳的在前）
          const timeA = typeof a.lastHeartbeat === 'number' ? a.lastHeartbeat : new Date(a.lastHeartbeat).getTime();
          const timeB = typeof b.lastHeartbeat === 'number' ? b.lastHeartbeat : new Date(b.lastHeartbeat).getTime();
          return timeB - timeA;
        });

        logger.debug(`🔄 已按心跳时间排序 ${filteredInstances.length} 个实例`);

        // 在调试模式下输出排序后的实例信息
        if (filteredInstances.length > 0) {
          logger.debug(`📊 实例心跳时间排序结果:`);
          filteredInstances.forEach((instance, index) => {
            const heartbeatTime = typeof instance.lastHeartbeat === 'number'
              ? new Date(instance.lastHeartbeat).toISOString()
              : instance.lastHeartbeat;
            logger.debug(`  ${index + 1}. ${instance.ip}:${instance.port} - 心跳时间: ${heartbeatTime}`);
          });
        }
      }

      logger.info(`✅ 从服务器查询到 ${filteredInstances.length} 个属于泳道 ${targetLaneId} 的健康实例${sortByHeartbeat ? '（已按心跳时间排序）' : ''}`);
      return filteredInstances;
    } else {
      logger.warn(`⚠️ Nacos 实例查询响应格式不正确或无实例列表:`, response.data);
      return [];
    }
  } catch (error) {
    logger.error(`❌ Nacos 实例查询失败: ${error instanceof Error ? error.message : String(error)}`);
    if (axios.isAxiosError(error) && error.response) {
      logger.error(`🔴 HTTP状态码: ${error.response.status}, 响应: ${JSON.stringify(error.response.data)}`);
    }
    return [];
  }
}

/**
 * 从 Nacos 获取指定泳道的健康服务实例（带缓存）
 * 查询 Nacos 获取指定服务名称和泳道 ID 的健康实例列表
 * 支持按心跳时间排序，优先选择最近心跳的实例
 * 使用缓存和请求去重机制提高性能
 *
 * @param serviceName 服务名称
 * @param targetLaneId 目标泳道ID
 * @param sortByHeartbeat 是否按心跳时间排序（最近心跳的在前）
 * @returns 健康服务实例列表
 */
export async function getNacosLaneInstances(
  serviceName: string,
  targetLaneId: string,
  sortByHeartbeat: boolean = true
): Promise<ServiceInstanceInfo[]> {
  const config = getConfig();
  const cacheKey = getCacheKey(serviceName, targetLaneId);
  const cacheTtl = config.nacosCacheTtl;

  // 使用 console.log 确保日志一定会输出
  console.log(`[multi-lane-manager] 🔍 获取 Nacos 实例，服务名: ${serviceName}, 目标泳道: ${targetLaneId}`);
  logger.debug(`🔍 获取 Nacos 实例，服务名: ${serviceName}, 目标泳道: ${targetLaneId}, 缓存TTL: ${cacheTtl}ms`);

  // 定期清理过期缓存
  cleanExpiredCache(cacheTtl);

  // 检查缓存
  const cachedItem = nacosInstanceCache.get(cacheKey);
  if (cachedItem) {
    // 如果有正在进行的请求，等待该请求完成（请求去重）
    if (cachedItem.promise) {
      logger.debug(`⏳ 发现正在进行的请求，等待完成: ${cacheKey}`);
      try {
        return await cachedItem.promise;
      } catch (error) {
        // 如果正在进行的请求失败，移除缓存项并继续执行新请求
        logger.warn(`⚠️ 正在进行的请求失败，移除缓存: ${cacheKey}, 错误: ${error}`);
        nacosInstanceCache.delete(cacheKey);
      }
    }
    // 如果缓存有效，直接返回缓存数据
    else if (isCacheValid(cachedItem, cacheTtl)) {
      logger.debug(`💾 使用缓存数据: ${cacheKey}, 缓存时间: ${new Date(cachedItem.timestamp).toISOString()}`);
      return cachedItem.data;
    }
    // 缓存过期，移除缓存项
    else {
      logger.debug(`⏰ 缓存已过期，移除: ${cacheKey}`);
      nacosInstanceCache.delete(cacheKey);
    }
  }

  // 创建新的请求 Promise
  logger.debug(`🌐 创建新的 Nacos 查询请求: ${cacheKey}`);
  const requestPromise = fetchNacosLaneInstancesFromServer(serviceName, targetLaneId, sortByHeartbeat);

  // 将 Promise 存储到缓存中（用于请求去重）
  nacosInstanceCache.set(cacheKey, {
    data: [], // 临时空数据
    timestamp: Date.now(),
    promise: requestPromise,
  });

  try {
    // 等待请求完成
    const result = await requestPromise;

    // 更新缓存，移除 Promise
    nacosInstanceCache.set(cacheKey, {
      data: result,
      timestamp: Date.now(),
    });

    logger.debug(`✅ 请求完成，已缓存结果: ${cacheKey}, 实例数量: ${result.length}`);
    return result;
  } catch (error) {
    // 请求失败，移除缓存项
    nacosInstanceCache.delete(cacheKey);
    logger.error(`❌ Nacos 查询请求失败，移除缓存: ${cacheKey}, 错误: ${error}`);
    throw error;
  }
}

/**
 * 清理所有 Nacos 实例查询缓存
 * 用于手动清理缓存或在配置变更时重置缓存
 */
export function clearNacosInstanceCache(): void {
  const cacheSize = nacosInstanceCache.size;
  nacosInstanceCache.clear();
  logger.info(`🗑️ 已清理所有 Nacos 实例缓存，清理了 ${cacheSize} 个缓存项`);
}

/**
 * 获取当前缓存状态信息
 * 用于调试和监控
 */
export function getNacosCacheStats(): {
  totalItems: number;
  validItems: number;
  expiredItems: number;
  pendingRequests: number;
} {
  const config = getConfig();
  const cacheTtl = config.nacosCacheTtl;
  const now = Date.now();

  let validItems = 0;
  let expiredItems = 0;
  let pendingRequests = 0;

  for (const item of nacosInstanceCache.values()) {
    if (item.promise) {
      pendingRequests++;
    } else if (now - item.timestamp < cacheTtl) {
      validItems++;
    } else {
      expiredItems++;
    }
  }

  return {
    totalItems: nacosInstanceCache.size,
    validItems,
    expiredItems,
    pendingRequests,
  };
}
