"""
MCP服务器创建和管理模块

这是lzwcai-mcp-dyntoolapi项目的核心模块，负责：
1. 创建和配置MCP服务器
2. 动态加载业务API配置
3. 注册API工具插件
4. 处理工具调用请求
5. 支持配置热加载
6. 支持多租户场景（内存模式）

主要功能:
- 从业务平台获取API配置
- 将API配置转换为MCP工具
- 处理认证和参数验证
- 支持多种传输方式（stdio、SSE）
- 支持两种配置模式：文件模式和内存模式

配置模式说明:
1. 内存模式（configMode=memory，默认）：
   - 根据businessUuid创建变量business{businessUuid}存储配置
   - 配置存储在内存中，不写入本地文件
   - 支持多个租户共享同一个包实例
   - 适用于多租户SaaS场景

2. 文件模式（configMode=file）：
   - 从业务平台获取配置后保存到本地api_config.json文件
   - 支持配置文件变更热加载
   - 适用于单租户场景

环境变量:
- configMode: 配置模式（file/memory），默认为memory
- businessUuid: 业务UUID（内存模式必需）
- bizSysApiIds: API ID列表
- ENABLE_CONFIG_WATCH: 是否启用配置热加载（仅文件模式）

作者: lzwcai
版本: 1.1.0
"""

import anyio
import mcp.types as types
from mcp.server.lowlevel import Server
import json
import sys
import os
import threading
import time
import re
import uuid

# 导入核心模块
from .core.api_base import ApiBase
import mcp.types as types
from .core.api_auth_service import AuthService
from .core.plugin_base import ToolPlugin

# 导入业务工具模块
from .business.business_util import (
    fill_default_values_by_schema,  # 参数默认值填充
    check_required_arguments,       # 必填参数检查
)
from .business.get_business_api import get_business_api_config  # 业务API配置获取

# 导入工具模块
from .util.logger_config import get_logger, setup_logging

# 获取日志器实例
logger = get_logger(__name__)

# ==================== 多租户配置存储 ====================
# 用于存储多个租户的配置（内存模式）
# key格式: business{businessUuid}, value: 配置字典
business_configs = {}


