import type { H3Event } from "h3";
import type { ServiceInstanceInfo } from "../types";
import { getConfig, getGlobalState, updateConfigPort } from "../utils/config";
import {
  DEFAULT_PORT,
  DEFAULT_LANE_TARGET_HEADER,
  HEADER_LANE_DEBUG,
  HEADER_LANE_DETAIL,
  getSafeHeaderValue
} from "../utils/defaults";
import { logger } from "../utils/logger";
import { deregisterServiceInstance, getNacosLaneInstances, registerServiceInstance, startHeartbeat, stopHeartbeat } from "../utils/nacos";
import { LoadBalanceStrategy, proxyRequestWithFailover, selectInstance } from "../utils/proxy";

/**
 * 从cookie字符串中解析指定key的值
 *
 * @param cookieHeader cookie字符串，格式如 "key1=value1; key2=value2"
 * @param key 要查找的cookie键名
 * @returns 找到的cookie值，如果未找到则返回undefined
 */
function parseCookieValue(cookieHeader: string, key: string): string | undefined {
  console.log(`[multi-lane-manager] 解析Cookie: cookieHeader=${cookieHeader}, key=${key}`);

  if (!cookieHeader || !key) {
    console.log(`[multi-lane-manager] Cookie解析失败: cookieHeader或key为空`);
    return undefined;
  }

  // 将cookie字符串分割成键值对数组
  const cookies = cookieHeader.split(';');
  console.log(`[multi-lane-manager] Cookie分割结果: ${JSON.stringify(cookies)}`);

  // 查找匹配的cookie
  for (const cookie of cookies) {
    console.log(`[multi-lane-manager] 处理Cookie片段: ${cookie}`);

    const parts = cookie.split('=');
    if (parts.length < 2) {
      console.log(`[multi-lane-manager] 无效的Cookie格式: ${cookie}`);
      continue;
    }

    const cookieKey = parts[0].trim();
    const cookieValue = parts.slice(1).join('=').trim(); // 处理值中可能包含等号的情况

    console.log(`[multi-lane-manager] Cookie键值对: key=${cookieKey}, value=${cookieValue}`);

    // 不区分大小写比较cookie键名
    if (cookieKey.toLowerCase() === key.toLowerCase()) {
      console.log(`[multi-lane-manager] 找到匹配的Cookie: ${cookieKey}=${cookieValue}`);
      return cookieValue;
    }
  }

  console.log(`[multi-lane-manager] 未找到匹配的Cookie: ${key}`);
  return undefined;
}

/**
 * 从环境变量或 Nitro 配置中获取服务器端口
 * 优先使用环境变量中的端口配置
 *
 * @returns 服务器端口
 */
export function getServerPort(): number {
  // 优先使用环境变量中的端口
  const port = parseInt(process.env.NITRO_PORT || process.env.PORT || String(DEFAULT_PORT), 10);
  logger.debug(`🔍 从环境变量获取服务器端口: ${port}`);
  return port;
}

/**
 * 自动检测和注册服务实例
 * 这个函数主要负责服务注册和设置进程退出处理程序
 *
 * @returns 是否尝试了注册
 */
