// Calendly MCP Server

import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
  ListResourcesRequestSchema,
  ReadResourceRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';

import { CalendlyClient } from './clients/calendly.js';
import { createEventsTools } from './tools/events-tools.js';
import { createEventTypesTools } from './tools/event-types-tools.js';
import { createSchedulingTools } from './tools/scheduling-tools.js';
import { createUsersTools } from './tools/users-tools.js';
import { createOrganizationsTools } from './tools/organizations-tools.js';
import { createWebhooksTools } from './tools/webhooks-tools.js';

export function createCalendlyServer(apiKey: string) {
  const server = new Server(
    {
      name: 'calendly-mcp-server',
      version: '1.0.0',
    },
    {
      capabilities: {
        tools: {},
        resources: {},
      },
    }
  );

  // Initialize Calendly client
  const client = new CalendlyClient({
    apiKey,
  });

  // Collect all tools
  const allTools = {
    ...createEventsTools(client),
    ...createEventTypesTools(client),
    ...createSchedulingTools(client),
    ...createUsersTools(client),
    ...createOrganizationsTools(client),
    ...createWebhooksTools(client),
  };

  // List tools handler
  server.setRequestHandler(ListToolsRequestSchema, async () => {
    return {
      tools: Object.entries(allTools).map(([name, tool]) => ({
        name,
        description: tool.description,
        inputSchema: tool.parameters,
      })),
    };
  });

  // Call tool handler
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
    const toolName = request.params.name;
    const tool = allTools[toolName as keyof typeof allTools];

    if (!tool) {
      throw new Error(`Unknown tool: ${toolName}`);
    }

    try {
      return await tool.handler(request.params.arguments || {});
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : String(error);
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify({
              error: errorMessage,
              tool: toolName,
            }, null, 2),
          },
        ],
        isError: true,
      };
    }
  });

  // Resources - expose current user as a resource
  server.setRequestHandler(ListResourcesRequestSchema, async () => {
    return {
      resources: [
        {
          uri: 'calendly://user/me',
          name: 'Current User',
          description: 'Currently authenticated Calendly user',
          mimeType: 'application/json',
        },
      ],
    };
  });

  server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
    const uri = request.params.uri;

    if (uri === 'calendly://user/me') {
      const user = await client.getCurrentUser();
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(user, null, 2),
          },
        ],
      };
    }

    throw new Error(`Unknown resource: ${uri}`);
  });

  return server;
}

export async function runStdioServer(apiKey: string) {
  const server = createCalendlyServer(apiKey);
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error('Calendly MCP Server running on stdio');
}
