/**
 * Monday.com MCP Server
 * Lazy-loaded tools for Monday.com GraphQL API
 */

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
  Tool,
} from "@modelcontextprotocol/sdk/types.js";
import { MondayClient } from "./clients/monday.js";

export class MondayMCPServer {
  private server: Server;
  private client: MondayClient;

  constructor(apiKey: string) {
    this.client = new MondayClient(apiKey);
    this.server = new Server(
      {
        name: "@mcpengine/monday",
        version: "1.0.0",
      },
      {
        capabilities: {
          tools: {},
        },
      }
    );

    this.setupHandlers();
  }

  private setupHandlers(): void {
    // List all available tools
    this.server.setRequestHandler(ListToolsRequestSchema, async () => {
      return {
        tools: this.getTools(),
      };
    });

    // Handle tool calls
    this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
      const { name, arguments: args } = request.params;

      try {
        let result: any;

        switch (name) {
          // Board tools
          case "get_boards":
            result = await this.client.getBoards((args || {}) as any);
            break;
          case "get_board":
            result = await this.client.getBoard((args?.board_id as string) || "");
            break;
          case "create_board":
            result = await this.client.createBoard((args || {}) as any);
            break;

          // Item tools
          case "get_items":
            result = await this.client.getItems(
              (args?.board_id as string) || "",
              (args || {}) as any
            );
            break;
          case "get_item":
            result = await this.client.getItem((args?.item_id as string) || "");
            break;
          case "create_item":
            result = await this.client.createItem((args || {}) as any);
            break;
          case "change_column_value":
            result = await this.client.changeColumnValue((args || {}) as any);
            break;

          // Group tools
          case "create_group":
            result = await this.client.createGroup((args || {}) as any);
            break;

          // Update tools
          case "get_updates":
            result = await this.client.getUpdates(
              (args?.item_id as string) || "",
              args?.limit as number | undefined
            );
            break;
          case "create_update":
            result = await this.client.createUpdate((args || {}) as any);
            break;

          // User, team, workspace tools
          case "get_users":
            result = await this.client.getUsers(args?.limit as number | undefined);
            break;
          case "get_teams":
            result = await this.client.getTeams(args?.limit as number | undefined);
            break;
          case "get_workspaces":
            result = await this.client.getWorkspaces(
              args?.limit as number | undefined
            );
            break;

          // Webhook tools
          case "create_webhook":
            result = await this.client.createWebhook((args || {}) as any);
            break;
          case "delete_webhook":
            result = await this.client.deleteWebhook((args?.webhook_id as string) || "");
            break;

          default:
            throw new Error(`Unknown tool: ${name}`);
        }

        return {
          content: [
            {
              type: "text",
              text: JSON.stringify(result, null, 2),
            },
          ],
        };
      } catch (error) {
        const errorMessage =
          error instanceof Error ? error.message : String(error);
        return {
          content: [
            {
              type: "text",
              text: `Error: ${errorMessage}`,
            },
          ],
          isError: true,
        };
      }
    });
  }

  private getTools(): Tool[] {
    return [
      // Board tools
      {
        name: "get_boards",
        description:
          "Get all boards. Filter by state, board_kind, workspace_ids. Supports pagination.",
        inputSchema: {
          type: "object",
          properties: {
            limit: {
              type: "number",
              description: "Number of boards to return (default: 25)",
            },
            page: {
              type: "number",
              description: "Page number for pagination (default: 1)",
            },
            state: {
              type: "string",
              enum: ["active", "archived", "deleted", "all"],
              description: "Filter by board state (default: active)",
            },
            board_kind: {
              type: "string",
              enum: ["public", "private", "share"],
              description: "Filter by board type",
            },
            workspace_ids: {
              type: "array",
              items: { type: "string" },
              description: "Filter by workspace IDs",
            },
          },
        },
      },
      {
        name: "get_board",
        description: "Get a single board by ID with all columns and groups",
        inputSchema: {
          type: "object",
          properties: {
            board_id: {
              type: "string",
              description: "Board ID",
            },
          },
          required: ["board_id"],
        },
      },
      {
        name: "create_board",
        description: "Create a new board",
        inputSchema: {
          type: "object",
          properties: {
            board_name: {
              type: "string",
              description: "Name of the new board",
            },
            board_kind: {
              type: "string",
              enum: ["public", "private", "share"],
              description: "Board visibility type",
            },
            description: {
              type: "string",
              description: "Board description",
            },
            workspace_id: {
              type: "string",
              description: "Workspace ID to create board in",
            },
            folder_id: {
              type: "string",
              description: "Folder ID to create board in",
            },
            template_id: {
              type: "string",
              description: "Template ID to use",
            },
          },
          required: ["board_name", "board_kind"],
        },
      },

      // Item tools
      {
        name: "get_items",
        description:
          "Get items from a board. Supports pagination and filtering.",
        inputSchema: {
          type: "object",
          properties: {
            board_id: {
              type: "string",
              description: "Board ID",
            },
            limit: {
              type: "number",
              description: "Number of items to return (default: 25)",
            },
            page: {
              type: "number",
              description: "Page number for pagination",
            },
            ids: {
              type: "array",
              items: { type: "string" },
              description: "Filter by specific item IDs",
            },
            newest_first: {
              type: "boolean",
              description: "Sort by newest first",
            },
          },
          required: ["board_id"],
        },
      },
      {
        name: "get_item",
        description: "Get a single item by ID with all column values",
        inputSchema: {
          type: "object",
          properties: {
            item_id: {
              type: "string",
              description: "Item ID",
            },
          },
          required: ["item_id"],
        },
      },
      {
        name: "create_item",
        description: "Create a new item in a board",
        inputSchema: {
          type: "object",
          properties: {
            board_id: {
              type: "string",
              description: "Board ID",
            },
            group_id: {
              type: "string",
              description: "Group ID to create item in",
            },
            item_name: {
              type: "string",
              description: "Name of the new item",
            },
            column_values: {
              type: "object",
              description:
                "Column values as JSON object (keys are column IDs, values are column-type-specific)",
            },
            create_labels_if_missing: {
              type: "boolean",
              description: "Create labels if they don't exist",
            },
          },
          required: ["board_id", "item_name"],
        },
      },
      {
        name: "change_column_value",
        description: "Change a column value for an item",
        inputSchema: {
          type: "object",
          properties: {
            board_id: {
              type: "string",
              description: "Board ID",
            },
            item_id: {
              type: "string",
              description: "Item ID",
            },
            column_id: {
              type: "string",
              description: "Column ID",
            },
            value: {
              type: "object",
              description:
                "New value (format depends on column type, e.g. {text: 'value'} for text)",
            },
          },
          required: ["board_id", "item_id", "column_id", "value"],
        },
      },

      // Group tools
      {
        name: "create_group",
        description: "Create a new group in a board",
        inputSchema: {
          type: "object",
          properties: {
            board_id: {
              type: "string",
              description: "Board ID",
            },
            group_name: {
              type: "string",
              description: "Name of the new group",
            },
            position_relative_method: {
              type: "string",
              enum: ["before_at", "after_at"],
              description: "Position relative to another group",
            },
            relative_to: {
              type: "string",
              description: "Group ID to position relative to",
            },
          },
          required: ["board_id", "group_name"],
        },
      },

      // Update tools
      {
        name: "get_updates",
        description: "Get updates (activity feed) for an item",
        inputSchema: {
          type: "object",
          properties: {
            item_id: {
              type: "string",
              description: "Item ID",
            },
            limit: {
              type: "number",
              description: "Number of updates to return (default: 25)",
            },
          },
          required: ["item_id"],
        },
      },
      {
        name: "create_update",
        description: "Create an update (comment) on an item",
        inputSchema: {
          type: "object",
          properties: {
            item_id: {
              type: "string",
              description: "Item ID",
            },
            body: {
              type: "string",
              description: "Update text content",
            },
            parent_id: {
              type: "string",
              description: "Parent update ID (for replies)",
            },
          },
          required: ["item_id", "body"],
        },
      },

      // User, team, workspace tools
      {
        name: "get_users",
        description: "Get all users in the account",
        inputSchema: {
          type: "object",
          properties: {
            limit: {
              type: "number",
              description: "Number of users to return (default: 50)",
            },
          },
        },
      },
      {
        name: "get_teams",
        description: "Get all teams in the account",
        inputSchema: {
          type: "object",
          properties: {
            limit: {
              type: "number",
              description: "Number of teams to return (default: 50)",
            },
          },
        },
      },
      {
        name: "get_workspaces",
        description: "Get all workspaces in the account",
        inputSchema: {
          type: "object",
          properties: {
            limit: {
              type: "number",
              description: "Number of workspaces to return (default: 50)",
            },
          },
        },
      },

      // Webhook tools
      {
        name: "create_webhook",
        description: "Create a webhook for board events",
        inputSchema: {
          type: "object",
          properties: {
            board_id: {
              type: "string",
              description: "Board ID",
            },
            url: {
              type: "string",
              description: "Webhook URL to receive events",
            },
            event: {
              type: "string",
              enum: [
                "create_item",
                "change_column_value",
                "change_status_column_value",
                "change_specific_column_value",
                "create_update",
                "delete_update",
                "item_archived",
                "item_deleted",
                "item_moved_to_group",
                "item_restored",
                "subitem_created",
              ],
              description: "Event type to subscribe to",
            },
            config: {
              type: "object",
              description: "Optional webhook configuration",
            },
          },
          required: ["board_id", "url", "event"],
        },
      },
      {
        name: "delete_webhook",
        description: "Delete a webhook",
        inputSchema: {
          type: "object",
          properties: {
            webhook_id: {
              type: "string",
              description: "Webhook ID to delete",
            },
          },
          required: ["webhook_id"],
        },
      },
    ];
  }

  async run(): Promise<void> {
    const transport = new StdioServerTransport();
    await this.server.connect(transport);
  }
}
