/**
 * MCP Manager
 * 管理多个 MCP 服务器的生命周期
 */

import { EventEmitter } from 'events';
import type {
  MCPConfig,
  MCPServerConfig,
  MCPTool,
  MCPServerStatus,
  MCPToolCallResult,
  MCPManagerEvents,
} from './types.js';
import { MCPClient } from './client.js';
import { getEnabledServers, isToolEnabled } from './config.js';

/**
 * MCP Manager 类
 * 负责管理所有 MCP 服务器连接
 */
export class MCPManager extends EventEmitter {
  private clients: Map<string, MCPClient> = new Map();
  private config: MCPConfig = {};
  private initialized = false;

  /**
   * 初始化所有已启用的服务器
   */
  async initialize(config: MCPConfig): Promise<void> {
    if (this.initialized) {
      await this.shutdown();
    }

    this.config = config;
    const servers = getEnabledServers(config);

    // 并行连接所有服务器
    const connectPromises = servers.map(async ({ name, config: serverConfig }) => {
      try {
        await this.connectServer(name, serverConfig);
      } catch (error) {
        console.error(
          `[MCP] Failed to connect to ${name}:`,
          error instanceof Error ? error.message : String(error)
        );
      }
    });

    await Promise.all(connectPromises);
    this.initialized = true;
  }

  /**
   * 连接单个服务器
   */
  private async connectServer(
    name: string,
    config: MCPServerConfig
  ): Promise<void> {
    const client = new MCPClient(name, config);

    try {
      await client.connect();
      this.clients.set(name, client);
      this.emit('server:connected', name);
    } catch (error) {
      this.emit('server:error', name, error instanceof Error ? error : new Error(String(error)));
      throw error;
    }
  }

  /**
   * 关闭所有连接
   */
  async shutdown(): Promise<void> {
    const disconnectPromises = Array.from(this.clients.entries()).map(
      async ([name, client]) => {
        try {
          await client.disconnect();
          this.emit('server:disconnected', name);
        } catch (error) {
          console.error(`[MCP] Error disconnecting ${name}:`, error);
        }
      }
    );

    await Promise.all(disconnectPromises);
    this.clients.clear();
    this.initialized = false;
  }

  /**
   * 重连指定服务器
   */
  async reconnect(serverName: string): Promise<void> {
    const existingClient = this.clients.get(serverName);
    if (existingClient) {
      await existingClient.disconnect();
      this.clients.delete(serverName);
      this.emit('server:disconnected', serverName);
    }

    const serverConfig = this.config.mcp?.[serverName];
    if (!serverConfig) {
      throw new Error(`Server not found: ${serverName}`);
    }

    await this.connectServer(serverName, serverConfig);
    this.emit('tools:changed');
  }

  /**
   * 获取所有可用工具
   */
  getTools(): MCPTool[] {
    const allTools: MCPTool[] = [];

    for (const client of this.clients.values()) {
      const status = client.getStatus();
      if (status.status === 'connected') {
        const tools = client.getTools();
        // 根据配置过滤工具
        for (const tool of tools) {
          if (isToolEnabled(tool.name, this.config.tools)) {
            allTools.push(tool);
          }
        }
      }
    }

    return allTools;
  }

  /**
   * 获取指定工具
   */
  getTool(name: string): MCPTool | undefined {
    for (const client of this.clients.values()) {
      const tools = client.getTools();
      const tool = tools.find((t) => t.name === name);
      if (tool && isToolEnabled(tool.name, this.config.tools)) {
        return tool;
      }
    }
    return undefined;
  }

  /**
   * 调用工具
   */
  async callTool(
    name: string,
    args: Record<string, unknown>
  ): Promise<MCPToolCallResult> {
    // 从工具名中解析服务器名
    const dashIndex = name.indexOf('-');
    if (dashIndex === -1) {
      return {
        success: false,
        content: [{ type: 'text', text: `Invalid tool name format: ${name}` }],
        isError: true,
      };
    }

    const serverName = name.substring(0, dashIndex);
    const client = this.clients.get(serverName);

    if (!client) {
      return {
        success: false,
        content: [{ type: 'text', text: `Server not connected: ${serverName}` }],
        isError: true,
      };
    }

    // 检查工具是否启用
    if (!isToolEnabled(name, this.config.tools)) {
      return {
        success: false,
        content: [{ type: 'text', text: `Tool is disabled: ${name}` }],
        isError: true,
      };
    }

    return await client.callTool(name, args);
  }

  /**
   * 获取所有服务器状态
   */
  getServerStatuses(): MCPServerStatus[] {
    const statuses: MCPServerStatus[] = [];

    // 已连接的服务器
    for (const client of this.clients.values()) {
      statuses.push(client.getStatus());
    }

    // 未连接但已配置的服务器
    if (this.config.mcp) {
      for (const [name, serverConfig] of Object.entries(this.config.mcp)) {
        if (!this.clients.has(name)) {
          statuses.push({
            name,
            type: serverConfig.type,
            status: serverConfig.enabled === false ? 'disabled' : 'disconnected',
            toolCount: 0,
          });
        }
      }
    }

    return statuses;
  }

  /**
   * 获取指定服务器状态
   */
  getServerStatus(name: string): MCPServerStatus | undefined {
    const client = this.clients.get(name);
    if (client) {
      return client.getStatus();
    }

    const serverConfig = this.config.mcp?.[name];
    if (serverConfig) {
      return {
        name,
        type: serverConfig.type,
        status: serverConfig.enabled === false ? 'disabled' : 'disconnected',
        toolCount: 0,
      };
    }

    return undefined;
  }

  /**
   * 启用/禁用服务器
   */
  async setServerEnabled(serverName: string, enabled: boolean): Promise<void> {
    const serverConfig = this.config.mcp?.[serverName];
    if (!serverConfig) {
      throw new Error(`Server not found: ${serverName}`);
    }

    if (enabled) {
      // 启用并连接
      serverConfig.enabled = true;
      if (!this.clients.has(serverName)) {
        await this.connectServer(serverName, serverConfig);
        this.emit('tools:changed');
      }
    } else {
      // 禁用并断开
      serverConfig.enabled = false;
      const client = this.clients.get(serverName);
      if (client) {
        await client.disconnect();
        this.clients.delete(serverName);
        this.emit('server:disconnected', serverName);
        this.emit('tools:changed');
      }
    }
  }

  /**
   * 获取客户端实例（用于测试）
   */
  getClient(name: string): MCPClient | undefined {
    return this.clients.get(name);
  }

  /**
   * 是否已初始化
   */
  isInitialized(): boolean {
    return this.initialized;
  }

  // 类型安全的事件方法
  override on<K extends keyof MCPManagerEvents>(
    event: K,
    listener: MCPManagerEvents[K]
  ): this {
    return super.on(event, listener);
  }

  override emit<K extends keyof MCPManagerEvents>(
    event: K,
    ...args: Parameters<MCPManagerEvents[K]>
  ): boolean {
    return super.emit(event, ...args);
  }
}

// 单例实例
let mcpManager: MCPManager | null = null;

/**
 * 获取 MCP Manager 单例
 */
export function getMCPManager(): MCPManager {
  if (!mcpManager) {
    mcpManager = new MCPManager();
  }
  return mcpManager;
}

/**
 * 重置 MCP Manager（用于测试）
 */
export function resetMCPManager(): void {
  if (mcpManager) {
    mcpManager.shutdown().catch(console.error);
    mcpManager = null;
  }
}
