/**
 * ExtensionExecutorPlugin 扩展插件执行器
 * 统一管理扩展插件（如 gate-trading）的工具，通过 ext_call 调用
 */

const { Plugin } = require('../src/core/plugin-base');
const { logger } = require('../src/utils/logger');
const { z } = require('zod');
const { zodSchemaToMarkdown } = require('@chnak/zod-to-markdown');

const log = logger.child('ExtensionExecutor');

class ExtensionExecutorPlugin extends Plugin {
  constructor(config = {}) {
    super();
    this.name = 'extension-executor';
    this.version = '1.0.0';
    this.description = '扩展插件执行器 - 统一管理扩展工具';
    this.priority = 10;
    this.system = true;

    this._framework = null;
    this._extensions = new Map();
  }

  install(framework) {
    this._framework = framework;

    // 监听插件加载事件，自动扫描插件的 this.tools
    framework.on('plugin:loaded', (plugin) => {
      this._scanPluginTools(plugin);
    });

    // 监听插件重载事件，重新扫描工具
    framework.on('plugin:reloaded', (plugin) => {
      this._rescanPluginTools(plugin);
    });

    // 监听框架就绪事件，刷新所有动态注册的工具（确保在 install() 中通过 registerTool() 注册的工具能被扫描到）
    framework.on('framework:ready', () => {
      log.debug('Framework ready, rescanning all plugin tools...');
      const plugins = framework.pluginManager.getAll();
      for (const { instance: plugin } of plugins) {
        this._scanPluginTools(plugin);
      }
      // 刷新所有 Agent 的扩展提示词
      this._refreshAllAgentsExtPrompt(framework);
    });

    return this;
  }

  /**
   * 扫描插件的 this.tools 并注册到扩展系统
   */
  _scanPluginTools(plugin) {
    if (!plugin || !plugin.tools || typeof plugin.tools !== 'object') {
      return;
    }

    const pluginName = plugin.name;
    if (!pluginName) return;

    // 获取插件信息
    const pluginInfo = {
      name: plugin.name,
      description: plugin.description || '',
      version: plugin.version || '1.0.0',
    };

    // 遍历插件的所有工具
    for (const [toolName, toolDef] of Object.entries(plugin.tools)) {
      if (!toolDef || typeof toolDef !== 'object') continue;

      this.registerTool(pluginName, pluginInfo, {
        name: toolName,
        description: toolDef.description || '',
        inputSchema: toolDef.inputSchema,
        execute: toolDef.execute,
      });
    }

    log.debug(` Scanned ${Object.keys(plugin.tools).length} tools from plugin '${pluginName}'`);

    // 刷新所有 Agent 的扩展提示词
    if (this._framework && this._framework._ready) {
      this._refreshAllAgentsExtPrompt(this._framework);
    }
  }

  /**
   * 重新扫描插件的工具（用于热重载）
   */
  _rescanPluginTools(plugin) {
    if (!plugin || !plugin.tools || typeof plugin.tools !== 'object') {
      return;
    }

    const pluginName = plugin.name;
    if (!pluginName) return;

    // 先移除旧工具
    if (this._extensions.has(pluginName)) {
      const ext = this._extensions.get(pluginName);
      for (const tool of ext.tools || []) {
        // 从 toolRouter 移除
        if (this._framework?.toolRouter) {
          this._framework.toolRouter.unregister(`ext_${tool.name}`);
        }
      }
      this._extensions.delete(pluginName);
    }

    // 重新扫描工具
    this._scanPluginTools(plugin);
    log.info(` Rescanned tools from plugin '${pluginName}'`);
  }

