"""SSH MCP Server - 通过 MCP 协议暴露 SSH 功能"""
import asyncio
import json
import logging
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent

from .config import ConfigManager
from .ssh_manager import SSHManager

logger = logging.getLogger(__name__)


def create_mcp_server(config_manager: ConfigManager, ssh_manager: SSHManager) -> Server:
    server = Server("ssh-mcp")

    @server.list_tools()
    async def list_tools() -> list[Tool]:
        return [
            Tool(
                name="list_servers",
                description="获取当前选中的 SSH 服务器（在 GUI 中设置）",
                inputSchema={
                    "type": "object",
                    "properties": {},
                },
            ),
            Tool(
                name="connect",
                description="连接到指定的 SSH 服务器。可通过 server_id 或 server_name 指定。",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "server_id": {
                            "type": "string",
                            "description": "服务器 ID",
                        },
                        "server_name": {
                            "type": "string",
                            "description": "服务器名称（如果不提供 server_id）",
                        },
                    },
                },
            ),
            Tool(
                name="disconnect",
                description="断开当前 SSH 连接",
                inputSchema={
                    "type": "object",
                    "properties": {},
                },
            ),
            Tool(
                name="get_status",
                description="获取当前 SSH 连接状态",
                inputSchema={
                    "type": "object",
                    "properties": {},
                },
            ),
            Tool(
                name="exec_command",
                description="在远程服务器上执行命令",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "command": {
                            "type": "string",
                            "description": "要执行的命令",
                        },
                        "timeout": {
                            "type": "integer",
                            "description": "超时时间（秒），默认 30",
                            "default": 30,
                        },
                    },
                    "required": ["command"],
                },
            ),
            Tool(
                name="upload_file",
                description="上传本地文件到远程服务器",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "local_path": {
                            "type": "string",
                            "description": "本地文件路径",
                        },
                        "remote_path": {
                            "type": "string",
                            "description": "远程文件路径",
                        },
                    },
                    "required": ["local_path", "remote_path"],
                },
            ),
            Tool(
                name="write_remote_file",
                description="将文本内容直接写入远程服务器文件",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "content": {
                            "type": "string",
                            "description": "要写入的文本内容",
                        },
                        "remote_path": {
                            "type": "string",
                            "description": "远程文件路径",
                        },
                    },
                    "required": ["content", "remote_path"],
                },
            ),
            Tool(
                name="read_remote_file",
                description="读取远程服务器上的文件内容",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "remote_path": {
                            "type": "string",
                            "description": "远程文件路径",
                        },
                    },
                    "required": ["remote_path"],
                },
            ),
            Tool(
                name="download_file",
                description="从远程服务器下载文件到本地",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "remote_path": {
                            "type": "string",
                            "description": "远程文件路径",
                        },
                        "local_path": {
                            "type": "string",
                            "description": "本地保存路径",
                        },
                    },
                    "required": ["remote_path", "local_path"],
                },
            ),
            Tool(
                name="list_remote_dir",
                description="列出远程目录内容",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "path": {
                            "type": "string",
                            "description": "远程目录路径，默认为当前目录",
                            "default": ".",
                        },
                    },
                },
            ),
        ]

    @server.call_tool()
    async def call_tool(name: str, arguments: dict) -> list[TextContent]:
        try:
            result = await asyncio.to_thread(
                _handle_tool,
                name,
                arguments,
                config_manager,
                ssh_manager,
            )
            return [TextContent(type="text", text=result)]
        except Exception as e:
            logger.error(f"Tool {name} error: {e}")
            return [TextContent(type="text", text=f"错误: {str(e)}")]

    return server


def _auto_sync_active(config_manager: ConfigManager, ssh_manager: SSHManager):
    """检查 GUI 选中的活动服务器是否变化，自动切换连接"""
    config_manager.load()
    active_id = config_manager.get_active_server_id()
    if not active_id:
        return
    current = ssh_manager.current_server
    if current and current.id == active_id:
        return  # 没变化
    active_srv = config_manager.get_server(active_id)
    if active_srv:
        try:
            ssh_manager.connect(active_id)
            logger.info(f"自动切换到活动服务器: {active_srv.name} ({active_srv.host})")
        except Exception as e:
            logger.warning(f"自动切换活动服务器失败: {e}")


def _handle_tool(name: str, arguments: dict, config_manager: ConfigManager, ssh_manager: SSHManager) -> str:
    # 每次调用工具前，自动感知 GUI 选中的服务器是否变化
    _auto_sync_active(config_manager, ssh_manager)

    if name == "list_servers":
        config_manager.load()
        active = config_manager.get_active_server()
        if not active:
            return "没有选中的服务器。请先运行 sshgui 并选择一个服务器。"
        server_info = {
            "id": active.id,
            "name": active.name,
            "host": active.host,
            "port": active.port,
            "username": active.username,
            "auth_type": active.auth_type,
        }
        return json.dumps(server_info, indent=2, ensure_ascii=False)

    elif name == "connect":
        config_manager.load()
        server_id = arguments.get("server_id")
        server_name = arguments.get("server_name")
        if not server_id and server_name:
            server = config_manager.get_server_by_name(server_name)
            if server:
                server_id = server.id
            else:
                return f"找不到名为 '{server_name}' 的服务器"
        if not server_id:
            return "请提供 server_id 或 server_name"
        return ssh_manager.connect(server_id)

    elif name == "disconnect":
        return ssh_manager.disconnect()

    elif name == "get_status":
        status = ssh_manager.get_status()
        return json.dumps(status, indent=2, ensure_ascii=False)

    elif name == "exec_command":
        command = arguments.get("command", "")
        timeout = arguments.get("timeout", 30)
        result = ssh_manager.exec_command(command, timeout=timeout)
        output = ""
        if result["stdout"]:
            output += f"[STDOUT]\n{result['stdout']}\n"
        if result["stderr"]:
            output += f"[STDERR]\n{result['stderr']}\n"
        output += f"[EXIT CODE] {result['exit_code']}"
        return output

    elif name == "upload_file":
        return ssh_manager.upload_file(arguments["local_path"], arguments["remote_path"])

    elif name == "write_remote_file":
        return ssh_manager.upload_content(arguments["content"], arguments["remote_path"])

    elif name == "read_remote_file":
        return ssh_manager.read_file(arguments["remote_path"])

    elif name == "download_file":
        return ssh_manager.download_file(arguments["remote_path"], arguments["local_path"])

    elif name == "list_remote_dir":
        path = arguments.get("path", ".")
        items = ssh_manager.list_dir(path)
        return json.dumps(items, indent=2, ensure_ascii=False)

    else:
        return f"未知工具: {name}"


async def run_mcp_server(config_manager: ConfigManager, ssh_manager: SSHManager):
    server = create_mcp_server(config_manager, ssh_manager)
    async with stdio_server() as (read_stream, write_stream):
        await server.run(read_stream, write_stream, server.create_initialization_options())