def load_api_configs():
    """
    加载API配置的核心函数

    支持两种配置模式：
    
    模式一 - 内存模式（configMode=memory，默认）：
        1. 根据环境变量businessUuid创建变量名：business{businessUuid}
        2. 从业务平台获取配置后存储在内存中（business_configs字典）
        3. 如果内存中已有配置则直接使用，否则从业务平台获取
        4. 不写入本地文件，支持多租户场景
    
    模式二 - 文件模式（configMode=file）：
        1. 从业务平台动态获取最新配置（通过get_business_api_config）
        2. 如果网络获取失败，则从本地api_config.json文件加载备份配置
        3. 成功获取后保存到本地文件作为备份

    环境变量:
        - configMode: 配置模式，"file"（文件模式）或 "memory"（内存模式），默认为memory
        - businessUuid: 业务UUID，仅在内存模式下使用，用于区分不同租户
        - bizSysApiIds: 指定要加载的API ID列表

    返回:
        dict: 包含完整API配置的字典，格式如下：
            {
                "packageName": "服务包名",
                "version": "版本号",
                "description": "服务描述",
                "apiConfig": [API配置列表]
            }

    异常处理:
        - 网络获取失败时自动降级（文件模式降级到本地文件，内存模式报错）
        - 详细记录所有错误信息用于调试
    """
    global business_configs
    
    # 获取配置模式（默认为内存模式）
    config_mode = os.getenv('configMode', 'memory').lower()
    logger.info(f"配置模式: {config_mode}")
    
    # 获取当前模块所在目录，用于定位配置文件
    current_dir = os.path.dirname(os.path.abspath(__file__))
    config_path = os.path.join(current_dir, "api_config.json")

    # ==================== 模式一：内存模式（多租户支持，默认） ====================
    if config_mode == 'memory':
        logger.info("使用内存模式加载配置（多租户支持）")
        
        # 获取业务UUID，如果不存在则自动生成一个
        business_uuid = os.getenv('businessUuid')
        if not business_uuid:
            # 生成随机UUID（使用uuid4，完全随机）
            business_uuid = str(uuid.uuid4())
            logger.warning(f"环境变量businessUuid未设置，已自动生成随机UUID: {business_uuid}")
            # 可选：将生成的UUID设置回环境变量，供后续使用
            os.environ['businessUuid'] = business_uuid
        else:
            logger.info(f"使用环境变量提供的businessUuid: {business_uuid}")
        
        # 构建配置变量名
        config_key = f"business{business_uuid}"
        logger.info(f"租户配置变量名: {config_key}")
        
        # 构建租户专属的配置文件路径
        memory_config_path = os.path.join(current_dir, f"api_config_{business_uuid}.json")
        
        # 本地文件不存在或加载失败，从业务平台获取
        logger.info(f"准备从业务平台获取租户 {business_uuid} 的最新配置(强制刷新)...")
        
        try:
            # 从环境变量获取API ID列表
            api_ids = []
            biz_sys_api_ids = os.getenv('bizSysApiIds')
            logger.debug(f"已获取环境变量bizSysApiIds: {biz_sys_api_ids}")
            
            if biz_sys_api_ids:
                try:
                    ids_str = biz_sys_api_ids.strip('[]')
                    api_ids = []
                    for id_part in ids_str.split(','):
                        id_clean = id_part.strip().strip('"\'')
                        if id_clean:
                            try:
                                api_id = int(id_clean)
                                api_ids.append(api_id)
                            except ValueError:
                                logger.warning(f"无法将 '{id_clean}' 转换为整数，跳过此项")
                                continue
                    logger.info(f"从环境变量bizSysApiIds获取到API IDs: {api_ids}")
                except (ValueError, AttributeError) as e:
                    logger.warning(f"解析环境变量bizSysApiIds失败，使用默认值: {str(e)}")
            else:
                logger.info("未找到环境变量bizSysApiIds，使用默认API IDs")
            
            # 从业务平台获取配置
            logger.info(f"调用get_business_api_config获取配置，API IDs: {api_ids}")
            config = get_business_api_config(api_ids)
            logger.info(f"成功获取业务API配置，包含 {len(config.get('apiConfig', []))} 个API配置")
            
            # 存储到内存中
            business_configs[config_key] = config
            logger.info(f"配置已存储到内存变量: {config_key}")
            logger.info(f"当前内存中共有 {len(business_configs)} 个租户配置")
            
            # 保存到本地文件作为备份
            try:
                logger.info(f"保存配置到本地文件: {memory_config_path}")
                with open(memory_config_path, "w", encoding="utf-8") as f:
                    json.dump(config, f, ensure_ascii=False, indent=2)
                logger.info("配置文件保存成功")
            except Exception as save_error:
                logger.warning(f"保存配置到本地文件失败（不影响运行）: {str(save_error)}")
            
            return config
            
        except Exception as e:
            logger.error(f"获取业务API配置失败: {str(e)}")
            
            # 网络获取失败，尝试降级使用本地缓存
            if os.path.exists(memory_config_path):
                try:
                    logger.info(f"网络获取失败，尝试使用本地缓存文件: {memory_config_path}")
                    with open(memory_config_path, "r", encoding="utf-8") as f:
                        config = json.load(f)
                    logger.info(f"成功加载本地缓存配置，包含 {len(config.get('apiConfig', []))} 个API配置")
                    
                    # 存储到内存中
                    business_configs[config_key] = config
                    return config
                except Exception as cache_error:
                    logger.error(f"加载本地缓存也失败了: {str(cache_error)}")
            
            error_msg = f"无法获取租户 {business_uuid} 的配置(网络和缓存均不可用): {str(e)}"
            raise Exception(error_msg)
    
    # ==================== 模式二：文件模式（单租户） ====================
    elif config_mode == 'file':
        logger.info("使用文件模式加载配置（单租户）")

        try:
            # 从环境变量获取API ID列表
            # 支持格式: "[1932682081958830081,1932682082285985793]" 或 "1932682081958830081,1932682082285985793"
            api_ids = []  # 默认空列表

            # 尝试从环境变量获取bizSysApiIds
            biz_sys_api_ids = os.getenv('bizSysApiIds')
            logger.debug(f"已获取环境变量bizSysApiIds: {biz_sys_api_ids}")

            if biz_sys_api_ids:
                try:
                    # 解析环境变量中的字符串，支持多种格式
                    # 格式1: [1932682081958830081,1932682082285985793]
                    # 格式2: 1932682081958830081,1932682082285985793
                    # 格式3: ["1932682081958830081","1932682082285985793"]
                    # 格式4: "1932682081958830081","1932682082285985793"
                    ids_str = biz_sys_api_ids.strip('[]')  # 移除方括号

                    # 分割并处理每个ID，自动转换字符串数字为整数
                    api_ids = []
                    for id_part in ids_str.split(','):
                        id_clean = id_part.strip().strip('"\'')  # 移除空格和引号
                        if id_clean:  # 确保不是空字符串
                            try:
                                # 尝试转换为整数，支持字符串数字自动转换
                                api_id = int(id_clean)
                                api_ids.append(api_id)
                            except ValueError:
                                logger.warning(f"无法将 '{id_clean}' 转换为整数，跳过此项")
                                continue

                    logger.info(f"从环境变量bizSysApiIds获取到API IDs: {api_ids}")
                except (ValueError, AttributeError) as e:
                    logger.warning(f"解析环境变量bizSysApiIds失败，使用默认值: {str(e)}")
                    logger.warning(f"环境变量值: {biz_sys_api_ids}")
            else:
                logger.info("未找到环境变量bizSysApiIds，使用默认API IDs")

            logger.info(f"调用get_business_api_config获取配置，API IDs: {api_ids}")

            # 从业务平台获取最新配置
            config = get_business_api_config(api_ids)
            logger.info(f"成功获取业务API配置，包含 {len(config.get('apiConfig', []))} 个API配置")

            # 将获取的配置保存到本地文件作为备份
            logger.info(f"保存配置到文件: {config_path}")
            with open(config_path, "w", encoding="utf-8") as f:
                json.dump(config, f, ensure_ascii=False, indent=2)
            logger.info("配置文件保存成功")

            return config

        except Exception as e:
            logger.error(f"获取业务API配置失败: {str(e)}")
            logger.info("尝试从本地配置文件加载...")

            # 降级处理：从本地文件加载配置
            try:
                logger.debug(f"加载本地API配置文件: {config_path}")
                with open(config_path, "r", encoding="utf-8") as f:
                    config = json.load(f)
                logger.info(f"成功加载本地API配置文件，包含 {len(config.get('apiConfig', []))} 个API配置")
                return config
            except FileNotFoundError:
                logger.error(f"本地API配置文件也未找到: {config_path}")
                raise Exception(f"无法获取业务API配置且本地配置文件不存在: {str(e)}")
            except json.JSONDecodeError as json_e:
                logger.error(f"本地API配置文件JSON格式错误: {str(json_e)}")
                raise Exception(f"无法获取业务API配置且本地配置文件格式错误: {str(e)}")
            except Exception as file_e:
                logger.error(f"加载本地API配置文件失败: {str(file_e)}")
                raise Exception(f"无法获取业务API配置且加载本地配置文件失败: {str(e)}")
    
    # ==================== 无效配置模式 ====================
    else:
        error_msg = f"无效的配置模式: {config_mode}，请使用 'file' 或 'memory'"
        logger.error(error_msg)
        raise Exception(error_msg)


