"""
MCPStore Service Management Module
服务管理相关操作的实现
"""

import asyncio
import datetime
import logging
import time
from typing import Dict, List, Optional, Any, Union, Tuple

from mcpstore.core.models.service import ServiceConnectionState
from .types import ContextType

logger = logging.getLogger(__name__)


class UpdateServiceAuthHelper:
    """更新服务认证助手 - 明确的服务名，避免状态混乱
    
    Note: 这是一个内部助手类，为了符合 async-only 约束，
    所有方法都改为 async，外部调用者需要 await。
    """

    def __init__(self, context: 'MCPStoreContext', service_name: str, config: Dict[str, Any] = None):
        self._context = context
        self._service_name = service_name  # [CONFIG] Clear service name to avoid confusion
        self._config = config.copy() if config else {}

    async def bearer_auth(self, auth: str) -> 'MCPStoreContext':
        """Update Bearer Token authentication for specified service (backward compatible)"""
        # Standardize to Authorization header
        if "headers" not in self._config:
            self._config["headers"] = {}
        self._config["headers"]["Authorization"] = f"Bearer {auth}"
        return await self._execute_update()

    async def token(self, token: str) -> 'MCPStoreContext':
        """Recommended: Set Bearer Token (equivalent to bearer_auth)"""
        if "headers" not in self._config:
            self._config["headers"] = {}
        self._config["headers"]["Authorization"] = f"Bearer {token}"
        return await self._execute_update()

    async def api_key(self, api_key: str) -> 'MCPStoreContext':
        """Recommended: Set API Key (standardized to X-API-Key)"""
        if "headers" not in self._config:
            self._config["headers"] = {}
        self._config["headers"]["X-API-Key"] = api_key
        return await self._execute_update()

    async def custom_headers(self, headers: Dict[str, str]) -> 'MCPStoreContext':
        """Update custom headers for specified service (explicit override)"""
        if "headers" not in self._config:
            self._config["headers"] = {}
        self._config["headers"].update(headers)
        return await self._execute_update()

    async def _execute_update(self) -> 'MCPStoreContext':
        """执行更新服务（内部 async-only）"""
        await self._context.update_service_async(self._service_name, self._config)
        return self._context


