"""MCP 运行时配置转换。

负责将主程序官方配置中的 MCP 配置转换为运行时使用的结构化对象。
"""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Literal

if TYPE_CHECKING:
    from src.config.official_configs import MCPConfig


@dataclass(slots=True)
class MCPAuthorizationRuntimeConfig:
    """MCP HTTP 认证运行时配置。"""

    mode: Literal["none", "bearer"] = "none"
    bearer_token: str = ""


@dataclass(slots=True)
class MCPRootRuntimeConfig:
    """MCP Root 运行时配置。"""

    uri: str
    name: str = ""


@dataclass(slots=True)
class MCPClientRuntimeConfig:
    """MCP 客户端宿主能力运行时配置。"""

    client_name: str = "MaiBot"
    client_version: str = "1.0.0"
    enable_roots: bool = False
    roots: list[MCPRootRuntimeConfig] = field(default_factory=list)
    enable_sampling: bool = False
    sampling_task_name: str = "planner"
    sampling_include_context_support: bool = False
    sampling_tool_support: bool = False
    enable_elicitation: bool = False
    elicitation_allow_form: bool = True
    elicitation_allow_url: bool = False


@dataclass(slots=True)
class MCPServerRuntimeConfig:
    """单个 MCP 服务器的运行时配置。"""

    name: str
    transport: Literal["stdio", "streamable_http", "sse"] = "stdio"
    command: str = ""
    args: list[str] = field(default_factory=list)
    env: dict[str, str] = field(default_factory=dict)
    url: str = ""
    headers: dict[str, str] = field(default_factory=dict)
    http_timeout_seconds: float = 30.0
    read_timeout_seconds: float = 300.0
    authorization: MCPAuthorizationRuntimeConfig = field(default_factory=MCPAuthorizationRuntimeConfig)

    @property
    def transport_type(self) -> str:
        """返回当前服务器的传输类型。

        Returns:
            str: ``stdio``、``streamable_http``、``sse`` 或 ``unknown``。
        """

        if self.transport == "stdio" and self.command:
            return "stdio"
        if self.transport == "streamable_http" and self.url:
            return "streamable_http"
        if self.transport == "sse" and self.url:
            return "sse"
        return "unknown"

    def build_http_headers(self) -> dict[str, str]:
        """构建远程 HTTP 连接需要附加的请求头。

        Returns:
            dict[str, str]: 归一化后的请求头集合。
        """

        headers = {str(key): str(value) for key, value in self.headers.items()}
        if self.authorization.mode == "bearer" and self.authorization.bearer_token.strip():
            headers["Authorization"] = f"Bearer {self.authorization.bearer_token.strip()}"
        return headers


def build_mcp_client_runtime_config(mcp_config: "MCPConfig") -> MCPClientRuntimeConfig:
    """将官方 MCP 客户端配置转换为运行时结构。

    Args:
        mcp_config: 主程序中的 MCP 官方配置对象。

    Returns:
        MCPClientRuntimeConfig: MCP 客户端宿主能力运行时配置。
    """

    roots = [
        MCPRootRuntimeConfig(
            uri=root.uri.strip(),
            name=root.name.strip(),
        )
        for root in mcp_config.client.roots.items
        if root.enabled and root.uri.strip()
    ]

    return MCPClientRuntimeConfig(
        client_name=mcp_config.client.client_name.strip() or "MaiBot",
        client_version=mcp_config.client.client_version.strip() or "1.0.0",
        enable_roots=mcp_config.client.roots.enable and bool(roots),
        roots=roots,
        enable_sampling=mcp_config.client.sampling.enable,
        sampling_task_name=mcp_config.client.sampling.task_name.strip() or "planner",
        sampling_include_context_support=mcp_config.client.sampling.include_context_support,
        sampling_tool_support=mcp_config.client.sampling.tool_support,
        enable_elicitation=mcp_config.client.elicitation.enable,
        elicitation_allow_form=mcp_config.client.elicitation.allow_form,
        elicitation_allow_url=mcp_config.client.elicitation.allow_url,
    )


def build_mcp_server_runtime_configs(mcp_config: "MCPConfig") -> list[MCPServerRuntimeConfig]:
    """将官方 MCP 配置转换为运行时配置列表。

    Args:
        mcp_config: 主程序中的 MCP 官方配置对象。

    Returns:
        list[MCPServerRuntimeConfig]: 启用且配置完整的 MCP 服务器列表。
    """

    if not mcp_config.enable:
        return []

    runtime_configs: list[MCPServerRuntimeConfig] = []
    for server in mcp_config.servers:
        if not server.enabled:
            continue

        runtime_configs.append(
            MCPServerRuntimeConfig(
                name=server.name.strip(),
                transport=server.transport,
                command=server.command.strip(),
                args=[str(argument) for argument in server.args],
                env={str(key): str(value) for key, value in server.env.items()},
                url=server.url.strip(),
                headers={str(key): str(value) for key, value in server.headers.items()},
                http_timeout_seconds=float(server.http_timeout_seconds),
                read_timeout_seconds=float(server.read_timeout_seconds),
                authorization=MCPAuthorizationRuntimeConfig(
                    mode=server.authorization.mode,
                    bearer_token=server.authorization.bearer_token.strip(),
                ),
            )
        )

    return runtime_configs