# ==================== MCP服务器初始化 ====================

logger.info("开始初始化 MCP 服务器")

# 加载API配置（从业务平台或本地文件）
api_configs = load_api_configs()

# 设置MCP服务器的默认配置值
default_name = "lzwcai-mcp-dyntoolapi"           # 默认服务器名称
default_version = "1.0.0"                        # 默认版本号
default_instructions = "动态业务API工具服务器"    # 默认服务器描述

# 从加载的配置中获取服务器信息，如果不存在则使用默认值
name = api_configs.get("packageName", default_name)
version = api_configs.get("version", default_version)
instructions = api_configs.get("description", default_instructions)

logger.info(f"服务器配置 - 名称: {name}, 版本: {version}")
logger.debug(f"服务器说明: {instructions}")

# 创建MCP服务器实例
# 这个Server实例将处理所有的MCP协议通信
app = Server(
    name=name,                    # 服务器名称，用于客户端识别
    version=version,              # 服务器版本，用于兼容性检查
    instructions=instructions,    # 服务器描述，告诉客户端这个服务器的功能
)

# 初始化API基础服务
# ApiBase负责管理所有的API配置和调用逻辑
logger.debug("初始化 API 基础服务")
api_base = ApiBase(api_configs.get("apiConfig"))
logger.info(f"API 基础服务初始化完成，共 {api_base.config_count} 个API配置")