  async start(framework) {
    // 扫描所有已加载插件的 tools
    const plugins = framework.pluginManager.getAll();
    for (const { instance: plugin } of plugins) {
      this._scanPluginTools(plugin);
    }

    // 获取 MCP executor 引用（用于 ext_call 统一路由）
    this._mcpExecutor = framework.pluginManager?.get('mcp') || null;

    framework.registerTool({
      name: 'ext_call',
      description: '调用扩展插件的工具（包括 MCP 服务器工具）',
      inputSchema: z.object({
        plugin: z.string().describe('插件名称（如 email, gate-trading, mcp）'),
        tool: z.string().describe('工具名称'),
        args: z.record(z.any()).optional().describe('工具参数'),
      }),
      execute: async (args) => {
        const { plugin, tool, args: toolArgs = {} } = args;
        log.info(` ext_call: plugin=${plugin}, tool=${tool}, args=${JSON.stringify(toolArgs)}`);

        // MCP 服务器工具（已注册为 server_toolname 格式，如 github_search）
        if (plugin === 'mcp' && this._mcpExecutor) {
          const mcpToolDef = this._mcpExecutor.tools?.[tool];
          if (mcpToolDef && mcpToolDef.execute) {
            log.info(` ext_call [MCP]: tool=${tool}`);
            return await mcpToolDef.execute(toolArgs || {});
          }
          return { success: false, error: `MCP tool '${tool}' not found` };
        }

        const ext = this._extensions.get(plugin);
        if (!ext) {
          // 触发错误事件
          framework.emit('tool:error', {
            name: `${plugin}:${tool}`,
            args: toolArgs,
            error: `扩展插件 '${plugin}' 不存在`,
            source: 'extension'
          });
          return { success: false, error: `扩展插件 '${plugin}' 不存在` };
        }

        const toolDef = ext.tools.find((t) => t.name === tool);
        if (!toolDef) {
          // 触发错误事件
          framework.emit('tool:error', {
            name: `${plugin}:${tool}`,
            args: toolArgs,
            error: `扩展工具 '${tool}' 不存在`,
            source: 'extension'
          });
          return { success: false, error: `扩展工具 '${tool}' 不存在` };
        }

        try {
          // 触发扩展工具开始事件
          framework.emit('tool:call', {
            name: `${plugin}:${tool}`,
            args: toolArgs,
            source: 'extension'
          });
          framework.emit('tool-call', {
            name: `${plugin}:${tool}`,
            args: toolArgs,
            source: 'extension'
          });

          // 统一 execute 签名为 (args, framework)
          const result = await toolDef.execute(toolArgs, framework);

          // 检查结果是否为错误
          if (result && result.success === false && result.error) {
            // 触发扩展工具错误事件
            framework.emit('tool:error', {
              name: `${plugin}:${tool}`,
              args: toolArgs,
              error: result.error,
              source: 'extension'
            });
            return result;
          }

          // 触发扩展工具完成事件
          framework.emit('tool:result', {
            name: `${plugin}:${tool}`,
            args: toolArgs,
            result,
            source: 'extension'
          });

          return { success: true, result };
        } catch (err) {
          log.error(` Tool '${tool}' failed:`, err.message);

          // 触发扩展工具错误事件
          framework.emit('tool:error', {
            name: `${plugin}:${tool}`,
            args: toolArgs,
            error: err.message,
            source: 'extension'
          });

          return { success: false, error: err.message };
        }
      },
    });

    framework.registerTool({
      name: 'ext_list',
      description: '列出所有可用的扩展插件及其工具',
      inputSchema: z.object({}),
      execute: async () => {
        const extensions = [];
        for (const [name, ext] of this._extensions) {
          extensions.push({
            name,
            description: ext.description,
            version: ext.version,
            tools: ext.tools.map((t) => ({ name: t.name, description: t.description })),
          });
        }
        return { success: true, extensions };
      },
    });

    framework.registerTool({
      name: 'ext_schema',
      description: '查询扩展工具的调用参数结构',
      inputSchema: z.object({
        plugin: z.string().describe('扩展插件名称'),
        tool: z.string().describe('工具名称'),
      }),
      execute: async (args) => {
        const { plugin, tool } = args;
        const ext = this._extensions.get(plugin);
        if (!ext) {
          return { success: false, error: `扩展插件 '${plugin}' 不存在` };
        }

        const toolDef = ext.tools.find((t) => t.name === tool);
        if (!toolDef) {
          return { success: false, error: `扩展工具 '${tool}' 不存在` };
        }

        return {
          success: true,
          result: {
            plugin,
            tool,
            description: toolDef.description,
            inputSchema: toolDef.inputSchema,
          },
        };
      },
    });

    framework.on('agent:created', (agent) => {
      this._refreshAgentExtPrompt(agent);
    });

    if (framework._ready) {
      this._refreshAllAgentsExtPrompt(framework);
    } else {
      framework.once('framework:ready', () => {
        this._refreshAllAgentsExtPrompt(framework);
      });
    }

    return this;
  }

  registerTool(pluginName, pluginInfo, toolDef) {
    if (!this._extensions.has(pluginName)) {
      this._extensions.set(pluginName, {
        name: pluginInfo.name || pluginName,
        description: pluginInfo.description || '',
        version: pluginInfo.version || '1.0.0',
        tools: [],
      });
    }

    const ext = this._extensions.get(pluginName);
    const existingIdx = ext.tools.findIndex((t) => t.name === toolDef.name);
    if (existingIdx >= 0) {
      // 更新已存在的工具
      ext.tools[existingIdx] = {
        name: toolDef.name,
        description: toolDef.description || '',
        inputSchema: toolDef.inputSchema,
        execute: toolDef.execute,
      };
    } else {
      // 添加新工具
      ext.tools.push({
        name: toolDef.name,
        description: toolDef.description || '',
        inputSchema: toolDef.inputSchema,
        execute: toolDef.execute,
      });
    }

    log.debug(` Registered tool '${toolDef.name}' for extension '${pluginName}'`);

    // 刷新所有 Agent 的扩展提示词
    if (this._framework && this._framework._ready) {
      this._refreshAllAgentsExtPrompt(this._framework);
    }
  }

