import {
  Controller,
  Get,
  Post,
  Delete,
  Param,
  Body,
  NotFoundException,
  BadRequestException,
} from "@nestjs/common";
import { McpHubService } from "./mcp-hub.service";
import { ToolRegistryService } from "./tool-registry.service";
import { RegisterServerDto } from "./dto";
import type { McpServer, McpTool } from "./interfaces";

/**
 * Controller for MCP server and tool management
 */
@Controller("mcp")
export class McpController {
  constructor(
    private readonly mcpHub: McpHubService,
    private readonly toolRegistry: ToolRegistryService
  ) {}

  /**
   * List all registered MCP servers
   */
  @Get("servers")
  listServers(): McpServer[] {
    return this.mcpHub.listServers();
  }

  /**
   * Register a new MCP server
   */
  @Post("servers")
  async registerServer(@Body() dto: RegisterServerDto): Promise<void> {
    await this.mcpHub.registerServer(dto);
  }

  /**
   * Start an MCP server
   */
  @Post("servers/:id/start")
  async startServer(@Param("id") id: string): Promise<void> {
    await this.mcpHub.startServer(id);
  }

  /**
   * Stop an MCP server
   */
  @Post("servers/:id/stop")
  async stopServer(@Param("id") id: string): Promise<void> {
    await this.mcpHub.stopServer(id);
  }

  /**
   * Unregister an MCP server
   */
  @Delete("servers/:id")
  async unregisterServer(@Param("id") id: string): Promise<void> {
    const server = this.mcpHub.getServerStatus(id);
    if (!server) {
      throw new NotFoundException(`Server ${id} not found`);
    }

    await this.mcpHub.unregisterServer(id);
  }

  /**
   * List all available tools
   */
  @Get("tools")
  listTools(): McpTool[] {
    return this.toolRegistry.listTools();
  }

  /**
   * Get a specific tool by name
   */
  @Get("tools/:name")
  getTool(@Param("name") name: string): McpTool {
    const tool = this.toolRegistry.getTool(name);
    if (!tool) {
      throw new NotFoundException(`Tool ${name} not found`);
    }
    return tool;
  }

  /**
   * Invoke a tool
   */
  @Post("tools/:name/invoke")
  async invokeTool(@Param("name") name: string, @Body() input: unknown): Promise<unknown> {
    const tool = this.toolRegistry.getTool(name);
    if (!tool) {
      throw new NotFoundException(`Tool ${name} not found`);
    }

    const requestId = Math.floor(Math.random() * 1000000);
    const response = await this.mcpHub.sendRequest(tool.serverId, {
      jsonrpc: "2.0",
      id: requestId,
      method: "tools/call",
      params: {
        name: tool.name,
        arguments: input,
      },
    });

    if (response.error) {
      throw new BadRequestException(response.error.message);
    }

    return response.result;
  }
}