class ApiToolPlugin(ToolPlugin):
    """
    API工具插件实现类

    这个类负责将业务API配置转换为MCP工具，并处理工具调用请求。
    它继承自ToolPlugin基类，实现了插件的标准接口。

    主要功能:
    1. 将API配置转换为MCP工具定义
    2. 处理工具列表请求（list_tools）
    3. 处理工具调用请求（call_tool）
    4. 支持插件的注册、注销和刷新

    属性:
        api_base: ApiBase实例，管理所有API配置
        tools: 工具列表缓存（当前未使用）
    """

    def __init__(self, api_base):
        """
        初始化API工具插件

        参数:
            api_base: ApiBase实例，包含所有API配置信息
        """
        self.api_base = api_base
        self.tools = []  # 工具列表缓存（预留）
        logger.debug(f"初始化 API 工具插件，API配置数量: {api_base.config_count}")

    def register(self, server):
        """
        向MCP服务器注册插件

        这个方法会向服务器注册两个处理器：
        1. list_tools: 返回可用工具列表
        2. call_tool: 处理工具调用请求

        参数:
            server: MCP服务器实例
        """
        @server.list_tools()
        async def list_tools() -> list[types.Tool]:
            """
            处理工具列表请求

            当MCP客户端请求可用工具列表时，这个函数会被调用。
            它会遍历所有API配置，为每个API创建一个MCP工具定义。

            返回:
                list[types.Tool]: MCP工具定义列表
            """
            logger.debug("处理工具列表请求")
            tools = []
            tools_configs = self.api_base.api_configs_map

            # 遍历所有API配置，创建工具定义
            for tool_config in tools_configs:
                tool_name = tool_config["interfaceName"]  # 工具名称（拼音格式）
                logger.debug(f"注册工具: {tool_name}")

                # 创建MCP工具定义
                tools.append(
                    types.Tool(
                        name=tool_name,
                        description=tool_config["schema_description"],
                        inputSchema=tool_config["schema"],
                    )
                )

            logger.info(f"返回工具列表，共 {len(tools)} 个工具")
            return tools

        @server.call_tool()
        async def fetch_tool(
            name: str, arguments: dict
        ) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:
            """
            处理工具调用请求

            当MCP客户端调用某个工具时，这个函数会被调用。
            它负责：
            1. 查找对应的API配置
            2. 验证和处理输入参数
            3. 调用实际的API接口
            4. 返回格式化的结果

            参数:
                name: 工具名称（对应API的interfaceName）
                arguments: 工具调用参数（JSON对象）

            返回:
                list[types.TextContent]: 包含API调用结果的文本内容列表
            """
            logger.info(f"调用工具: {name}")
            logger.debug(f"工具参数: {arguments}")

            # 查找对应的工具配置
            tool_config = None
            for config in self.api_base.api_configs_map:
                if config["interfaceName"] == name:
                    tool_config = config
                    break

            # 检查工具是否存在
            if tool_config is None:
                logger.error(f"未找到工具: {name}")
                return [types.TextContent(type="text", text=f"未找到工具: {name}")]

            logger.debug(f"找到工具配置: {tool_config.get('apiUrl', 'N/A')}")

            # ==================== 参数处理和验证 ====================
            logger.debug("开始参数处理和验证")

            # 保存原始参数用于调试
            original_args = arguments.copy()

            # 使用schema中的默认值补全缺失的参数
            arguments = fill_default_values_by_schema(
                tool_config.get("schema", {}), arguments
            )
            logger.debug(f"参数默认值补全完成，原始参数: {original_args}, 补全后: {arguments}")

            # 检查必填参数是否都已提供
            missing = check_required_arguments(tool_config.get("schema", {}), arguments)
            if missing:
                missing_str = ", ".join(missing)
                logger.warning(f"缺少必填参数: {missing_str}")
                return [
                    types.TextContent(
                        type="text",
                        text=f"请补充以下必填参数：{missing_str}。填写后再试一次哦~ 如果有疑问请联系管理员。",
                    )
                ]

            # ==================== API接口调用 ====================
            logger.info(f"开始调用API接口: {tool_config.get('apiUrl', 'N/A')}")
            try:
                # 通过ApiBase调用实际的API接口
                result = await self.api_base.call_interface(tool_config, arguments)
                logger.info("API调用成功")
                logger.debug(f"API返回结果: {result}")

                # 将结果转换为JSON格式返回给客户端
                result_json = json.dumps(result, ensure_ascii=False, indent=2)
                return [types.TextContent(type="text", text=result_json)]

            except Exception as e:
                # 处理API调用异常
                logger.error(f"API调用失败: {str(e)}")
                logger.debug("API调用异常详情:", exc_info=True)
                error_msg = f"API调用失败: {str(e)}"
                return [types.TextContent(type="text", text=error_msg)]

    def unregister(self, server):
        """
        从MCP服务器注销插件

        目前MCP Server不支持动态注销功能，这个方法预留给未来使用。

        参数:
            server: MCP服务器实例（当前未使用）
        """
        # 目前 Server 不支持动态注销，预留接口
        logger.debug("插件注销请求（当前不支持动态注销）")
        pass

    def refresh(self, config):
        """
        刷新插件配置

        当API配置发生变化时（如热加载），这个方法会被调用来更新插件的配置。

        参数:
            config: 新的配置字典，包含apiConfig字段
        """
        logger.info("刷新API工具插件配置")
        # 重新创建ApiBase实例以使用新配置
        self.api_base = ApiBase(config.get("apiConfig"))
        logger.info(f"插件配置刷新完成，共 {self.api_base.config_count} 个API配置")