export function detectPortAndRegisterOnFirstRequest(): boolean {
  logger.info(`====== 🚀 开始端口检测和服务注册流程 ======`);

  // 获取配置
  logger.debug(`📋 正在加载配置...`);
  const config = getConfig();

  try {
    // 检查泳道功能是否启用
    logger.debug(`🔍 检查泳道功能是否启用: ${config.isLaneEnabled}`);
    if (!config.isLaneEnabled) {
      logger.debug(`🚫 泳道功能未启用，跳过初始注册`);
      return false;
    }

    // 获取服务器端口
    const serverPort = getServerPort();
    logger.info(`🔌 检测到服务器端口: ${serverPort}`);

    // 检查全局注册状态
    const globalState = getGlobalState();

    if (!globalState._laneMgrRegistered) {
      logger.info(`🆕 首次检测到端口 ${serverPort}，准备注册服务...`);

      // 设置全局注册状态
      globalState._laneMgrRegistered = true;
      globalState._laneMgrPort = serverPort;

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

      // 注册服务实例
      registerServiceInstance(serverPort)
        .then((success) => {
          if (success) {
            logger.info(`✅ 服务注册成功，设置进程退出处理程序`);

            // 创建优雅退出处理函数
            const gracefulShutdown = async () => {
              logger.info(`🛑 应用退出/信号，正在注销服务，端口=${serverPort}...`);
              await deregisterServiceInstance(serverPort);
            };

            // 注册进程退出事件处理程序
            process.on("beforeExit", gracefulShutdown);
            process.on("SIGINT", async () => {
              logger.info("🔴 收到 SIGINT 信号，执行注销...");
              await gracefulShutdown();
              process.exit(0);
            });
            process.on("SIGTERM", async () => {
              logger.info("🔴 收到 SIGTERM 信号，执行注销...");
              await gracefulShutdown();
              process.exit(0);
            });
          } else {
            logger.warn(`⚠️ 服务注册失败，不设置退出处理程序`);
          }
        })
        .catch((err) => {
          logger.error(`❌ 注册过程中出错: ${err.message}`, err.stack);
        });

      logger.info(`====== ✅ 端口检测和服务注册流程完成，返回 true ======`);
      return true;
    } else {
      logger.info(`ℹ️ 服务已注册 (端口: ${globalState._laneMgrPort})，跳过初始注册`);
    }

    logger.info(`====== ✅ 端口检测和服务注册流程完成，返回 false ======`);
    return false;
  } catch (error) {
    logger.error(
      `❌ 端口检测或初始注册错误: ${error instanceof Error ? error.message : String(error)}`,
      error instanceof Error ? error.stack : "",
    );
    return false;
  }
}

/**
 * 创建服务器中间件以处理跨泳道代理
 * 这个中间件负责检测请求的目标泳道，并在必要时将请求转发到目标泳道的实例
 * 注意：服务注册逻辑已移至 Nitro 插件
 *
 * @returns 中间件处理函数
 */