  _refreshAllAgentsExtPrompt(framework) {
    const visited = new Set();
    const traverse = (agent) => {
      if (!agent || visited.has(agent)) return;
      visited.add(agent);
      this._refreshAgentExtPrompt(agent);
      const subAgents = agent.getSubAgents?.() || agent._subAgents || new Map();
      for (const [, subAgentInfo] of subAgents) {
        traverse(subAgentInfo.agent);
      }
    };
    for (const agent of framework._agents || []) {
      traverse(agent);
    }
  }

  _refreshAgentExtPrompt(agent) {
    const extDesc = this._buildExtensionsDescription();
    if (!extDesc) return;

    const existingPrompt = agent._originalPrompt || '';

    // 如果已有 [Extensions] 部分，替换它
    const extStartIdx = existingPrompt.indexOf('【Extensions】');
    if (extStartIdx !== -1) {
      const extEndMarker = '\n\n【';
      let extEndIdx = existingPrompt.indexOf(extEndMarker, extStartIdx);
      if (extEndIdx === -1) {
        // 尝试其他标记
        extEndIdx = existingPrompt.indexOf('\n\n---\n\n', extStartIdx);
      }
      if (extEndIdx === -1) {
        extEndIdx = existingPrompt.length;
      } else {
        extEndIdx += extEndMarker.length;
      }
      const newPrompt = existingPrompt.substring(0, extStartIdx) + extDesc + existingPrompt.substring(extEndIdx);
      agent.setSystemPrompt(newPrompt);
    } else {
      agent.setSystemPrompt(existingPrompt + '\n\n' + extDesc);
    }
  }

  _buildExtensionsDescription() {
    let desc = '';

    // 1. 扩展插件工具（包括 MCP，已通过 this.tools 注册为 server_toolname 格式）
    if (this._extensions.size > 0 || (this._mcpExecutor && Object.keys(this._mcpExecutor.tools || {}).length > 0)) {
      desc += '## 【Extensions】扩展插件工具\n\n';
      desc += '你可以通过 `ext_call` 工具调用以下扩展插件的功能。\n\n';

      for (const [name, ext] of this._extensions) {
        desc += `### ${ext.name || name}\n\n`;
        desc += `${ext.description || ''}\n\n`;
        for (const tool of ext.tools) {
          desc += `- **${tool.name}**: ${tool.description || '无描述'}\n`;
          // 添加参数描述
          if (tool.inputSchema) {
            try {
              if (typeof tool.inputSchema.toJSON === 'function') {
                desc += `**参数:**\n\n`;
                desc += zodSchemaToMarkdown(tool.inputSchema) + '\n\n';
              } else if (tool.inputSchema.properties) {
                // JSON Schema 格式
                desc += `**参数:**\n\n`;
                desc += zodSchemaToMarkdown(tool.inputSchema) + '\n\n';
              }
            } catch (e) {
              // 忽略转换错误
            }
          }
        }
        desc += '\n';
      }

      // MCP 服务器工具（已注册为 server_toolname 格式）
      if (this._mcpExecutor && Object.keys(this._mcpExecutor.tools || {}).length > 0) {
        desc += '### mcp (MCP 服务器工具)\n\n';
        desc += 'MCP 服务器工具已注册为 `服务器_工具名` 格式（如 github_search）。\n\n';
        for (const [toolName, toolDef] of Object.entries(this._mcpExecutor.tools)) {
          desc += `- **${toolName}**: ${toolDef.description || '无描述'}\n`;
          // 添加参数描述
          if (toolDef.inputSchema) {
            try {
              const schemaResult = this._convertSchemaToMarkdown(toolDef.inputSchema);
              if (schemaResult) {
                desc += `**参数:**\n\n`;
                desc += schemaResult + '\n\n';
              }
            } catch (e) {
              // 忽略转换错误
            }
          }
        }
        desc += '\n';
      }
    }

    if (!desc) {
      return '';
    }

    desc += '**统一调用格式:**\n';
    desc += '```\next_call({ plugin: "插件名", tool: "工具名", args: {参数} })\n';
    desc += '```\n';
    return desc.trim();
  }