# ==================== 插件注册 ====================

# 创建并注册API工具插件
logger.info("注册API工具插件")
api_tool_plugin = ApiToolPlugin(api_base)  # 创建插件实例
api_tool_plugin.register(app)              # 向MCP服务器注册插件
logger.info("API工具插件注册完成")



# ==================== MCP服务器启动函数 ====================

def main(port: int, transport: str) -> int:
    """
    MCP服务器主启动函数

    根据指定的传输方式启动MCP服务器。支持两种传输方式：
    1. stdio: 标准输入输出传输（默认，用于命令行工具集成）
    2. sse: Server-Sent Events传输（用于Web集成）

    参数:
        port: 服务器端口号（仅在SSE模式下使用）
        transport: 传输方式，"stdio" 或 "sse"

    返回:
        int: 退出状态码，0表示成功
    """

    if transport == "sse":
        # ==================== SSE传输模式 ====================
        logger.info(f"启动SSE传输模式，端口: {port}")

        # 导入SSE相关模块
        from mcp.server.sse import SseServerTransport
        from starlette.applications import Starlette
        from starlette.responses import Response
        from starlette.routing import Mount, Route

        # 创建SSE传输实例
        sse = SseServerTransport("/messages/")

        async def handle_sse(request):
            """
            处理SSE连接请求

            这个函数处理来自Web客户端的SSE连接请求，
            建立双向通信流并运行MCP服务器。
            """
            async with sse.connect_sse(
                request.scope, request.receive, request._send
            ) as streams:
                # 运行MCP服务器，使用SSE流进行通信
                await app.run(
                    streams[0], streams[1], app.create_initialization_options()
                )
            return Response()

        # 创建Starlette Web应用
        starlette_app = Starlette(
            debug=True,  # 开启调试模式
            routes=[
                # SSE连接端点
                Route("/sse", endpoint=handle_sse, methods=["GET"]),
                # 消息处理端点
                Mount("/messages/", app=sse.handle_post_message),
            ],
        )

        # 使用uvicorn启动Web服务器
        import uvicorn
        logger.info(f"启动Web服务器，监听 0.0.0.0:{port}")
        uvicorn.run(starlette_app, host="0.0.0.0", port=port)

    else:
        # ==================== STDIO传输模式 ====================
        logger.info("启动STDIO传输模式")

        # 导入stdio传输模块
        from mcp.server.stdio import stdio_server

        async def arun():
            """
            异步运行MCP服务器

            使用标准输入输出流与客户端通信，
            这是MCP协议的标准传输方式。
            """
            async with stdio_server() as streams:
                # 运行MCP服务器，使用stdio流进行通信
                await app.run(
                    streams[0], streams[1], app.create_initialization_options()
                )

        # 启动异步事件循环
        anyio.run(arun)

    return 0