export function createServerMiddleware() {
  const config = getConfig();

  // 使用 console.log 确保日志一定会输出
  console.log(`[multi-lane-manager] 🔧 服务器中间件初始化: 启用状态=${config.isLaneEnabled}, 当前泳道ID=${config.currentLaneId}, 服务名=${config.serviceName}, 目标泳道Header=${config.targetLaneHeaderKey || DEFAULT_LANE_TARGET_HEADER.toLowerCase()}, Cookie检测=${config.isLaneCookieEnabled ? '启用' : '禁用'}`);

  logger.info(
    `🔧 服务器中间件初始化: 启用状态=${config.isLaneEnabled}, 当前泳道ID=${config.currentLaneId}, 服务名=${config.serviceName}, 目标泳道Header=${config.targetLaneHeaderKey || DEFAULT_LANE_TARGET_HEADER.toLowerCase()}, Cookie检测=${config.isLaneCookieEnabled ? '启用' : '禁用'}`,
  );

  return async (event: H3Event) => {
    // 检查是否启用了调试模式
    const debugHeaderKey = HEADER_LANE_DEBUG.toLowerCase();
    const debugHeaderValue = event.node.req.headers[debugHeaderKey];
    const isDebugMode = !!debugHeaderValue;

    // 记录调试模式检测过程
    console.log(`[multi-lane-manager] 调试模式检测: headerKey=${HEADER_LANE_DEBUG}, headerKeyLower=${debugHeaderKey}, value=${debugHeaderValue}, isDebugMode=${isDebugMode}`);
    const debugInfo: string[] = [];

    // 如果启用了调试模式，收集调试信息
    if (isDebugMode) {
      debugInfo.push(`请求时间: ${new Date().toISOString()}`);
      debugInfo.push(`请求路径: ${event.node.req.method} ${event.node.req.url || ""}`);
      debugInfo.push(`当前泳道: ${config.currentLaneId}`);
      debugInfo.push(`服务名称: ${config.serviceName}`);
    }

    // 检查请求是否已经被处理过
    if (event.context._laneManagerHandled) {
      if (isDebugMode) debugInfo.push(`状态: 请求已被泳道管理器处理，跳过`);
      logger.debug(`⏭️ 请求已被泳道管理器处理，跳过`);
      return;
    }

    const requestPath = event.node.req.url || "";

    // 特别记录 /_nuxt/ 路径的请求
    if (event.path.startsWith('/_nuxt/')) {
      console.log(`[multi-lane-manager] Intercepting _nuxt request2: ${event.path}`);
      logger.info(`🔍 拦截到静态资源请求: ${event.path}`);
    }

    // 特别记录 /api/ 路径的请求
    if (event.path.startsWith('/api/')) {
      console.log(`[multi-lane-manager] Intercepting API request: ${event.path}`);
      logger.info(`🔍 拦截到API请求: ${event.path}, 方法: ${event.node.req.method}, 头部: ${JSON.stringify(event.node.req.headers)}`);
    }

    // 强制使用 console.log 确保日志一定会输出
    console.log(`[multi-lane-manager] 📥 中间件接收请求: ${event.node.req.method} ${requestPath}`);
    logger.debug(`📥 中间件接收请求: ${event.node.req.method} ${requestPath}`);

    if (!config.isLaneEnabled) {
      if (isDebugMode) debugInfo.push(`状态: 泳道功能未启用，跳过代理逻辑`);
      logger.debug(`🚫 泳道功能未启用，跳过代理逻辑`);

      // 如果启用了调试模式，添加调试响应头
      if (isDebugMode && !event.node.res.headersSent) {
        try {
          event.node.res.setHeader(HEADER_LANE_DETAIL, getSafeHeaderValue(debugInfo));
        } catch (error) {
          logger.error(`❌ 设置调试响应头时出错: ${error instanceof Error ? error.message : String(error)}`);
        }
      }
      return;
    }

    // 标记请求正在被处理
    event.context._laneManagerProcessing = true;

    // 获取目标泳道ID
    const headerKey = config.targetLaneHeaderKey || DEFAULT_LANE_TARGET_HEADER;

    // 记录请求头信息，帮助调试
    console.log(`[multi-lane-manager] 请求头信息:`, event.node.req.headers);

    // HTTP 请求头是不区分大小写的，在 Node.js 中会被自动转换为小写
    const headerKeyLower = headerKey.toLowerCase();

    // 1. 首先尝试从header中获取泳道ID
    const requestTargetLaneIdHeaderValue = event.node.req.headers[headerKeyLower];
    let requestTargetLaneId = Array.isArray(requestTargetLaneIdHeaderValue)
      ? requestTargetLaneIdHeaderValue[0]?.trim()
      : requestTargetLaneIdHeaderValue?.trim();

    // 记录泳道ID获取过程
    console.log(`[multi-lane-manager] 尝试从请求头获取泳道ID: headerKey=${headerKey}, headerKeyLower=${headerKeyLower}, value=${requestTargetLaneIdHeaderValue}`);

    if (isDebugMode) {
      debugInfo.push(`目标泳道Header键: ${headerKey} (实际查找: ${headerKeyLower})`);
    }

    // 2. 如果header中没有泳道ID，且启用了cookie功能，则尝试从cookie中获取
    if (!requestTargetLaneId && config.isLaneCookieEnabled) {
      const cookieHeader = event.node.req.headers.cookie;
      if (cookieHeader) {
        // 记录 Cookie 信息，帮助调试
        console.log(`[multi-lane-manager] Cookie信息: ${cookieHeader}`);

        // 从cookie字符串中解析出目标泳道ID
        // 使用与header完全相同的键名，不再移除'x-'前缀
        const cookieKey = headerKey;
        const cookieValue = parseCookieValue(cookieHeader, cookieKey);

        // 记录 Cookie 解析过程
        console.log(`[multi-lane-manager] 尝试从Cookie获取泳道ID: cookieKey=${cookieKey}, value=${cookieValue}`);

        if (cookieValue) {
          requestTargetLaneId = cookieValue.trim();
          console.log(`[multi-lane-manager] 🍪 从Cookie中获取到泳道ID: ${requestTargetLaneId}, Cookie键名: ${cookieKey}`);
          logger.debug(`🍪 从Cookie中获取到泳道ID: ${requestTargetLaneId}, Cookie键名: ${cookieKey}`);
          if (isDebugMode) debugInfo.push(`泳道ID来源: Cookie, 值: ${requestTargetLaneId}`);
        } else if (isDebugMode) {
          debugInfo.push(`Cookie中未找到泳道ID, Cookie键: ${cookieKey}`);
        }
      } else if (isDebugMode) {
        debugInfo.push(`请求中没有Cookie`);
      }
    } else if (requestTargetLaneId) {
      console.log(`[multi-lane-manager] 🔤 从Header中获取到泳道ID: ${requestTargetLaneId}`);
      logger.debug(`🔤 从Header中获取到泳道ID: ${requestTargetLaneId}`);
      if (isDebugMode) debugInfo.push(`泳道ID来源: Header, 值: ${requestTargetLaneId}`);
    } else if (isDebugMode) {
      debugInfo.push(`未找到泳道ID`);
    }

    // 处理请求的泳道路由逻辑
    if (requestTargetLaneId && requestTargetLaneId !== config.currentLaneId) {
      // 1. 如果请求指定了目标泳道，且与当前泳道不同，则进行代理
      // 确定泳道ID的来源
      const sourceType = event.node.req.headers[headerKey] ? 'Header' : 'Cookie';

      // 使用 console.log 确保日志一定会输出
      console.log(`[multi-lane-manager] 🔀 检测到跨泳道请求: 当前泳道=${config.currentLaneId}, 目标泳道=${requestTargetLaneId} (来源: ${sourceType}), 路径: ${event.path}`);
      logger.info(`🔀 检测到跨泳道请求: 当前泳道=${config.currentLaneId}, 目标泳道=${requestTargetLaneId} (来源: ${sourceType}), 路径: ${event.path}`);

      if (isDebugMode) {
        debugInfo.push(`处理: 跨泳道请求`);
        debugInfo.push(`目标泳道: ${requestTargetLaneId}`);
      }
    } else if (!requestTargetLaneId) {
      // 2. 如果请求没有指定泳道ID，尝试路由到 baseline 泳道
      logger.debug(`🔍 请求未指定泳道ID，尝试查找 baseline 泳道实例`);

      if (isDebugMode) {
        debugInfo.push(`处理: 未指定泳道ID，尝试路由到 baseline 泳道`);
      }

      // 如果当前已经是 baseline 泳道，直接在本地处理
      if (config.currentLaneId === 'baseline') {
        logger.debug(`✅ 当前已是 baseline 泳道，在本地处理请求`);

        if (isDebugMode) {
          debugInfo.push(`状态: 当前已是 baseline 泳道，在本地处理`);

          // 如果启用了调试模式，添加调试响应头
          if (!event.node.res.headersSent) {
            try {
              event.node.res.setHeader(HEADER_LANE_DETAIL, getSafeHeaderValue(debugInfo));
            } catch (error) {
              logger.error(`❌ 设置调试响应头时出错: ${error instanceof Error ? error.message : String(error)}`);
            }
          }
        }

        // 清除处理中标记，但不标记为已处理，因为请求将由后续中间件处理
        event.context._laneManagerProcessing = false;
        return;
      }

      // 设置目标泳道ID为 baseline
      requestTargetLaneId = 'baseline';

      if (isDebugMode) {
        debugInfo.push(`目标泳道: ${requestTargetLaneId} (默认)`);
      }

    }

    // 如果有目标泳道ID（可能是请求中指定的，也可能是默认的 baseline），且与当前泳道不同，则尝试进行代理
    if (requestTargetLaneId && requestTargetLaneId !== config.currentLaneId) {
      try {
        // 获取目标泳道的服务实例（按心跳时间排序）
        const targetInstances = await getNacosLaneInstances(config.serviceName, requestTargetLaneId, true);

        if (isDebugMode) {
          debugInfo.push(`找到实例数量: ${targetInstances.length}`);
        }

        if (targetInstances.length > 0) {
          // 使用负载均衡策略选择一个实例
          const targetInstance = selectInstance(
            targetInstances,
            config.serviceName,
            LoadBalanceStrategy.ROUND_ROBIN
          );

          if (isDebugMode) {
            debugInfo.push(`选择实例: ${targetInstance.ip}:${targetInstance.port}`);
            debugInfo.push(`负载均衡策略: ROUND_ROBIN`);

            // 添加调试响应头
            if (!event.node.res.headersSent) {
              try {
                event.node.res.setHeader(HEADER_LANE_DETAIL, getSafeHeaderValue(debugInfo));
              } catch (error) {
                logger.error(`❌ 设置调试响应头时出错: ${error instanceof Error ? error.message : String(error)}`);
              }
            }
          }

          // 转发请求到目标实例（使用故障转移）
          await proxyRequestWithFailover(event, targetInstance, isDebugMode, targetInstances);
          return;
        } else {
          // 如果是尝试路由到 baseline 但没找到实例，则在当前实例处理
          if (requestTargetLaneId === 'baseline' && !event.node.req.headers[headerKey]) {
            logger.info(`🔄 未找到 baseline 泳道实例，在当前泳道 ${config.currentLaneId} 处理请求`);

            if (isDebugMode) {
              debugInfo.push(`状态: 未找到 baseline 泳道实例，在当前泳道处理`);

              // 如果启用了调试模式，添加调试响应头
              if (!event.node.res.headersSent) {
                try {
                  event.node.res.setHeader(HEADER_LANE_DETAIL, getSafeHeaderValue(debugInfo));
                } catch (error) {
                  logger.error(`❌ 设置调试响应头时出错: ${error instanceof Error ? error.message : String(error)}`);
                }
              }
            }

            // 清除处理中标记，但不标记为已处理，因为请求将由后续中间件处理
            event.context._laneManagerProcessing = false;
            return;
          }

          // 对于明确指定了泳道ID的请求，如果找不到实例，尝试查找 baseline 泳道
          logger.warn(`⚠️ 未找到泳道 ${requestTargetLaneId} 的健康实例，尝试查找 baseline 泳道`);

          if (isDebugMode) {
            debugInfo.push(`警告: 未找到泳道 ${requestTargetLaneId} 的健康实例，尝试查找 baseline 泳道`);
          }

          // 如果当前请求的泳道不是 baseline，则尝试查找 baseline 泳道
          if (requestTargetLaneId !== 'baseline') {
            console.log(`[multi-lane-manager] 尝试查找 baseline 泳道实例`);

            // 获取 baseline 泳道的服务实例（按心跳时间排序）
            const baselineInstances = await getNacosLaneInstances(config.serviceName, 'baseline', true);

            if (baselineInstances.length > 0) {
              console.log(`[multi-lane-manager] 找到 baseline 泳道实例，将请求转发到 baseline 泳道`);
              logger.info(`✅ 找到 baseline 泳道实例，将请求转发到 baseline 泳道`);

              if (isDebugMode) {
                debugInfo.push(`状态: 找到 baseline 泳道实例，将请求转发到 baseline 泳道`);
              }

              // 使用负载均衡策略选择一个实例
              const baselineInstance = selectInstance(
                baselineInstances,
                config.serviceName,
                LoadBalanceStrategy.ROUND_ROBIN
              );

              if (isDebugMode) {
                debugInfo.push(`选择实例: ${baselineInstance.ip}:${baselineInstance.port}`);
                debugInfo.push(`负载均衡策略: ROUND_ROBIN`);

                // 添加调试响应头
                if (!event.node.res.headersSent) {
                  try {
                    event.node.res.setHeader(HEADER_LANE_DETAIL, getSafeHeaderValue(debugInfo));
                  } catch (error) {
                    logger.error(`❌ 设置调试响应头时出错: ${error instanceof Error ? error.message : String(error)}`);
                  }
                }
              }

              // 转发请求到 baseline 实例（使用故障转移）
              await proxyRequestWithFailover(event, baselineInstance, isDebugMode, baselineInstances);
              return;
            } else {
              console.log(`[multi-lane-manager] 未找到 baseline 泳道实例，在当前泳道处理请求`);
              logger.info(`🔄 未找到 baseline 泳道实例，在当前泳道 ${config.currentLaneId} 处理请求`);

              if (isDebugMode) {
                debugInfo.push(`状态: 未找到 baseline 泳道实例，在当前泳道处理请求`);
              }

              // 清除处理中标记，但不标记为已处理，因为请求将由后续中间件处理
              event.context._laneManagerProcessing = false;

              // 如果启用了调试模式，添加调试响应头
              if (isDebugMode && !event.node.res.headersSent) {
                try {
                  event.node.res.setHeader(HEADER_LANE_DETAIL, getSafeHeaderValue(debugInfo));
                } catch (error) {
                  logger.error(`❌ 设置调试响应头时出错: ${error instanceof Error ? error.message : String(error)}`);
                }
              }

              return;
            }
          } else {
            // 如果当前请求的泳道已经是 baseline，但仍然没有找到实例，则在当前泳道处理
            console.log(`[multi-lane-manager] 已经是 baseline 泳道但未找到实例，在当前泳道处理请求`);
            logger.info(`🔄 已经是 baseline 泳道但未找到实例，在当前泳道 ${config.currentLaneId} 处理请求`);

            if (isDebugMode) {
              debugInfo.push(`状态: 已经是 baseline 泳道但未找到实例，在当前泳道处理请求`);
            }

            // 清除处理中标记，但不标记为已处理，因为请求将由后续中间件处理
            event.context._laneManagerProcessing = false;

            // 如果启用了调试模式，添加调试响应头
            if (isDebugMode && !event.node.res.headersSent) {
              try {
                event.node.res.setHeader(HEADER_LANE_DETAIL, getSafeHeaderValue(debugInfo));
              } catch (error) {
                logger.error(`❌ 设置调试响应头时出错: ${error instanceof Error ? error.message : String(error)}`);
              }
            }

            return;
          }
        }
      } catch (e) {
        logger.error(`❌ 处理跨泳道请求时发生错误: ${e instanceof Error ? e.message : String(e)}`);

        if (isDebugMode) {
          debugInfo.push(`错误: ${e instanceof Error ? e.message : String(e)}`);
        }

        if (!event.node.res.headersSent) {
          // 如果启用了调试模式，添加调试响应头
          if (isDebugMode) {
            try {
              event.node.res.setHeader(HEADER_LANE_DETAIL, getSafeHeaderValue(debugInfo));
            } catch (error) {
              logger.error(`❌ 设置调试响应头时出错: ${error instanceof Error ? error.message : String(error)}`);
            }
          }

          event.node.res.statusCode = 500; // Internal Server Error
          event.node.res.setHeader("Content-Type", "text/plain");
          event.node.res.end("处理泳道请求时发生内部服务器错误。");
        }
        // 标记请求已处理
        event.context._laneManagerHandled = true;
        return;
      }
    }

    logger.debug(`✅ 请求在当前泳道 (${config.currentLaneId}) 处理或无目标泳道指定，将由后续处理程序处理。`);

    if (isDebugMode) {
      debugInfo.push(`处理: 在当前泳道处理请求`);

      // 如果启用了调试模式，添加调试响应头
      if (!event.node.res.headersSent) {
        try {
          event.node.res.setHeader(HEADER_LANE_DETAIL, getSafeHeaderValue(debugInfo));
        } catch (error) {
          logger.error(`❌ 设置调试响应头时出错: ${error instanceof Error ? error.message : String(error)}`);
        }
      }
    }

    // 清除处理中标记，但不标记为已处理，因为请求将由后续中间件处理
    event.context._laneManagerProcessing = false;
  };
}

// 导出 Nacos 相关函数，方便其他模块使用
export { getNacosLaneInstances };
