#!/usr/bin/env node
// ============================================================================
// CloseBot MCP Server — Main Entry Point
// Lazy-loaded tool groups, 6 rich UI tool apps, ~55 tools
// ============================================================================

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { CloseBotClient } from "./client.js";
import type { ToolDefinition, ToolResult } from "./types.js";

// ---------------------------------------------------------------------------
// Lazy-loaded module registry
// ---------------------------------------------------------------------------

interface ToolModule {
  tools: ToolDefinition[];
  handle: (
    client: CloseBotClient,
    name: string,
    args: Record<string, unknown>
  ) => Promise<ToolResult>;
}

interface LazyGroup {
  /** File path (relative) for dynamic import */
  path: string;
  /** Cached module after first load */
  module?: ToolModule;
  /** Tool metadata — populated eagerly, handler loaded lazily */
  toolNames: string[];
}

// Tool groups — we import metadata eagerly but handler code lazily
const groups: LazyGroup[] = [
  { path: "./tools/bot-management.js", toolNames: [] },
  { path: "./tools/source-management.js", toolNames: [] },
  { path: "./tools/lead-management.js", toolNames: [] },
  { path: "./tools/analytics.js", toolNames: [] },
  { path: "./tools/bot-testing.js", toolNames: [] },
  { path: "./tools/library.js", toolNames: [] },
  { path: "./tools/agency-billing.js", toolNames: [] },
  { path: "./tools/configuration.js", toolNames: [] },
  // Apps
  { path: "./apps/bot-dashboard.js", toolNames: [] },
  { path: "./apps/analytics-dashboard.js", toolNames: [] },
  { path: "./apps/test-console.js", toolNames: [] },
  { path: "./apps/lead-manager.js", toolNames: [] },
  { path: "./apps/library-manager.js", toolNames: [] },
  { path: "./apps/leaderboard.js", toolNames: [] },
];

// Map: toolName → group index (for fast dispatch)
const toolToGroup = new Map<string, number>();
// All tool definitions (populated on init)
let allTools: ToolDefinition[] = [];

async function loadGroupMetadata(): Promise<void> {
  const toolDefs: ToolDefinition[] = [];
  for (let i = 0; i < groups.length; i++) {
    const mod = (await import(groups[i].path)) as ToolModule;
    groups[i].module = mod;
    groups[i].toolNames = mod.tools.map((t) => t.name);
    for (const tool of mod.tools) {
      toolToGroup.set(tool.name, i);
      toolDefs.push(tool);
    }
  }
  allTools = toolDefs;
}

async function getHandler(
  toolName: string
): Promise<ToolModule["handle"] | null> {
  const idx = toolToGroup.get(toolName);
  if (idx === undefined) return null;
  const group = groups[idx];
  if (!group.module) {
    group.module = (await import(group.path)) as ToolModule;
  }
  return group.module.handle;
}

// ---------------------------------------------------------------------------
// Server setup
// ---------------------------------------------------------------------------

async function main(): Promise<void> {
  // Init client (validates API key)
  let client: CloseBotClient;
  try {
    client = new CloseBotClient();
  } catch (e) {
    console.error(
      (e as Error).message ||
        "Failed to initialize. Set CLOSEBOT_API_KEY env var."
    );
    process.exit(1);
  }

  // Load all tool metadata
  await loadGroupMetadata();

  const server = new Server(
    {
      name: "closebot-mcp",
      version: "1.0.0",
    },
    {
      capabilities: {
        tools: {},
      },
    }
  );

  // --- List Tools ---
  server.setRequestHandler(ListToolsRequestSchema, async () => {
    return {
      tools: allTools.map((t) => ({
        name: t.name,
        description: t.description,
        inputSchema: t.inputSchema,
      })),
    };
  });

  // --- Call Tool ---
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
    const { name, arguments: args } = request.params;
    const handler = await getHandler(name);
    if (!handler) {
      return {
        content: [{ type: "text" as const, text: `Unknown tool: ${name}` }],
        isError: true,
      } as Record<string, unknown>;
    }
    const result = await handler(client, name, (args as Record<string, unknown>) || {});
    return result as unknown as Record<string, unknown>;
  });

  // --- Connect stdio transport ---
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error(
    `CloseBot MCP server running — ${allTools.length} tools loaded across ${groups.length} modules`
  );
}

main().catch((err) => {
  console.error("Fatal error:", err);
  process.exit(1);
});