# ==================== 工具函数 ====================

def save_to_json_file(data, file_path="output/test_data.json"):
    """
    将输入数据保存为JSON文件

    这是一个通用的数据保存工具函数，主要用于调试和数据持久化。

    参数:
        data: 要保存的数据(字典、列表或其他可JSON序列化的对象)
        file_path: 要保存的文件路径，默认保存到output目录

    返回:
        bool: 操作成功返回True，失败返回False

    特性:
        - 自动创建目录（如果不存在）
        - 使用UTF-8编码确保中文正确显示
        - 格式化输出（缩进2个空格）
    """
    try:
        # 确保目录存在
        os.makedirs(os.path.dirname(file_path), exist_ok=True)

        # 保存数据到JSON文件
        with open(file_path, "w", encoding="utf-8") as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
        logger.info(f"数据已成功保存到 {file_path}")
        return True
    except Exception as e:
        logger.error(f"保存JSON文件时出错: {str(e)}")
        return False


def refresh_api_configs():
    """
    刷新API配置和工具注册（热加载功能）

    这个函数实现了配置的热加载功能，支持两种模式：
    - 文件模式：当检测到配置文件变化时会被调用
    - 内存模式：强制重新从业务平台获取配置并更新内存和本地文件

    全局变量更新:
        - api_configs: 重新加载的API配置
        - name, version, instructions: 服务器基本信息
        - api_base: 重新创建的API基础服务实例
        - api_tool_plugin: 刷新插件配置
        - business_configs: 内存模式下更新租户配置

    注意:
        这个函数修改全局变量，在多线程环境中需要注意线程安全。
    """
    global api_configs, name, version, instructions, api_base, api_tool_plugin, business_configs

    logger.info("开始刷新API配置...")
    
    # 获取配置模式
    config_mode = os.getenv('configMode', 'memory').lower()
    
    # 内存模式下需要清除当前租户的缓存配置和本地文件，强制重新获取
    if config_mode == 'memory':
        business_uuid = os.getenv('businessUuid')
        if business_uuid:
            config_key = f"business{business_uuid}"
            if config_key in business_configs:
                logger.info(f"清除租户 {business_uuid} 的缓存配置")
                del business_configs[config_key]
            
            # 删除本地配置文件，强制从业务平台重新获取
            current_dir = os.path.dirname(os.path.abspath(__file__))
            memory_config_path = os.path.join(current_dir, f"api_config_{business_uuid}.json")
            if os.path.exists(memory_config_path):
                try:
                    os.remove(memory_config_path)
                    logger.info(f"已删除本地配置文件: {memory_config_path}")
                except Exception as e:
                    logger.warning(f"删除本地配置文件失败: {str(e)}")

    # 重新加载API配置
    api_configs = load_api_configs()

    # 更新服务器基本信息
    name = api_configs.get("packageName", default_name)
    version = api_configs.get("version", default_version)
    instructions = api_configs.get("description", default_instructions)

    # 重新创建API基础服务
    api_base = ApiBase(api_configs.get("apiConfig"))

    # 刷新插件配置
    api_tool_plugin.refresh(api_configs)

    logger.info(f"API配置已热加载并刷新（模式：{config_mode}）")


