/**
 * MCP Bridge — converts MCP tools into Flynn's Tool interface.
 *
 * Each MCP tool is prefixed with "mcp:<serverName>:" to avoid
 * namespace collisions with builtin tools. When the tool is executed,
 * the bridge routes the call back to the originating McpClient.
 */

import type { Tool, ToolResult } from '../tools/types.js';
import type { McpClient } from './client.js';
import type { McpToolInfo } from './types.js';

/**
 * Create the prefixed tool name used in Flynn's tool registry.
 *
 * Example: MCP server "filesystem" with tool "read_file" -> "mcp:filesystem:read_file"
 */
export function mcpToolName(serverName: string, toolName: string): string {
  return `mcp:${serverName}:${toolName}`;
}

/**
 * Parse a prefixed tool name back into server + tool components.
 * Returns null if the name doesn't match the mcp: prefix pattern.
 */
export function parseMcpToolName(prefixedName: string): { serverName: string; toolName: string } | null {
  const match = prefixedName.match(/^mcp:([^:]+):(.+)$/);
  if (!match) {return null;}
  return { serverName: match[1], toolName: match[2] };
}

/**
 * Convert a single MCP tool into a Flynn Tool.
 *
 * The returned Tool's execute() calls back into the McpClient
 * to invoke the tool on the remote MCP server.
 */
export function bridgeMcpTool(client: McpClient, toolInfo: McpToolInfo): Tool {
  const prefixedName = mcpToolName(client.serverName, toolInfo.name);

  return {
    name: prefixedName,
    description: `[MCP:${client.serverName}] ${toolInfo.description}`,
    inputSchema: {
      type: 'object',
      properties: toolInfo.inputSchema.properties ?? {},
      required: toolInfo.inputSchema.required,
    },

    async execute(args: unknown): Promise<ToolResult> {
      try {
        const result = await client.callTool(
          toolInfo.name,
          (args ?? {}) as Record<string, unknown>,
        );

        return {
          success: !result.isError,
          output: result.content,
          error: result.isError ? result.content : undefined,
        };
      } catch (error) {
        return {
          success: false,
          output: '',
          error: error instanceof Error ? error.message : String(error),
        };
      }
    },
  };
}

/**
 * Bridge all tools from an MCP client into Flynn Tool objects.
 */
export function bridgeAllTools(client: McpClient): Tool[] {
  return client.tools.map((t) => bridgeMcpTool(client, t));
}