  /**
   * 将 Schema 转换为 Markdown 格式的参数描述
   * 支持 Zod schema 和 JSON Schema
   */
  _convertSchemaToMarkdown(inputSchema) {
    if (!inputSchema) return null;

    // 提取实际 schema（处理 { jsonSchema: {...} } 或 { inputSchema: {...} } 格式）
    let schema = inputSchema;
    if (inputSchema.jsonSchema) schema = inputSchema.jsonSchema;
    if (inputSchema.inputSchema) schema = inputSchema.inputSchema;

    // 检查是否是 Zod schema
    const isZodSchema = typeof schema.shape === 'function' || (schema._def && schema._def.typeName);
    if (isZodSchema) {
      // Zod schema 直接转换
      return zodSchemaToMarkdown(schema);
    }

    // JSON Schema 转换为 Zod 再转换
    if (schema.properties) {
      const zodSchema = this._jsonSchemaToZod(schema);
      if (zodSchema) {
        return zodSchemaToMarkdown(zodSchema);
      }
    }

    // 如果都没有，回退到简单格式
    return this._schemaToMarkdown(schema);
  }

  /**
   * 将 JSON Schema 转换为 Zod schema
   */
  _jsonSchemaToZod(jsonSchema) {
    if (!jsonSchema || !jsonSchema.properties) return null;

    try {
      const shape = {};
      const properties = jsonSchema.properties;
      const required = jsonSchema.required || [];

      for (const [key, prop] of Object.entries(properties)) {
        shape[key] = this._jsonSchemaPropToZod(prop, required.includes(key));
      }

      return z.object(shape);
    } catch (e) {
      return null;
    }
  }

  /**
   * 将 JSON Schema 属性转换为 Zod 类型
   */
  _jsonSchemaPropToZod(prop, isRequired) {
    if (prop.enum) {
      let zodType = z.string().enum(prop.enum);
      if (prop.nullable) zodType = zodType.nullable();
      return isRequired ? zodType : zodType.optional();
    }

    const type = prop.type || 'string';
    switch (type) {
      case 'string':
        return isRequired ? z.string() : z.string().optional();
      case 'number':
      case 'integer':
        return isRequired ? z.number() : z.number().optional();
      case 'boolean':
        return isRequired ? z.boolean() : z.boolean().optional();
      case 'array':
        return isRequired ? z.array(z.any()) : z.array(z.any()).optional();
      case 'object':
        if (prop.properties) {
          const nested = {};
          for (const [k, v] of Object.entries(prop.properties)) {
            nested[k] = this._jsonSchemaPropToZod(v, prop.required?.includes(k) || false);
          }
          return isRequired ? z.object(nested) : z.object(nested).optional();
        }
        return isRequired ? z.record(z.any()) : z.record(z.any()).optional();
      default:
        return isRequired ? z.any() : z.any().optional();
    }
  }

  /**
   * 将 JSON Schema 转换为 Markdown（简单格式）
   */
  _schemaToMarkdown(schema) {
    if (!schema || !schema.properties) return null;

    const props = schema.properties || {};
    const required = schema.required || [];
    let md = '';

    for (const [key, prop] of Object.entries(props)) {
      const isRequired = required.includes(key);
      const type = prop.type || 'any';
      const descText = prop.description || '';
      md += `- \`${key}\`${isRequired ? ' (必填)' : ''}: ${type} ${descText}\n`;
    }
    return md || null;
  }

  getExtensions() {
    return Array.from(this._extensions.entries()).map(([name, ext]) => ({
      name,
      description: ext.description,
      version: ext.version,
      tools: ext.tools,
    }));
  }

  async reload(framework) {
    this._framework = framework;
    // 重新扫描所有已加载插件的 tools
    this._extensions.clear();
    const plugins = framework.pluginManager.getAll();
    for (const { instance: plugin } of plugins) {
      this._scanPluginTools(plugin);
    }
    // 重新获取 MCP executor 引用
    this._mcpExecutor = framework.pluginManager?.get('mcp') || null;
    // 刷新所有 Agent 的扩展提示词
    this._refreshAllAgentsExtPrompt(framework);

    // 同时重载 MCP 配置
    await this._reloadMCPConfig(framework);
  }

  // 重载 MCP 配置
  async _reloadMCPConfig(framework) {
    const fs = require('fs');
    const path = require('path');
    const mcpExecutor = framework.pluginManager?.get('mcp');
    if (!mcpExecutor) return;

    try {
      const configPath = path.resolve('.agent/mcp_config.json');
      if (fs.existsSync(configPath)) {
        const configContent = fs.readFileSync(configPath, 'utf8');
        const config = JSON.parse(configContent);
        await mcpExecutor.reloadConfig(config);
        logger.info(' MCP config reloaded via extension-executor');
      }
    } catch (err) {
      logger.warn(' Failed to reload MCP config:', err.message);
    }
  }

  async uninstall(framework) {
    this._extensions.clear();
    this._framework = null;
  }
}

module.exports = ExtensionExecutorPlugin