# ==================== 配置热加载功能 ====================

def watch_config_file(interval=2):
    """
    配置文件变更监控函数（仅文件模式）

    这个函数在后台线程中运行，定期检查配置文件的修改时间。
    当检测到文件变更时，自动触发配置热加载。

    注意:
        - 仅在文件模式（configMode=file）下有效
        - 内存模式下此函数会直接返回，不进行监控

    参数:
        interval: 检查间隔时间（秒），默认2秒

    特性:
        - 轮询方式检测文件变更
        - 异常安全，不会因为单次错误而停止监控
        - 在守护线程中运行，不会阻止程序退出

    注意:
        这个函数会无限循环运行，直到程序退出。
    """
    # 检查配置模式，内存模式下不需要监控文件
    config_mode = os.getenv('configMode', 'memory').lower()
    if config_mode != 'file':
        logger.info(f"当前为 {config_mode} 模式，无需监控配置文件")
        return
    
    current_dir = os.path.dirname(os.path.abspath(__file__))
    config_path = os.path.join(current_dir, "api_config.json")

    try:
        # 获取初始修改时间
        last_mtime = os.path.getmtime(config_path)
        logger.debug(f"开始监控配置文件: {config_path}")
    except OSError:
        logger.warning(f"配置文件不存在，跳过热加载监控: {config_path}")
        return

    # 无限循环监控文件变更
    while True:
        try:
            # 获取当前修改时间
            mtime = os.path.getmtime(config_path)

            # 检查是否有变更
            if mtime != last_mtime:
                logger.info("检测到api_config.json变更，自动热加载...")
                refresh_api_configs()
                last_mtime = mtime

        except Exception as e:
            logger.error(f"配置热加载异常: {e}")

        # 等待下次检查
        time.sleep(interval)


# ==================== 主启动函数 ====================

def run_main():
    """
    程序主启动函数

    这是整个MCP服务器的启动入口，负责：
    1. 配置日志系统（MCP模式下禁用控制台输出）
    2. 可选启动配置文件监控线程（通过环境变量ENABLE_CONFIG_WATCH控制）
    3. 启动MCP服务器

    配置说明:
        - 使用stdio传输方式（标准MCP协议）
        - 端口8000（仅在SSE模式下使用）
        - 配置热加载功能默认关闭，可通过环境变量ENABLE_CONFIG_WATCH=true启用
    """

    # 在MCP模式下，禁用控制台日志输出，避免干扰stdio通信
    # 只输出到文件，确保MCP协议通信不被日志干扰
    setup_logging(console_output=False, file_output=True)

    # 检查是否启用配置文件监控（默认关闭）
    # 通过环境变量ENABLE_CONFIG_WATCH=true来启用
    enable_watch = os.getenv('ENABLE_CONFIG_WATCH', 'false').lower() in ['true', '1', 'yes']
    
    if enable_watch:
        # 启动配置文件监听线程（守护线程）
        # 守护线程会在主程序退出时自动结束
        config_watcher = threading.Thread(target=watch_config_file, daemon=True)
        config_watcher.start()
        logger.info("配置文件监控线程已启动")
    else:
        logger.info("配置文件监控功能已禁用（如需启用，请设置环境变量ENABLE_CONFIG_WATCH=true）")

    # 启动MCP服务器
    # 使用stdio传输方式，这是MCP协议的标准传输方式
    # 如果需要Web集成，可以改为 transport="sse"
    main(port=8000, transport="stdio")


# ==================== 程序入口 ====================

if __name__ == "__main__":
    """
    直接运行此模块时的入口点

    通常情况下，这个模块会被main.py调用，
    但也支持直接运行进行测试。
    """
    run_main()

    # 以下是测试代码，正常运行时被注释掉
    # from core.api_auth_service import test_auth_service
    # asyncio.run(test_auth_service())