class ServiceManagementMixin:
    """服务管理混入类"""

    # [已删除] check_services 同步方法
    # 根据 "pykv 唯一真相数据源" 原则，请使用 check_services_async 异步方法

    async def check_services_async(self) -> dict:
        """
        异步健康检查，store/agent上下文自动判断
        - store上下文：聚合 global_agent_store 下所有 client_id 的服务健康状态
        - agent上下文：聚合 agent_id 下所有 client_id 的服务健康状态
        """
        if self._context_type.name == 'STORE':
            return await self._store.get_health_status()
        elif self._context_type.name == 'AGENT':
            return await self._store.get_health_status(self._agent_id, agent_mode=True)
        else:
            logger.error(f"[check_services] Unknown context type: {self._context_type}")
            return {}

    def get_service_info(self, name: str) -> Any:
        """
        获取服务详情（同步版本），支持 store/agent 上下文
        - store上下文：在 global_agent_store 下的所有 client 中查找服务
        - agent上下文：在指定 agent_id 下的所有 client 中查找服务

        [新架构] 避免_sync_helper.run_async，使用更安全的同步实现
        """
        try:
            if not name:
                return {}

            if self._context_type == ContextType.STORE:
                logger.debug(f"STORE mode - searching service in global_agent_store: {name}")
                agent_id = self._store.client_manager.global_agent_store_id
            else:
                logger.debug(f"AGENT mode - searching service in agent({self._agent_id}): {name}")
                agent_id = self._agent_id

            # 直接从缓存获取服务信息
            complete_info = self._store.registry.get_complete_service_info(agent_id, name)
            if not complete_info:
                logger.debug(f"Service {name} not found in agent {agent_id}")
                return {}

            # 构建返回信息
            return {
                "name": name,
                "client_id": complete_info.get("client_id"),
                "config": complete_info.get("config", {}),
                "state": complete_info.get("state", "disconnected"),
                "tool_count": complete_info.get("tool_count", 0),
                "agent_id": agent_id
            }

        except Exception as e:
            logger.error(f"[NEW_ARCH] get_service_info failed: {e}")
            return {
                "name": name,
                "error": str(e),
                "agent_id": getattr(self, '_agent_id', 'unknown')
            }

    # 别名：符合命名规范
    def service_info(self, name: str) -> Any:
        return self.get_service_info(name)

    async def get_service_info_async(self, name: str) -> Any:
        """
        获取服务详情（异步版本），支持 store/agent 上下文
        - store上下文：在 global_agent_store 下的所有 client 中查找服务
        - agent上下文：在指定 agent_id 下的所有 client 中查找服务（支持本地名称）
        """
        if not name:
            return {}

        if self._context_type == ContextType.STORE:
            logger.debug(f"STORE mode - searching service in global_agent_store: {name}")
            return await self._store.get_service_info(name)
        elif self._context_type == ContextType.AGENT:
            # Agent模式：将名称原样交给 Store 层处理，Store 负责本地名/全局名的鲁棒解析
            logger.debug(f"AGENT mode - searching service in agent({self._agent_id}): {name}")
            return await self._store.get_service_info(name, self._agent_id)
        else:
            logger.error(f"[get_service_info] Unknown context type: {self._context_type}")
            return {}

    async def service_info_async(self, name: str) -> Any:
        return await self.get_service_info_async(name)

    def update_service(self,
                      name: str,
                      config: Union[Dict[str, Any], None] = None,
                      # 🆕 与用户用法对齐
                      auth: Optional[str] = None,            # 兼容历史：等价于 token
                      token: Optional[str] = None,           # 推荐：Bearer Token
                      api_key: Optional[str] = None,         # 推荐：API Key
                      headers: Optional[Dict[str, str]] = None) -> Union['MCPStoreContext', 'UpdateServiceAuthHelper']:
        """
        更新服务配置，支持安全的链式认证与凭证轮换（合并更新，不会破坏原有关键字段）

        Args:
            name: 服务名称（明确指定，不会混乱）
            config: 新的服务配置（可选，按“补丁”合并语义处理）
            auth/token: Bearer token（两者等价；优先使用 token）
            api_key: API Key（统一标准化为 X-API-Key 头）
            headers: 自定义请求头（显式传入的键优先级最高）

        Returns:
            如果有配置或认证参数：立即执行更新，返回 MCPStoreContext
            如果什么都没有：返回 UpdateServiceAuthHelper 支持链式配置
        """

        if config is not None:
            # 有配置参数：立即执行更新（与认证参数合并，并采用“补丁合并”语义）
            if any([auth, token, api_key, headers]):
                final_config = self._apply_auth_to_update_config(config, auth, token, api_key, headers)
            else:
                final_config = config

            try:
                self._run_async_via_bridge(
                    self.update_service_async(name, final_config),
                    op_name="service_management.update_service"
                )
            except Exception as e:
                logger.error(f"[NEW_ARCH] update_service failed: {e}")
            return self
        else:
            # 没有配置参数：
            if any([auth, token, api_key, headers]):
                # 纯认证：立即执行（也走补丁合并语义）
                final_config = self._apply_auth_to_update_config({}, auth, token, api_key, headers)
                try:
                    self._run_async_via_bridge(
                        self.update_service_async(name, final_config),
                        op_name="service_management.update_service_auth"
                    )
                except Exception as e:
                    logger.error(f"[NEW_ARCH] update_service (auth) failed: {e}")
                return self
            else:
                # 什么都没有：返回助手用于链式调用
                return UpdateServiceAuthHelper(self, name, {})

    async def update_service_async(self, name: str, config: Dict[str, Any]) -> bool:
        """
        更新服务配置（异步版本）- 合并更新（不会破坏未提供的关键字段）

        Args:
            name: 服务名称
            config: 新的服务配置（作为补丁）

        Returns:
            bool: 更新是否成功
        """
        try:
            #  内部：简单的深度合并（仅对字典执行一层合并；headers 为字典则键级覆盖）
            def _deep_merge(base: Dict[str, Any], patch: Dict[str, Any]) -> Dict[str, Any]:
                result = dict(base or {})
                for k, v in (patch or {}).items():
                    if isinstance(v, dict) and isinstance(result.get(k), dict):
                        merged = dict(result.get(k) or {})
                        merged.update(v)
                        result[k] = merged
                    else:
                        result[k] = v
                return result

            if self._context_type == ContextType.STORE:
                # Store级别：使用原子更新，避免读改写竞态
                from mcpstore.core.configuration.config_write_service import ConfigWriteService
                from mcpstore.utils.perspective_resolver import PerspectiveResolver
                from mcpstore.core.exceptions import PerspectiveResolutionError

                try:
                    resolver = PerspectiveResolver()
                    name_res = resolver.normalize_service_name(
                        self._store.client_manager.global_agent_store_id,
                        name,
                        target="global",
                        strict=False,
                    )
                    config_key = name_res.global_name
                except Exception as e:
                    raise PerspectiveResolutionError(name, str(e)) from e

                cws = ConfigWriteService()
                def _mutator(cfg: Dict[str, Any]) -> Dict[str, Any]:
                    servers = dict(cfg.get("mcpServers", {}))
                    if config_key not in servers:
                        raise KeyError(f"Service {config_key} not found in store configuration")
                    existing = dict(servers.get(config_key) or {})
                    merged = _deep_merge(existing, config)
                    servers[config_key] = merged
                    cfg["mcpServers"] = servers
                    return cfg
                try:
                    success = cws.atomic_update(self._store.config.json_path, _mutator)
                except KeyError as e:
                    logger.error(str(e))
                    return False

                if success:
                    # 触发重新注册
                    if hasattr(self._store.orchestrator, 'sync_manager') and self._store.orchestrator.sync_manager:
                        await self._store.orchestrator.sync_manager.sync_global_agent_store_from_mcp_json()

                return success
            else:
                # Agent级别：与单一数据源模式对齐——直接更新 mcp.json 并触发同步
                from mcpstore.utils.perspective_resolver import PerspectiveResolver
                from mcpstore.core.exceptions import PerspectiveResolutionError

                try:
                    resolver = PerspectiveResolver()
                    name_res = resolver.normalize_service_name(
                        self._agent_id,
                        name,
                        target="global",
                        strict=False,
                    )
                    global_name = name_res.global_name
                except Exception as e:
                    raise PerspectiveResolutionError(name, str(e)) from e

                from mcpstore.core.configuration.config_write_service import ConfigWriteService
                cws = ConfigWriteService()
                def _mutator(cfg: Dict[str, Any]) -> Dict[str, Any]:
                    servers = dict(cfg.get("mcpServers", {}))
                    if global_name not in servers:
                        raise KeyError(f"Service {global_name} not found in store configuration (agent mode)")
                    existing = dict(servers.get(global_name) or {})
                    merged = _deep_merge(existing, config)
                    servers[global_name] = merged
                    cfg["mcpServers"] = servers
                    return cfg
                try:
                    success = cws.atomic_update(self._store.config.json_path, _mutator)
                except KeyError as e:
                    logger.error(str(e))
                    return False

                if success and hasattr(self._store.orchestrator, 'sync_manager') and self._store.orchestrator.sync_manager:
                    await self._store.orchestrator.sync_manager.sync_global_agent_store_from_mcp_json()

                # 更新缓存中的 metadata.service_config，确保一致性
                try:
                    # 从 pykv 异步获取元数据
                    global_agent = self._store.client_manager.global_agent_store_id
                    metadata = await self._store.registry._service_state_service.get_service_metadata_async(global_agent, global_name)
                    if metadata:
                        # 将变更合并到缓存元数据中
                        metadata.service_config = _deep_merge(metadata.service_config or {}, config)
                        await self._store.registry.set_service_metadata_async(global_agent, global_name, metadata)
                except Exception as e:
                    logger.error(f"Failed to update service metadata: {e}")
                    raise

                return success
        except Exception as e:
            logger.error(f"Failed to update service {name}: {e}")
            raise

    def patch_service(self, name: str, updates: Dict[str, Any]) -> bool:
        """
        增量更新服务配置（同步版本）- 推荐使用

        Args:
            name: 服务名称
            updates: 要更新的配置项

        Returns:
            bool: 更新是否成功
        """
        try:
            return self._run_async_via_bridge(
                self.patch_service_async(name, updates),
                op_name="service_management.patch_service"
            )
        except Exception as e:
            logger.error(f"[NEW_ARCH] patch_service failed: {e}")
            return False

    async def patch_service_async(self, name: str, updates: Dict[str, Any]) -> bool:
        """
        增量更新服务配置（异步版本）- 推荐使用

        Args:
            name: 服务名称
            updates: 要更新的配置项

        Returns:
            bool: 更新是否成功
        """
        try:
            if self._context_type == ContextType.STORE:
                # Store级别：使用原子增量更新
                from mcpstore.core.configuration.config_write_service import ConfigWriteService
                from mcpstore.utils.perspective_resolver import PerspectiveResolver
                from mcpstore.core.exceptions import PerspectiveResolutionError

                try:
                    resolver = PerspectiveResolver()
                    name_res = resolver.normalize_service_name(
                        self._store.client_manager.global_agent_store_id,
                        name,
                        target="global",
                        strict=False,
                    )
                    config_key = name_res.global_name
                except Exception as e:
                    raise PerspectiveResolutionError(name, str(e)) from e

                cws = ConfigWriteService()
                def _mutator(cfg: Dict[str, Any]) -> Dict[str, Any]:
                    servers = dict(cfg.get("mcpServers", {}))
                    if config_key not in servers:
                        raise KeyError(f"Service {config_key} not found in store configuration")
                    merged = dict(servers[config_key])
                    merged.update(updates)
                    servers[config_key] = merged
                    cfg["mcpServers"] = servers
                    return cfg
                try:
                    success = cws.atomic_update(self._store.config.json_path, _mutator)
                except KeyError as e:
                    logger.error(str(e))
                    return False

                if success:
                    # 触发重新注册
                    if hasattr(self._store.orchestrator, 'sync_manager') and self._store.orchestrator.sync_manager:
                        await self._store.orchestrator.sync_manager.sync_global_agent_store_from_mcp_json()

                return success
            else:
                # Agent级别：与单一数据源模式对齐——直接增量更新 mcp.json 并触发同步
                from mcpstore.utils.perspective_resolver import PerspectiveResolver
                from mcpstore.core.exceptions import PerspectiveResolutionError

                try:
                    resolver = PerspectiveResolver()
                    name_res = resolver.normalize_service_name(
                        self._agent_id,
                        name,
                        target="global",
                        strict=False,
                    )
                    global_name = name_res.global_name
                except Exception as e:
                    raise PerspectiveResolutionError(name, str(e)) from e

                from mcpstore.core.configuration.config_write_service import ConfigWriteService
                cws = ConfigWriteService()
                def _mutator(cfg: Dict[str, Any]) -> Dict[str, Any]:
                    servers = dict(cfg.get("mcpServers", {}))
                    if global_name not in servers:
                        raise KeyError(f"Service {global_name} not found in store configuration (agent mode)")
                    merged = dict(servers[global_name])
                    merged.update(updates)
                    servers[global_name] = merged
                    cfg["mcpServers"] = servers
                    return cfg
                try:
                    success = cws.atomic_update(self._store.config.json_path, _mutator)
                except KeyError as e:
                    logger.error(str(e))
                    return False

                if success and hasattr(self._store.orchestrator, 'sync_manager') and self._store.orchestrator.sync_manager:
                    await self._store.orchestrator.sync_manager.sync_global_agent_store_from_mcp_json()

                # 更新缓存中的 metadata.service_config，确保一致性
                try:
                    # 从 pykv 异步获取元数据
                    global_agent = self._store.client_manager.global_agent_store_id
                    metadata = await self._store.registry._service_state_service.get_service_metadata_async(global_agent, global_name)
                    if metadata:
                        metadata.service_config = dict(metadata.service_config or {})
                        metadata.service_config.update(updates)
                        await self._store.registry.set_service_metadata_async(global_agent, global_name, metadata)
                except Exception as e:
                    logger.error(f"Failed to update service metadata: {e}")
                    raise

                return success
        except Exception as e:
            logger.error(f"Failed to patch service {name}: {e}")
            raise

    def delete_service(self, name: str) -> bool:
        """
        删除服务（同步版本）

        Args:
            name: 服务名称

        Returns:
            bool: 删除是否成功
        """
        try:
            return self._run_async_via_bridge(
                self.delete_service_async(name),
                op_name="service_management.delete_service"
            )
        except Exception as e:
            logger.error(f"[NEW_ARCH] delete_service failed: {e}")
            return False

    async def delete_service_async(self, name: str) -> bool:
        """
        删除服务（异步版本，透明代理）

        Args:
            name: 服务名称（Agent 模式下使用本地名称）

        Returns:
            bool: 删除是否成功
        """
        try:
            if self._context_type == ContextType.STORE:
                # Store级别：删除服务并触发双向同步
                from mcpstore.utils.perspective_resolver import PerspectiveResolver
                from mcpstore.core.exceptions import PerspectiveResolutionError

                try:
                    resolver = PerspectiveResolver()
                    name_res = resolver.normalize_service_name(
                        self._store.client_manager.global_agent_store_id,
                        name,
                        target="global",
                        strict=False,
                    )
                    target_name = name_res.global_name
                except Exception as e:
                    raise PerspectiveResolutionError(name, str(e)) from e

                await self._delete_store_service_with_sync(target_name)
                return True
            else:
                # Agent级别：透明代理删除
                await self._delete_agent_service_with_sync(name)
                return True
        except Exception as e:
            logger.error(f"Failed to delete service {name}: {e}")
            raise

    def _normalize_agent_local_name(self, input_name: str) -> str:
        """
        将输入的服务标识归一化为当前 Agent 的本地服务名。

        支持三种输入：
        1) 纯本地名（默认）
        2) 全局名格式：<local>_byagent_<agent_id>
        3) 冒号分隔：<agent_id>:<local>

        若提供的 agent_id 与当前上下文不一致则抛出异常，避免误删。
        """
        if not input_name:
            raise ValueError("service name is required")

        # 统一委托给 PerspectiveResolver，避免重复实现视角转换
        try:
            from mcpstore.utils.perspective_resolver import PerspectiveResolver

            resolver = PerspectiveResolver()
            res = resolver.normalize_service_name(
                self._agent_id,
                input_name,
                target="local",
                strict=True,
            )
            logger.debug(
                f"[PERSPECTIVE] normalize input='{input_name}' -> local='{res.local_name}' method='{res.resolution_method}'"
            )
            return res.local_name
        except Exception as e:
            logger.error(f"[PERSPECTIVE] normalize_agent_local_name failed: {e}")
            raise

    async def delete_service_two_step(self, service_name: str) -> Dict[str, Any]:
        """
        两步删除服务：从配置文件删除 + 从Registry注销

        Args:
            service_name: 服务名称

        Returns:
            Dict: 包含两步操作结果的字典
        """
        result = {
            "step1_config_removal": False,
            "step2_registry_cleanup": False,
            "step1_error": None,
            "step2_error": None,
            "overall_success": False
        }

        # 第一步：从配置文件删除
        try:
            result["step1_config_removal"] = await self.delete_service_async(service_name)
            if not result["step1_config_removal"]:
                result["step1_error"] = "Failed to remove service from configuration"
        except Exception as e:
            result["step1_error"] = f"Configuration removal failed: {str(e)}"
            logger.error(f"Step 1 (config removal) failed: {e}")

        # 第二步：从Registry清理（即使第一步失败也尝试）
        try:
            if self._context_type == ContextType.STORE:
                # Store级别：清理global_agent_store的Registry
                cleanup_success = await self._store.orchestrator.registry.cleanup_service(service_name)
            else:
                # Agent级别：清理特定agent的Registry
                global_name = service_name
                if self._service_mapper:
                    global_name = self._service_mapper.to_global_name(service_name)
                cleanup_success = await self._store.orchestrator.registry.cleanup_service(global_name, self._agent_id)

            result["step2_registry_cleanup"] = cleanup_success
            if not cleanup_success:
                result["step2_error"] = "Failed to cleanup service from registry"
        except Exception as e:
            result["step2_error"] = f"Registry cleanup failed: {str(e)}"
            logger.warning(f"Step 2 (registry cleanup) failed: {e}")

        result["overall_success"] = result["step1_config_removal"] and result["step2_registry_cleanup"]
        return result

    def reset_config(self) -> bool:
        """
        重置配置（同步版本）
        
        清空所有 pykv 缓存数据和 mcp.json 文件。
        相当于批量执行 delete_service 操作。
        """
        return self._run_async_via_bridge(
            self.reset_config_async(),
            op_name="service_management.reset_config"
        )

    def switch_cache(self, cache_config: Any) -> bool:
        """运行时切换缓存后端（同步版本）。

        仅支持 Store 上下文；Agent 上下文会抛出 ValueError。
        """
        try:
            return self._run_async_via_bridge(
                self.switch_cache_async(cache_config),
                op_name="service_management.switch_cache"
            )
        except Exception as e:
            logger.error(f"[NEW_ARCH] switch_cache failed: {e}")
            return False

    async def switch_cache_async(self, cache_config: Any) -> bool:
        """运行时切换缓存后端（异步版本）。"""
        try:
            if self._context_type != ContextType.STORE:
                raise ValueError("Cache switching is only supported in STORE context")

            # 委托给 Store 层的封装方法，内部会进行配置解析和连接测试
            await self._store._switch_cache_backend(cache_config)
            return True
        except Exception as e:
            logger.error(f"Failed to switch cache backend: {e}")
            return False

    async def reset_config_async(self) -> bool:
        """
        重置配置（异步版本）
        
        清空所有 pykv 缓存数据和 mcp.json 文件。
        相当于批量执行 delete_service 操作。
        
        清理内容：
        - pykv 实体层：services, tools
        - pykv 关系层：agent_services, service_tools
        - pykv 状态层：service_status, service_metadata
        - mcp.json 文件
        - 健康检查任务（通过服务不存在检测自动停止）
        
        根据上下文类型执行不同的重置操作：
        - Store 上下文：清空所有 Agent 的配置
        - Agent 上下文：只清空该 Agent 的配置
        """
        if self._context_type == ContextType.STORE:
            return await self._reset_store_config()
        else:
            return await self._reset_agent_config()

    async def _reset_store_config(self) -> bool:
        """
        Store 级别重置配置
        
        清理流程：
        1. 获取所有 Agent ID
        2. 对每个 Agent 调用 registry.clear_async()
           - clear_async 内部调用 remove_service_async 逐个删除服务
           - remove_service_async 清理：实体层、关系层、状态层、工具实体
        3. 重置 mcp.json 为空配置
        """
        logger.info("[RESET_CONFIG] [STORE] Store level: starting to reset all configurations")
        
        # 1. 获取所有 Agent ID
        agent_ids = await self._store.registry.get_all_agent_ids_async()
        logger.debug(f"[RESET_CONFIG] [CLEAN] Found {len(agent_ids)} Agents need to be cleaned")
        
        # 2. 清空每个 Agent 的缓存数据
        for agent_id in agent_ids:
            logger.debug(f"[RESET_CONFIG] [CLEAN] Cleaning Agent: {agent_id}")
            await self._store.registry.clear_async(agent_id)
        
        # 3. 单源模式：不再重置 mcp.json，重置以 KV 为准
        logger.info("[RESET_CONFIG] [STORE] Single-source KV: skip mcp.json reset")
        
        logger.info("[RESET_CONFIG] [STORE] Store level: configuration reset completed")
        return True

    async def _reset_agent_config(self) -> bool:
        """Agent级别重置配置的内部实现"""
        try:
            logger.info(f"[RESET_CONFIG] [AGENT] Agent level: resetting all configurations for Agent {self._agent_id}")

            # 1. 清空Agent在缓存中的数据（使用异步版本）
            await self._store.registry.clear_async(self._agent_id)

            # 2. 单源模式：不再同步到分片文件
            logger.info("Single-source mode: skip shard mapping files sync")

            logger.info(f"[RESET_CONFIG] [AGENT] Agent level: Agent {self._agent_id} configuration reset completed")
            return True

        except Exception as e:
            logger.error(f"[RESET_CONFIG] [ERROR] Agent level configuration reset failed: {e}")
            return False

    def show_config(self) -> Dict[str, Any]:
        """
        显示配置信息（同步版本）

        - Store级别: 返回所有Agent的配置
        - Agent级别: 返回该Agent的配置

        Returns:
            Dict: 配置信息字典
        """
        try:
            return self._run_async_via_bridge(
                self.show_config_async(),
                op_name="service_management.show_config"
            )
        except Exception as e:
            logger.error(f"[NEW_ARCH] show_config failed: {e}")
            return {}

    async def show_config_async(self) -> Dict[str, Any]:
        """
        显示配置信息（异步版本）- 遵循 Functional Core, Imperative Shell 架构

        架构说明：
        - 使用 ShowConfigAsyncShell 作为异步外壳，负责 pykv IO 操作
        - 使用 ShowConfigLogicCore 作为纯逻辑核心，负责数据组装
        - 严格遵循 pykv 唯一真相数据源原则

        根据上下文类型执行不同的显示操作：
        - Store上下文：显示所有Agent的配置
        - Agent上下文：显示该Agent的配置

        Returns:
            Dict: 配置信息字典
        """
        try:
            # 获取 CacheLayerManager 实例
            cache_layer = self._get_cache_layer_manager()
            
            # 创建异步外壳实例
            from mcpstore.core.architecture.show_config_shell import ShowConfigAsyncShell
            shell = ShowConfigAsyncShell(cache_layer)
            
            if self._context_type == ContextType.STORE:
                return await shell.show_store_config_async()
            else:
                return await shell.show_agent_config_async(self._agent_id)
                
        except Exception as e:
            logger.error(f"Failed to show config: {e}")
            # 使用纯逻辑核心构建错误响应
            from mcpstore.core.architecture.show_config_core import ShowConfigLogicCore
            logic_core = ShowConfigLogicCore()
            return logic_core.build_error_response(
                f"Failed to show config: {str(e)}",
                agent_id=self._agent_id if self._context_type != ContextType.STORE else None
            )

    def _get_cache_layer_manager(self):
        """
        获取 CacheLayerManager 实例
        
        遵循 pykv 唯一真相数据源原则，确保使用正确的缓存层管理器。
        
        Returns:
            CacheLayerManager 实例
            
        Raises:
            RuntimeError: 如果无法获取 CacheLayerManager
        """
        # 从 registry 获取 _cache_layer_manager
        # 注意：不再使用 _cache_layer，因为它在 Redis 模式下是 RedisStore，没有所需的方法
        cache_layer = getattr(self._store.registry, '_cache_layer_manager', None)
        if cache_layer is not None:
            return cache_layer
        
        # 尝试从 store 获取
        cache_layer = getattr(self._store, '_cache_layer_manager', None)
        if cache_layer is not None:
            return cache_layer
        
        raise RuntimeError(
            "无法获取 CacheLayerManager 实例。"
            "请确保 MCPStore 已正确初始化，且 registry._cache_layer_manager 已设置。"
        )

    def delete_config(self, client_id_or_service_name: str) -> Dict[str, Any]:
        """
        删除服务配置（同步版本）

        Args:
            client_id_or_service_name: client_id或服务名

        Returns:
            Dict: 删除结果
        """
        try:
            return self._run_async_via_bridge(
                self.delete_config_async(client_id_or_service_name),
                op_name="service_management.delete_config"
            )
        except Exception as e:
            logger.error(f"[NEW_ARCH] delete_config failed: {e}")
            return {
                "success": False,
                "error": str(e),
                "client_id": None,
                "service_name": None
            }

    async def delete_config_async(self, client_id_or_service_name: str) -> Dict[str, Any]:
        """
        删除服务配置（异步版本）

        支持智能参数识别：
        - 如果传入client_id，直接使用
        - 如果传入服务名，自动查找对应的client_id
        - Agent级别严格隔离，只在指定agent范围内查找

        Args:
            client_id_or_service_name: client_id或服务名

        Returns:
            Dict: 删除结果
        """
        try:
            if self._context_type == ContextType.STORE:
                return await self._delete_store_config(client_id_or_service_name)
            else:
                return await self._delete_agent_config(client_id_or_service_name)
        except Exception as e:
            logger.error(f"Failed to delete config: {e}")
            return {
                "success": False,
                "error": f"Failed to delete config: {str(e)}",
                "client_id": None,
                "service_name": None
            }

    def update_config(self, client_id_or_service_name: str, new_config: Dict[str, Any]) -> Dict[str, Any]:
        """
        更新服务配置（同步版本）

        Args:
            client_id_or_service_name: client_id或服务名
            new_config: 新的配置信息

        Returns:
            Dict: 更新结果
        """
        try:
            return self._run_async_via_bridge(
                self.update_config_async(client_id_or_service_name, new_config),
                op_name="service_management.update_config"
            )
        except Exception as e:
            logger.error(f"[NEW_ARCH] update_config failed: {e}")
            return {
                "success": False,
                "error": str(e),
                "client_id": None,
                "service_name": None,
                "old_config": None,
                "new_config": None
            }

    async def update_config_async(self, client_id_or_service_name: str, new_config: Dict[str, Any]) -> Dict[str, Any]:
        """
        更新服务配置（异步版本）

        支持智能参数识别和多种配置格式：
        - 参数识别：client_id或服务名自动识别
        - 配置格式：支持简化格式和mcpServers格式
        - 字段验证：不允许修改服务名，不允许新增字段类型
        - Agent级别严格隔离

        Args:
            client_id_or_service_name: client_id或服务名
            new_config: 新的配置信息

        Returns:
            Dict: 更新结果
        """
        try:
            if self._context_type == ContextType.STORE:
                return await self._update_store_config(client_id_or_service_name, new_config)
            else:
                return await self._update_agent_config(client_id_or_service_name, new_config)
        except Exception as e:
            logger.error(f"Failed to update config: {e}")
            return {
                "success": False,
                "error": f"Failed to update config: {str(e)}",
                "client_id": None,
                "service_name": None,
                "old_config": None,
                "new_config": None
            }

    def _is_deterministic_client_id(self, identifier: str) -> bool:
        """使用 ClientIDGenerator 统一判断确定性client_id格式"""
        try:
            from mcpstore.core.utils.id_generator import ClientIDGenerator
            return ClientIDGenerator.is_deterministic_format(identifier)
        except Exception:
            return False

    def _parse_deterministic_client_id(self, client_id: str, agent_id: str) -> Tuple[str, str]:
        """使用 ClientIDGenerator 统一解析确定性client_id，并验证agent范围"""
        from mcpstore.core.utils.id_generator import ClientIDGenerator
        parsed = ClientIDGenerator.parse_client_id(client_id)
        if parsed.get("type") == "store":
            global_agent_store_id = self._store.client_manager.global_agent_store_id
            if agent_id != global_agent_store_id:
                raise ValueError(f"Store client_id '{client_id}' cannot be used with agent '{agent_id}'")
            return client_id, parsed.get("service_name")
        elif parsed.get("type") == "agent":
            if parsed.get("agent_id") != agent_id:
                raise ValueError(f"Client_id '{client_id}' belongs to agent '{parsed.get('agent_id')}', not '{agent_id}'")
            return client_id, parsed.get("service_name")
        raise ValueError(f"Cannot parse client_id format: {client_id}")

    async def _validate_resolved_mapping_async(self, client_id: str, service_name: str, agent_id: str) -> bool:
        """
        验证解析后的client_id和service_name映射是否有效（异步版本）

        Args:
            client_id: 解析出的client_id
            service_name: 解析出的service_name
            agent_id: Agent ID

        Returns:
            bool: 映射是否有效
        """
        try:
            # 检查client_id是否存在于agent的映射中 - 从 pykv 获取
            agent_clients = await self._store.registry.get_agent_clients_async(agent_id)
            if client_id not in agent_clients:
                logger.debug(f" [VALIDATE_MAPPING] client_id '{client_id}' not found in agent '{agent_id}' clients")
                return False

            # 检查service_name是否存在于Registry中
            existing_client_id = await self._store.registry._agent_client_service.get_service_client_id_async(agent_id, service_name)
            if existing_client_id != client_id:
                logger.debug(f" [VALIDATE_MAPPING] service '{service_name}' maps to different client_id: expected={client_id}, actual={existing_client_id}")
                return False

            return True
        except Exception as e:
            logger.debug(f" [VALIDATE_MAPPING] Validation failed: {e}")
            return False

    def _validate_resolved_mapping(self, client_id: str, service_name: str, agent_id: str) -> bool:
        raise RuntimeError("[SERVICE_MANAGEMENT] Synchronous validate_mapping is disabled, please use _validate_resolved_mapping_async.")

    async def _resolve_client_id_async(self, client_id_or_service_name: str, agent_id: str) -> Tuple[str, str]:
        """
        智能解析client_id或服务名（使用最新的确定性算法）

        Args:
            client_id_or_service_name: 用户输入的参数
            agent_id: Agent ID（用于范围限制）

        Returns:
            Tuple[client_id, service_name]: 解析后的client_id和服务名

        Raises:
            ValueError: 当参数无法解析或不存在时
        """
        logger.debug(f"[RESOLVE_CLIENT_ID] start value='{client_id_or_service_name}' agent='{agent_id}'")

        from .agent_service_mapper import AgentServiceMapper
        global_agent_id = self._store.client_manager.global_agent_store_id

        # 1) 优先：确定性 client_id 直接解析
        if self._is_deterministic_client_id(client_id_or_service_name):
            try:
                client_id, service_name = self._parse_deterministic_client_id(client_id_or_service_name, agent_id)
                logger.debug(f"[RESOLVE_CLIENT_ID] deterministic_ok client_id={client_id} service_name={service_name}")
                return client_id, service_name
            except ValueError as e:
                logger.debug(f"[RESOLVE_CLIENT_ID] deterministic_parse_failed error={e}")
                # 继续按服务名处理

        # 2) Agent 模式：透明代理到 Store（不依赖 Agent 命名空间缓存）
        if self._context_type == ContextType.AGENT and agent_id != global_agent_id:
            # 2.1 判断输入是本地名还是全局名
            input_name = client_id_or_service_name
            global_service_name = None

            if AgentServiceMapper.is_any_agent_service(input_name):
                # 输入是全局名，校验归属
                try:
                    parsed_agent_id, local_name = AgentServiceMapper.parse_agent_service_name(input_name)
                    if parsed_agent_id != agent_id:
                        raise ValueError(f"Service '{input_name}' belongs to agent '{parsed_agent_id}', not '{agent_id}'")
                    global_service_name = input_name
                except ValueError as e:
                    raise ValueError(f"Invalid agent service name '{input_name}': {e}")
            else:
                # 输入是本地名：优先用映射，其次用规则推导
                mapped = await self._store.registry.get_global_name_from_agent_service_async(agent_id, input_name)
                global_service_name = mapped or AgentServiceMapper(agent_id).to_global_name(input_name)

            # 2.2 优先在 Agent 命名空间解析 client_id，再回退到 Store 命名空间
            client_id = await self._store.registry._agent_client_service.get_service_client_id_async(agent_id, input_name)
            if not client_id:
                # 回退到 Store 命名空间
                client_id = await self._store.registry._agent_client_service.get_service_client_id_async(global_agent_id, global_service_name)

            if not client_id:
                available_agent = ', '.join(await self._store.registry.get_all_service_names_async(agent_id)) or 'None'
                available_global = ', '.join(await self._store.registry.get_all_service_names_async(global_agent_id)) or 'None'
                raise ValueError(
                    f"Service '{input_name}' (global '{global_service_name}') not found. "
                    f"Agent services: {available_agent}. Store services: {available_global}"
                )

            logger.debug(f"[RESOLVE_CLIENT_ID] agent_proxy_ok local_or_global='{input_name}' -> global='{global_service_name}' client_id={client_id}")
            return client_id, global_service_name

        # 3) Store 模式：直接在 Store 命名空间解析
        service_name = client_id_or_service_name
        service_names = await self._store.registry.get_all_service_names_async(agent_id)
        if service_name in service_names:
            client_id = await self._store.registry._agent_client_service.get_service_client_id_async(agent_id, service_name)
            if client_id:
                logger.debug(f"[RESOLVE_CLIENT_ID] store_lookup_ok service={service_name} client_id={client_id}")
                return client_id, service_name
            else:
                raise ValueError(f"Service '{service_name}' found but no client_id mapping")

        available_services = ', '.join(service_names) if service_names else 'None'
        raise ValueError(f"Service '{service_name}' not found in store. Available services: {available_services}")

    def _resolve_client_id(self, client_id_or_service_name: str, agent_id: str) -> Tuple[str, str]:
        """
        同步包装，保留给旧代码使用；内部通过 AOB 执行异步解析。
        """
        return self._run_async_via_bridge(
            self._resolve_client_id_async(client_id_or_service_name, agent_id),
            op_name="service_management.resolve_client_id"
        )

    async def _delete_store_config(self, client_id_or_service_name: str) -> Dict[str, Any]:
        """Store级别删除配置的内部实现"""
        try:
            logger.info(f"[DELETE_CONFIG] [STORE] Store level: deleting configuration {client_id_or_service_name}")

            global_agent_store_id = self._store.client_manager.global_agent_store_id

            # 解析client_id和服务名
            client_id, service_name = await self._resolve_client_id_async(client_id_or_service_name, global_agent_store_id)

            logger.info(f"[DELETE_CONFIG] [RESOLVE] Resolution result: client_id={client_id}, service_name={service_name}")

            # 验证服务存在
            if not self._store.registry.get_session(global_agent_store_id, service_name):
                logger.warning(f"Service {service_name} not found in registry, but continuing with cleanup")

            # 事务性删除：直接删除缓存/映射，不触碰文件
            # 1. 从缓存中删除服务（包括工具和会话）- 使用异步版本
            await self._store.registry.remove_service_async(global_agent_store_id, service_name)

            # 2. 删除Service-Client映射
            self._store.registry.remove_service_client_mapping(global_agent_store_id, service_name)

            # 3. 删除Client配置
            self._store.registry.remove_client_config(client_id)

            # 4. 删除Agent-Client映射
            self._store.registry.remove_agent_client_mapping(global_agent_store_id, client_id)

            # 5. 单源模式：不再同步到分片文件或 mcp.json
            logger.info("Single-source mode: skip file/shard sync")

            logger.info(f"[DELETE_CONFIG] [STORE] Store level: configuration deletion completed {service_name}")

            return {
                "success": True,
                "message": f"Service '{service_name}' deleted successfully",
                "client_id": client_id,
                "service_name": service_name
            }

        except Exception as e:
            logger.error(f"[DELETE_CONFIG] [ERROR] Store level configuration deletion failed: {e}")
            return {
                "success": False,
                "error": f"Failed to delete store config: {str(e)}",
                "client_id": None,
                "service_name": None
            }

    async def _delete_agent_config(self, client_id_or_service_name: str) -> Dict[str, Any]:
        """Agent级别删除配置的内部实现"""
        try:
            logger.info(f"[DELETE_CONFIG] [AGENT] Agent level: deleting Agent {self._agent_id} configuration {client_id_or_service_name}")

            # 解析client_id和服务名
            client_id, service_name = await self._resolve_client_id_async(client_id_or_service_name, self._agent_id)

            logger.info(f"[DELETE_CONFIG] [RESOLVE] Resolution result: client_id={client_id}, service_name={service_name}")

            # 验证服务存在
            if not self._store.registry.get_session(self._agent_id, service_name):
                logger.warning(f"Service {service_name} not found in registry for agent {self._agent_id}, but continuing with cleanup")

            # Agent级别删除：只删除缓存，不修改mcp.json
            # 1. 从缓存中删除服务（包括工具和会话）- 使用异步版本
            await self._store.registry.remove_service_async(self._agent_id, service_name)

            # 2. 删除Service-Client映射
            self._store.registry.remove_service_client_mapping(self._agent_id, service_name)

            # 3. 删除Client配置
            self._store.registry.remove_client_config(client_id)

            # 4. 删除Agent-Client映射
            self._store.registry.remove_agent_client_mapping(self._agent_id, client_id)

            # 5. 单源模式：不再同步到分片文件
            logger.info("Single-source mode: skip shard mapping files sync")

            logger.info(f"[DELETE_CONFIG] [AGENT] Agent level: configuration deletion completed {service_name}")

            return {
                "success": True,
                "message": f"Service '{service_name}' deleted successfully from agent '{self._agent_id}'",
                "client_id": client_id,
                "service_name": service_name
            }

        except Exception as e:
            logger.error(f"[DELETE_CONFIG] [ERROR] Agent level configuration deletion failed: {e}")
            return {
                "success": False,
                "error": f"Failed to delete agent config: {str(e)}",
                "client_id": None,
                "service_name": None
            }

    def _validate_and_normalize_config(self, new_config: Dict[str, Any], service_name: str, old_config: Dict[str, Any]) -> Dict[str, Any]:
        """
        验证和标准化配置

        Args:
            new_config: 新配置
            service_name: 服务名
            old_config: 原配置

        Returns:
            Dict: 标准化后的配置

        Raises:
            ValueError: 配置验证失败
        """
        # 1. 处理配置格式
        if "mcpServers" in new_config:
            # mcpServers格式
            if len(new_config["mcpServers"]) != 1:
                raise ValueError("mcpServers format must contain exactly one service")

            config_service_name = list(new_config["mcpServers"].keys())[0]
            if config_service_name != service_name:
                raise ValueError(f"Cannot change service name from '{service_name}' to '{config_service_name}'")

            normalized_config = new_config["mcpServers"][service_name]
        else:
            # 简化格式
            if "name" in new_config:
                raise ValueError("Cannot modify service name in config update")
            normalized_config = new_config.copy()

        # 2. 验证字段类型一致性
        old_config_keys = set(old_config.keys())
        new_config_keys = set(normalized_config.keys())

        # 检查是否有新增的字段类型
        new_fields = new_config_keys - old_config_keys
        if new_fields:
            raise ValueError(f"Cannot add new field types: {list(new_fields)}. Only existing fields can be updated.")

        # 3. 验证字段值的合理性
        for key, value in normalized_config.items():
            if key in old_config:
                old_type = type(old_config[key])
                new_type = type(value)

                # 允许的类型转换
                if old_type != new_type:
                    # 允许字符串和数字之间的转换
                    if not ((old_type in [str, int, float] and new_type in [str, int, float]) or
                            (old_type == list and new_type == list)):
                        raise ValueError(f"Field '{key}' type mismatch: expected {old_type.__name__}, got {new_type.__name__}")

        return normalized_config

    async def _update_store_config(self, client_id_or_service_name: str, new_config: Dict[str, Any]) -> Dict[str, Any]:
        """Store级别更新配置的内部实现"""
        try:
            logger.info(f"[UPDATE_CONFIG] [STORE] Store level: updating configuration {client_id_or_service_name}")

            global_agent_store_id = self._store.client_manager.global_agent_store_id

            # 解析client_id和服务名
            client_id, service_name = await self._resolve_client_id_async(client_id_or_service_name, global_agent_store_id)

            logger.info(f"[UPDATE_CONFIG] [RESOLVE] Resolution result: client_id={client_id}, service_name={service_name}")

            # 获取当前配置
            old_complete_info = await self._store.registry.get_complete_service_info_async(global_agent_store_id, service_name)
            old_config = old_complete_info.get("config", {})

            if not old_config:
                raise ValueError(f"Service '{service_name}' configuration not found")

            # 验证和标准化新配置
            normalized_config = self._validate_and_normalize_config(new_config, service_name, old_config)

            logger.info(f"[UPDATE_CONFIG] [VALIDATE] Configuration validation passed, starting update: {service_name}")

            # 1. 清空服务的工具和会话数据
            self._store.registry.clear_service_tools_only(global_agent_store_id, service_name)

            # 2. 更新Client配置缓存
            self._store.registry.update_client_config(client_id, {
                "mcpServers": {service_name: normalized_config}
            })

            # 3. 设置服务状态为STARTUP并更新元数据
            from mcpstore.core.models.service import ServiceConnectionState
            await self._store.orchestrator.lifecycle_manager._transition_state(
                agent_id=global_agent_store_id,
                service_name=service_name,
                new_state=ServiceConnectionState.STARTUP,
                reason="config_updated",
                source="ServiceManagement",
            )

            # 从 pykv 异步获取并更新服务元数据中的配置
            metadata = await self._store.registry._service_state_service.get_service_metadata_async(global_agent_store_id, service_name)
            if metadata:
                metadata.service_config = normalized_config
                metadata.consecutive_failures = 0
                metadata.error_message = None
                from datetime import datetime
                metadata.state_entered_time = datetime.now()
                self._store.registry.set_service_metadata(global_agent_store_id, service_name, metadata)

            # 4. 单源模式：不再同步到 mcp.json 或分片文件
            logger.info("Single-source mode: skip file/shard sync")

            # 5. 触发生命周期管理器重新初始化服务
            await self._store.orchestrator.lifecycle_manager.initialize_service(
                global_agent_store_id, service_name, normalized_config
            )

            logger.info(f"[UPDATE_CONFIG] [STORE] Store level: configuration update completed {service_name}")

            return {
                "success": True,
                "message": f"Service '{service_name}' configuration updated successfully",
                "client_id": client_id,
                "service_name": service_name,
                "old_config": old_config,
                "new_config": normalized_config
            }

        except Exception as e:
            logger.error(f"[UPDATE_CONFIG] [ERROR] Store level configuration update failed: {e}")
            return {
                "success": False,
                "error": f"Failed to update store config: {str(e)}",
                "client_id": None,
                "service_name": None,
                "old_config": None,
                "new_config": None
            }

    async def _update_agent_config(self, client_id_or_service_name: str, new_config: Dict[str, Any]) -> Dict[str, Any]:
        """Agent级别更新配置的内部实现"""
        try:
            logger.info(f"[UPDATE_CONFIG] [AGENT] Agent level: updating Agent {self._agent_id} configuration {client_id_or_service_name}")

            # 解析client_id和服务名
            client_id, service_name = await self._resolve_client_id_async(client_id_or_service_name, self._agent_id)

            logger.info(f"[UPDATE_CONFIG] [RESOLVE] Resolution result: client_id={client_id}, service_name={service_name}")

            # 获取当前配置
            old_complete_info = await self._store.registry.get_complete_service_info_async(self._agent_id, service_name)
            old_config = old_complete_info.get("config", {})

            if not old_config:
                raise ValueError(f"Service '{service_name}' configuration not found")

            # 验证和标准化新配置
            normalized_config = self._validate_and_normalize_config(new_config, service_name, old_config)

            logger.info(f"[UPDATE_CONFIG] [VALIDATE] Configuration validation passed, starting update: {service_name}")

            # 1. 清空服务的工具和会话数据
            self._store.registry.clear_service_tools_only(self._agent_id, service_name)

            # 2. 更新Client配置缓存
            self._store.registry.update_client_config(client_id, {
                "mcpServers": {service_name: normalized_config}
            })

            # 3. 设置服务状态为STARTUP并更新元数据
            from mcpstore.core.models.service import ServiceConnectionState
            await self._store.orchestrator.lifecycle_manager._transition_state(
                agent_id=self._agent_id,
                service_name=service_name,
                new_state=ServiceConnectionState.STARTUP,
                reason="agent_config_updated",
                source="ServiceManagement",
            )

            # 从 pykv 异步获取并更新服务元数据中的配置
            metadata = await self._store.registry._service_state_service.get_service_metadata_async(self._agent_id, service_name)
            if metadata:
                metadata.service_config = normalized_config
                metadata.consecutive_failures = 0
                metadata.error_message = None
                from datetime import datetime
                metadata.state_entered_time = datetime.now()
                self._store.registry.set_service_metadata(self._agent_id, service_name, metadata)

            # 4. 单源模式：不再同步到分片文件（Agent级别不更新mcp.json）
            logger.info("Single-source mode: skip shard mapping files sync")

            # 5. 触发生命周期管理器重新初始化服务
            await self._store.orchestrator.lifecycle_manager.initialize_service(
                self._agent_id, service_name, normalized_config
            )

            logger.info(f"[UPDATE_CONFIG] [AGENT] Agent level: configuration update completed {service_name}")

            return {
                "success": True,
                "message": f"Service '{service_name}' configuration updated successfully for agent '{self._agent_id}'",
                "client_id": client_id,
                "service_name": service_name,
                "old_config": old_config,
                "new_config": normalized_config
            }

        except Exception as e:
            logger.error(f"[UPDATE_CONFIG] [ERROR] Agent level configuration update failed: {e}")
            return {
                "success": False,
                "error": f"Failed to update agent config: {str(e)}",
                "client_id": None,
                "service_name": None,
                "old_config": None,
                "new_config": None
            }

    def get_service_status(self, name: str) -> dict:
        """获取单个服务的状态信息（同步版本，内部桥接异步）。"""
        try:
            return self._run_async_via_bridge(
                self.get_service_status_async(name),
                op_name="service_management.get_service_status"
            )
        except Exception as e:
            logger.error(f"[NEW_ARCH] get_service_status failed: {e}")
            return {"status": "error", "error": str(e)}

    async def get_service_status_async(self, name: str) -> dict:
        """获取单个服务的状态信息"""
        try:
            if self._context_type == ContextType.STORE:
                from mcpstore.utils.perspective_resolver import PerspectiveResolver

                resolver = PerspectiveResolver()
                name_res = resolver.normalize_service_name(
                    self._store.client_manager.global_agent_store_id,
                    name,
                    target="global",
                    strict=True,
                )
                return await self._store.orchestrator.get_service_status_async(name_res.global_name)
            else:
                # Agent模式：转换服务名称（严格校验）
                from mcpstore.utils.perspective_resolver import PerspectiveResolver

                resolver = PerspectiveResolver()
                name_res = resolver.normalize_service_name(
                    self._agent_id,
                    name,
                    target="global",
                    strict=True,
                )
                return await self._store.orchestrator.get_service_status_async(name_res.global_name)
        except Exception as e:
            logger.error(f"Failed to get service status for {name}: {e}")
            return {"status": "error", "error": str(e)}

    # 别名：符合命名规范
    def service_status(self, name: str) -> dict:
        return self.get_service_status(name)

    async def service_status_async(self, name: str) -> dict:
        return await self.get_service_status_async(name)

    def restart_service(self, name: str) -> bool:
        raise RuntimeError("[SERVICE_MANAGEMENT] Synchronous restart_service is disabled, please use restart_service_async.")

    async def restart_service_async(self, name: str) -> bool:
        """重启指定服务（透明代理）"""
        try:
            if self._context_type == ContextType.STORE:
                from mcpstore.utils.perspective_resolver import PerspectiveResolver
                from mcpstore.core.exceptions import PerspectiveResolutionError

                try:
                    resolver = PerspectiveResolver()
                    name_res = resolver.normalize_service_name(
                        self._store.client_manager.global_agent_store_id,
                        name,
                        target="global",
                        strict=False,
                    )
                    target_name = name_res.global_name
                except Exception as e:
                    raise PerspectiveResolutionError(name, str(e)) from e

                return await self._store.orchestrator.restart_service(target_name)
            else:
                # Agent模式：透明代理 - 将本地服务名映射到全局服务名，并在全局命名空间执行重启
                global_name = await self._map_agent_service_to_global(name)
                global_agent = self._store.client_manager.global_agent_store_id
                return await self._store.orchestrator.restart_service(global_name, global_agent)
        except Exception as e:
            logger.error(f"Failed to restart service {name}: {e}")
            raise

    # === Lifecycle-only disconnection (no config/registry deletion) ===
    def disconnect_service(self, name: str, reason: str = "user_requested") -> bool:
        raise RuntimeError("[SERVICE_MANAGEMENT] Synchronous disconnect_service is disabled, please use disconnect_service_async.")

    async def disconnect_service_async(self, name: str, reason: str = "user_requested") -> bool:
        """
        断开服务（异步版本）- 仅生命周期断链：不改配置/不删注册表。

        Store 上下文：name 视为全局名；
        Agent 上下文：自动将本地名映射为全局名后断开。
        """
        try:
            global_agent_id = self._store.client_manager.global_agent_store_id
            if self._context_type == ContextType.STORE:
                from mcpstore.utils.perspective_resolver import PerspectiveResolver
                from mcpstore.core.exceptions import PerspectiveResolutionError

                try:
                    resolver = PerspectiveResolver()
                    name_res = resolver.normalize_service_name(
                        self._store.client_manager.global_agent_store_id,
                        name,
                        target="global",
                        strict=False,
                    )
                    global_name = name_res.global_name
                except Exception as e:
                    raise PerspectiveResolutionError(name, str(e)) from e
            else:
                global_name = await self._map_agent_service_to_global(name)

            # 调用生命周期管理器执行优雅断开
            lm = self._store.orchestrator.lifecycle_manager
            await lm.graceful_disconnect(global_agent_id, global_name, reason)

            # 清空工具展示缓存（仅清工具，不删除服务实体）
            try:
                self._store.registry.clear_service_tools_only(global_agent_id, global_name)
            except Exception:
                pass
            return True
        except Exception as e:
            logger.error(f"[DISCONNECT_SERVICE] Failed to disconnect '{name}': {e}")
            raise

    # ===  新增：Agent 透明代理辅助方法 ===

    async def _map_agent_service_to_global(self, local_name: str) -> str:
        """
        将 Agent 的本地服务名映射到全局服务名

        Args:
            local_name: Agent 中的本地服务名

        Returns:
            str: 全局服务名
        """
        try:
            from mcpstore.utils.perspective_resolver import PerspectiveResolver

            resolver = PerspectiveResolver()
            res = resolver.normalize_service_name(
                self._agent_id,
                local_name,
                target="global",
                strict=False,
            )
            logger.debug(f" [SERVICE_PROXY] Service name mapping via PerspectiveResolver: {local_name} -> {res.global_name}")
            return res.global_name
        except Exception as e:
            logger.error(f" [SERVICE_PROXY] Service name mapping failed: {e}")
            return local_name

    async def _delete_store_service_with_sync(self, service_name: str):
        """Store 服务删除（带双向同步）"""
        try:
            # 1. 从 Registry 中删除（使用异步版本）
            await self._store.registry.remove_service_async(
                self._store.client_manager.global_agent_store_id,
                service_name
            )

            # 2. 单源模式：不再同步到 mcp.json
            logger.info("[SERVICE_DELETE] [STORE] Skip file sync (single-source KV)")

            # 3. 触发双向同步（如果是 Agent 服务）
            if hasattr(self._store, 'bidirectional_sync_manager'):
                await self._store.bidirectional_sync_manager.handle_service_deletion_with_sync(
                    self._store.client_manager.global_agent_store_id,
                    service_name
                )

        except Exception as e:
            logger.error(f" [SERVICE_DELETE] Store service deletion failed {service_name}: {e}")
            raise

    async def _delete_agent_service_with_sync(self, local_name: str):
        """Agent 服务删除（带双向同步），返回是否成功"""
        try:
            # 使用 PerspectiveResolver 统一归一化输入到本地名
            from mcpstore.utils.perspective_resolver import PerspectiveResolver

            resolver = PerspectiveResolver()
            local_res = resolver.normalize_service_name(
                self._agent_id,
                local_name,
                target="local",
                strict=True,
            )
            local_name = local_res.local_name

            success = True
            # 1. 获取全局名称（使用异步版本，避免 AOB 事件循环冲突）
            global_res = resolver.normalize_service_name(
                self._agent_id,
                local_name,
                target="global",
                strict=True,
            )
            global_name = global_res.global_name
            if not global_name:
                raise ValueError(f"Service mapping not found: {self._agent_id}:{local_name}")

            # 2. 从 Agent 缓存中删除（使用异步版本）
            await self._store.registry.remove_service_async(self._agent_id, local_name)

            # 3. 从 Store 缓存中删除（使用异步版本）
            await self._store.registry.remove_service_async(
                self._store.client_manager.global_agent_store_id,
                global_name
            )

            # 4. 移除映射关系（仅映射表，不触发关系/状态删除）
            await self._store.registry.remove_agent_service_mapping_async(self._agent_id, local_name)

            # 5. 单源模式：不再同步到 mcp.json
            logger.info("[SERVICE_DELETE] [AGENT] Skip file sync (single-source KV)")

            # 6. 清理服务状态数据
            try:
                state_manager = self._store.registry._cache_state_manager
                await state_manager.delete_service_status(global_name)
                await state_manager.delete_service_metadata(global_name)
                logger.info(
                    f"[SERVICE_DELETE] Service status cleanup successful: "
                    f"agent_id={self._agent_id}, service={local_name}, global_name={global_name}"
                )
            except Exception as cleanup_error:
                logger.error(
                    f"[SERVICE_DELETE] Service status cleanup failed: "
                    f"agent_id={self._agent_id}, service={local_name}, error={cleanup_error}"
                )
                raise

            # 7. 单源模式：不再同步到分片文件
            logger.info("Single-source mode: skip shard mapping files sync")
            return success

        except Exception as e:
            logger.error(f" [SERVICE_DELETE] Agent service deletion failed {self._agent_id}:{local_name}: {e}")
            raise

    def show_mcpconfig(self) -> Dict[str, Any]:
        """
        根据当前上下文（store/agent）获取对应的配置信息

        Returns:
            Dict[str, Any]: Store上下文返回MCP JSON格式，Agent上下文返回client配置字典
        """
        if self._context_type == ContextType.STORE:
            # Store上下文：返回MCP JSON格式的配置（从缓存读取，更高效）
            try:
                config = self._store._unified_config.get_mcp_config()
                # 确保返回格式正确
                if isinstance(config, dict) and 'mcpServers' in config:
                    return config
                else:
                    logger.warning("Invalid MCP config format")
                    return {"mcpServers": {}}
            except Exception as e:
                logger.error(f"Failed to show MCP config: {e}")
                return {"mcpServers": {}}
        else:
            # Agent上下文：返回所有相关client配置的字典
            return self._run_async_via_bridge(
                self._show_config_agent_async(),
                op_name="service_management.show_config_agent"
            )

    async def _show_config_agent_async(self) -> Dict[str, Any]:
        """Agent上下文的 show_config 异步实现"""
        agent_id = self._agent_id
        # 从 pykv 获取 client_ids
        client_ids = await self._store.registry.get_agent_clients_async(agent_id)

        # 获取每个client的配置
        result = {}
        for client_id in client_ids:
            client_config = self._store.orchestrator.client_manager.get_client_config(client_id)
            if client_config:
                result[client_id] = client_config

        return result

    def wait_service(self, client_id_or_service_name: str,
                    status: Union[str, List[str]] = 'healthy',
                    timeout: float = 10.0,
                    raise_on_timeout: bool = False) -> Dict[str, Any]:
        """
        等待服务达到指定状态（同步版本，使用新架构避免死锁）。

        Args:
            client_id_or_service_name: client_id或服务名（智能识别）
            status: 目标状态，可以是单个状态字符串或状态列表
            timeout: 超时时间（秒），默认10秒
            raise_on_timeout: 超时时是否抛出异常，默认False

        Returns:
            dict: {success, status, window_metrics, retry_in, hard_timeout_in, lease_remaining,
                   next_retry_time, hard_deadline, lease_deadline, response_time,
                   consecutive_failures, last_state_change, hard_timeout_remaining, last_error}

        Raises:
            TimeoutError: 当raise_on_timeout=True且超时时抛出
            ValueError: 当参数无法解析时抛出
        """
        try:
            # 解析服务名称（简化版，实际可能需要更复杂的解析逻辑）
            service_name = self._extract_service_name_from_identifier(client_id_or_service_name)

            # 使用新架构：同步外壳
            if not hasattr(self, '_service_management_sync_shell'):
                from ..architecture import ServiceManagementFactory
                self._service_management_sync_shell, _, _ = ServiceManagementFactory.create_service_management(
                    self._store.registry,
                    self._store.orchestrator,
                    agent_id=self._agent_id or self._store.client_manager.global_agent_store_id
                )

            # 直接调用同步外壳，避免_sync_helper.run_async的复杂性
            result = self._service_management_sync_shell.wait_service(service_name, timeout)
            if isinstance(result, bool):
                result = {"success": bool(result), "status": None}
            result = self._enrich_wait_result(result)
            if not result.get("success") and raise_on_timeout:
                raise TimeoutError(f"Service {service_name} did not reach status {status} within {timeout} seconds")
            return result

        except Exception as e:
            logger.error(f"[NEW_ARCH] wait_service failed: {e}")
            if raise_on_timeout:
                raise
            return {"success": False, "error": str(e)}

    async def wait_service_async(self, client_id_or_service_name: str,
                               status: Union[str, List[str]] = 'healthy',
                               timeout: float = 10.0,
                               raise_on_timeout: bool = False) -> Dict[str, Any]:
        """
        等待服务达到指定状态（异步版本）

        Args:
            client_id_or_service_name: client_id或服务名（智能识别）
            status: 目标状态，可以是单个状态字符串或状态列表
            timeout: 超时时间（秒），默认10秒
            raise_on_timeout: 超时时是否抛出异常，默认False

        Returns:
            dict: {success, status, window_metrics, retry_in, hard_timeout_in, lease_remaining,
                   next_retry_time, hard_deadline, lease_deadline, response_time,
                   consecutive_failures, last_state_change, hard_timeout_remaining, last_error}

        Raises:
            TimeoutError: 当raise_on_timeout=True且超时时抛出
            ValueError: 当参数无法解析时抛出
        """
        try:
            # 解析参数
            agent_scope = self._agent_id if self._context_type == ContextType.AGENT else self._store.client_manager.global_agent_store_id
            client_id, service_name = await self._resolve_client_id_async(client_id_or_service_name, agent_scope)

            # 在纯视图模式下，Agent 的状态查询统一使用全局命名空间
            status_agent_key = self._store.client_manager.global_agent_store_id


            # 诊断：解析后的作用域与标识
            try:
                logger.info(f"[WAIT_SERVICE] resolved agent_scope={agent_scope} client_id='{client_id}' service='{service_name}' status_agent_key={status_agent_key}")
            except Exception:
                pass

            # 解析等待模式
            change_mode = False
            if isinstance(status, str) and status.lower() == 'change':
                change_mode = True
                logger.info(f"[WAIT_SERVICE] start mode=change service='{service_name}' timeout={timeout}s")
                try:
                    initial_status = (await self._store.orchestrator.get_service_status_async(service_name, status_agent_key) or {}).get("status", "unknown")
                except Exception as _e_init:
                    logger.debug(f"[WAIT_SERVICE] initial_status_error service='{service_name}' error={_e_init}")
                    initial_status = "unknown"
            else:
                # 规范化目标状态
                target_statuses = self._normalize_target_statuses(status)
                logger.info(f"[WAIT_SERVICE] start mode=target service='{service_name}' client_id='{client_id}' target={target_statuses} timeout={timeout}s")

            start_time = time.time()
            poll_interval = 0.2  # 200ms轮询间隔
            prev_status = None
            last_log = start_time
            last_meta: Dict[str, Any] = {}

            while True:
                # 检查超时
                elapsed = time.time() - start_time
                if elapsed >= timeout:
                    if change_mode:
                        msg = f"[WAIT_SERVICE] timeout mode=change service='{service_name}' from='{initial_status}' elapsed={elapsed:.2f}s"
                    else:
                        msg = f"[WAIT_SERVICE] timeout mode=target service='{service_name}' target={target_statuses} last='{prev_status}' elapsed={elapsed:.2f}s"
                    logger.warning(msg)
                    if raise_on_timeout:
                        raise TimeoutError(msg)
                    return self._enrich_wait_result({
                        "success": False,
                        "status": prev_status or "unknown",
                        "hard_timeout_remaining": max(timeout - elapsed, 0.0),
                        "last_error": msg,
                    }, meta=last_meta)

                # 获取当前状态（先读一次缓存，随后在必要时读一次新缓存以防止竞态）
                try:

                    status_dict = await self._store.orchestrator.get_service_status_async(service_name, status_agent_key) or {}
                    current_status = status_dict.get("status", "unknown")
                    try:
                        meta = await self._store.registry._service_state_service.get_service_metadata_async(status_agent_key, service_name)
                        if meta:
                            last_meta = {
                                "window_error_rate": getattr(meta, "window_error_rate", None),
                                "latency_p95": getattr(meta, "latency_p95", None),
                                "latency_p99": getattr(meta, "latency_p99", None),
                                "sample_size": getattr(meta, "sample_size", None),
                                "next_retry_time": getattr(meta, "next_retry_time", None),
                                "hard_deadline": getattr(meta, "hard_deadline", None),
                                "lease_deadline": getattr(meta, "lease_deadline", None),
                                "response_time": getattr(meta, "response_time", None),
                                "consecutive_failures": getattr(meta, "consecutive_failures", None),
                                "last_state_change": getattr(meta, "state_entered_time", None) or getattr(meta, "last_health_check", None),
                                "last_error": getattr(meta, "error_message", None),
                            }
                    except Exception as meta_err:
                        logger.debug(f"[WAIT_SERVICE] metadata_fetch_error service='{service_name}' error={meta_err}")

                    # 仅在状态变化或每2秒节流一次打印
                    now = time.time()
                    if current_status != prev_status or (now - last_log) > 2.0:
                        logger.debug(f"[WAIT_SERVICE] status service='{service_name}' value='{current_status}'")
                        # 对比 orchestrator 与 registry 的状态及最近健康检查（节流打印）
                        try:
                            reg_state = await self._store.registry.get_service_state_async(status_agent_key, service_name)
                            meta = await self._store.registry._service_state_service.get_service_metadata_async(status_agent_key, service_name)
                            last_check_ts = meta.last_health_check.isoformat() if getattr(meta, 'last_health_check', None) else None
                            logger.debug(f"[WAIT_SERVICE] compare orchestrator='{current_status}' registry='{getattr(reg_state,'value',reg_state)}' last_check={last_check_ts}")
                        except Exception as e:
                            logger.debug(f"[WAIT_SERVICE] Failed to get metadata: {e}")

                        prev_status, last_log = current_status, now

                    if change_mode:
                        if current_status != initial_status:
                            logger.info(f"[WAIT_SERVICE] done mode=change service='{service_name}' from='{initial_status}' to='{current_status}' elapsed={elapsed:.2f}s")
                            return self._enrich_wait_result({
                                "success": True,
                                "status": current_status,
                                "last_error": last_meta.get("last_error") if last_meta else None,
                            }, meta=last_meta)
                    else:
                        # 检查是否达到目标状态
                        if current_status in target_statuses:
                            logger.info(f"[WAIT_SERVICE] done mode=target service='{service_name}' reached='{current_status}' elapsed={elapsed:.2f}s")
                            return self._enrich_wait_result({
                                "success": True,
                                "status": current_status,
                                "last_error": last_meta.get("last_error") if last_meta else None,
                            }, meta=last_meta)
                except Exception as e:
                    # 降级到 debug，避免无意义刷屏
                    logger.debug(f"[WAIT_SERVICE] status_error service='{service_name}' error={e}")
                    # 继续轮询

                # 等待下次轮询
                await asyncio.sleep(poll_interval)

        except ValueError as e:
            logger.error(f"[WAIT_SERVICE] param_error error={e}")
            raise
        except Exception as e:
            logger.error(f"[WAIT_SERVICE] unexpected_error error={e}")
            if raise_on_timeout:
                raise
            return {"success": False, "error": str(e)}

    @staticmethod
    def _remaining_seconds(dt: Any) -> Optional[float]:
        """计算距离未来时间的剩余秒数"""
        try:
            if dt is None:
                return None
            import datetime
            if isinstance(dt, (int, float)):
                return max(dt - time.time(), 0.0)
            if isinstance(dt, datetime.datetime):
                return max((dt - datetime.datetime.now()).total_seconds(), 0.0)
            return None
        except Exception:
            return None

    @staticmethod
    def _serialize_time(dt: Any) -> Any:
        """统一序列化时间字段为 ISO 字符串或原值"""
        try:
            if isinstance(dt, datetime.datetime):
                return dt.isoformat()
            return dt
        except Exception:
            return dt

    def _enrich_wait_result(self, result: Dict[str, Any], meta: Any = None) -> Dict[str, Any]:
        """
        将 wait_service 返回结构补齐到与健康状态对齐：
        - window_metrics（错误率/延迟分位/样本数）
        - retry_in/hard_timeout_in/lease_remaining
        - next_retry_time/hard_deadline/lease_deadline（ISO 字符串）
        - response_time/consecutive_failures/last_state_change
        """
        enriched = dict(result or {})

        def _read_meta(key: str) -> Any:
            if meta is None:
                return None
            if hasattr(meta, key):
                return getattr(meta, key)
            if isinstance(meta, dict):
                return meta.get(key)
            return None

        def _set_default(key: str, value: Any):
            if key not in enriched or enriched.get(key) is None:
                enriched[key] = value

        window_metrics = None
        error_rate = _read_meta("window_error_rate")
        latency_p95 = _read_meta("latency_p95")
        latency_p99 = _read_meta("latency_p99")
        sample_size = _read_meta("sample_size")
        if any(v is not None for v in (error_rate, latency_p95, latency_p99, sample_size)):
            window_metrics = {
                "error_rate": error_rate,
                "latency_p95": latency_p95,
                "latency_p99": latency_p99,
                "sample_size": sample_size,
            }

        next_retry_time = _read_meta("next_retry_time")
        hard_deadline = _read_meta("hard_deadline")
        lease_deadline = _read_meta("lease_deadline")
        response_time = _read_meta("response_time") or _read_meta("last_response_time")
        consecutive_failures = _read_meta("consecutive_failures")
        last_state_change = _read_meta("last_state_change") or _read_meta("state_entered_time") or _read_meta("last_health_check")

        _set_default("status", enriched.get("status", "unknown"))
        _set_default("window_metrics", window_metrics)
        _set_default("retry_in", self._remaining_seconds(next_retry_time))
        _set_default("hard_timeout_in", self._remaining_seconds(hard_deadline))
        _set_default("lease_remaining", self._remaining_seconds(lease_deadline))
        _set_default("next_retry_time", self._serialize_time(next_retry_time))
        _set_default("hard_deadline", self._serialize_time(hard_deadline))
        _set_default("lease_deadline", self._serialize_time(lease_deadline))
        _set_default("response_time", response_time)
        _set_default("consecutive_failures", consecutive_failures)
        _set_default("last_state_change", self._serialize_time(last_state_change))
        return enriched

    def _normalize_target_statuses(self, status: Union[str, List[str]]) -> List[str]:
        """
        规范化目标状态参数

        Args:
            status: 状态参数，可以是字符串或列表

        Returns:
            List[str]: 规范化的状态列表

        Raises:
            ValueError: 当状态值无效时抛出
        """
        # 获取有效的状态值
        valid_statuses = {state.value for state in ServiceConnectionState}

        if isinstance(status, str):
            target_statuses = [status]
        elif isinstance(status, list):
            target_statuses = status
        else:
            raise ValueError(f"Status must be string or list, got {type(status)}")

        # 验证状态值
        for s in target_statuses:
            if s not in valid_statuses:
                raise ValueError(f"Invalid status '{s}'. Valid statuses are: {sorted(valid_statuses)}")

        return target_statuses

    def _apply_auth_to_update_config(self, config: Dict[str, Any],
                                    auth: Optional[str],
                                    token: Optional[str],
                                    api_key: Optional[str],
                                    headers: Optional[Dict[str, str]]) -> Dict[str, Any]:
        """将认证配置应用到更新配置中（标准化为 headers + 合并语义）"""
        final_config = config.copy() if config else {}

        # 构造标准化后的 headers
        normalized_headers: Dict[str, str] = {}
        eff_token = token if token else auth
        if eff_token:
            normalized_headers["Authorization"] = f"Bearer {eff_token}"
        if api_key:
            normalized_headers["X-API-Key"] = api_key
        if headers:
            normalized_headers.update(headers)

        if normalized_headers:
            existing = dict(final_config.get("headers", {}) or {})
            existing.update(normalized_headers)
            final_config["headers"] = existing

        # 清理入口字段，避免持久化污染
        for k in ("token", "api_key", "auth"):
            if k in final_config:
                try:
                    del final_config[k]
                except Exception:
                    final_config.pop(k, None)

        return final_config

    def _extract_service_name_from_identifier(self, client_id_or_service_name: str) -> str:
        """
        从标识符中提取服务名称（新架构辅助方法）

        Args:
            client_id_or_service_name: client_id或服务名

        Returns:
            str: 服务名称
        """
        if not isinstance(client_id_or_service_name, str):
            raise ValueError(f"Identifier must be a string, actual type: {type(client_id_or_service_name)}")

        # 如果包含client_id格式，提取服务名称
        if "::" in client_id_or_service_name:
            # global_agent_store::service_name 格式
            parts = client_id_or_service_name.split("::", 1)
            if len(parts) == 2:
                return parts[1]

        # 如果是client_id格式，提取服务名称
        if client_id_or_service_name.startswith("client_"):
            # client_global_agent_store_service_name 格式
            parts = client_id_or_service_name.split("_", 3)
            if len(parts) >= 4:
                return parts[3]

        # 直接返回作为服务名称
        return client_id_or_service_name
