import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { ElicitResultSchema } from "@modelcontextprotocol/sdk/types.js";
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";

// Tool configuration
const name = "trigger-elicitation-request";
const config = {
  title: "Trigger Elicitation Request Tool",
  description: "Trigger a Request from the Server for User Elicitation",
  inputSchema: {},
};

/**
 * Registers the 'trigger-elicitation-request' tool.
 *
 * If the client does not support the elicitation capability, the tool is not registered.
 *
 * The registered tool sends an elicitation request for the user to provide information
 * based on a pre-defined schema of fields including text inputs, booleans, numbers,
 * email, dates, enums of various types, etc. It uses validation and handles multiple
 * possible outcomes from the user's response, such as acceptance with content, decline,
 * or cancellation of the dialog. The process also ensures parsing and validating
 * the elicitation input arguments at runtime.
 *
 * The elicitation dialog response is returned, formatted into a structured result,
 * which contains both user-submitted input data (if provided) and debugging information,
 * including raw results.
 *
 * @param {McpServer} server - TThe McpServer instance where the tool will be registered.
 */
export const registerTriggerElicitationRequestTool = (server: McpServer) => {
  // Does the client support elicitation?
  const clientCapabilities = server.server.getClientCapabilities() || {};
  const clientSupportsElicitation: boolean =
    clientCapabilities.elicitation !== undefined;

  // If so, register tool
  if (clientSupportsElicitation) {
    server.registerTool(
      name,
      config,
      async (args, extra): Promise<CallToolResult> => {
        const elicitationResult = await extra.sendRequest(
          {
            method: "elicitation/create",
            params: {
              message: "Please provide inputs for the following fields:",
              requestedSchema: {
                type: "object",
                properties: {
                  name: {
                    title: "String",
                    type: "string",
                    description: "Your full, legal name",
                  },
                  check: {
                    title: "Boolean",
                    type: "boolean",
                    description: "Agree to the terms and conditions",
                  },
                  firstLine: {
                    title: "String with default",
                    type: "string",
                    description: "Favorite first line of a story",
                    default: "It was a dark and stormy night.",
                  },
                  email: {
                    title: "String with email format",
                    type: "string",
                    format: "email",
                    description:
                      "Your email address (will be verified, and never shared with anyone else)",
                  },
                  homepage: {
                    type: "string",
                    format: "uri",
                    title: "String with uri format",
                    description: "Portfolio / personal website",
                  },
                  birthdate: {
                    title: "String with date format",
                    type: "string",
                    format: "date",
                    description: "Your date of birth",
                  },
                  integer: {
                    title: "Integer",
                    type: "integer",
                    description:
                      "Your favorite integer (do not give us your phone number, pin, or other sensitive info)",
                    minimum: 1,
                    maximum: 100,
                    default: 42,
                  },
                  number: {
                    title: "Number in range 1-1000",
                    type: "number",
                    description: "Favorite number (there are no wrong answers)",
                    minimum: 0,
                    maximum: 1000,
                    default: 3.14,
                  },
                  untitledSingleSelectEnum: {
                    type: "string",
                    title: "Untitled Single Select Enum",
                    description: "Choose your favorite friend",
                    enum: [
                      "Monica",
                      "Rachel",
                      "Joey",
                      "Chandler",
                      "Ross",
                      "Phoebe",
                    ],
                    default: "Monica",
                  },
                  untitledMultipleSelectEnum: {
                    type: "array",
                    title: "Untitled Multiple Select Enum",
                    description: "Choose your favorite instruments",
                    minItems: 1,
                    maxItems: 3,
                    items: {
                      type: "string",
                      enum: ["Guitar", "Piano", "Violin", "Drums", "Bass"],
                    },
                    default: ["Guitar"],
                  },
                  titledSingleSelectEnum: {
                    type: "string",
                    title: "Titled Single Select Enum",
                    description: "Choose your favorite hero",
                    oneOf: [
                      { const: "hero-1", title: "Superman" },
                      { const: "hero-2", title: "Green Lantern" },
                      { const: "hero-3", title: "Wonder Woman" },
                    ],
                    default: "hero-1",
                  },
                  titledMultipleSelectEnum: {
                    type: "array",
                    title: "Titled Multiple Select Enum",
                    description: "Choose your favorite types of fish",
                    minItems: 1,
                    maxItems: 3,
                    items: {
                      anyOf: [
                        { const: "fish-1", title: "Tuna" },
                        { const: "fish-2", title: "Salmon" },
                        { const: "fish-3", title: "Trout" },
                      ],
                    },
                    default: ["fish-1"],
                  },
                  legacyTitledEnum: {
                    type: "string",
                    title: "Legacy Titled Single Select Enum",
                    description: "Choose your favorite type of pet",
                    enum: ["pet-1", "pet-2", "pet-3", "pet-4", "pet-5"],
                    enumNames: ["Cats", "Dogs", "Birds", "Fish", "Reptiles"],
                    default: "pet-1",
                  },
                },
                required: ["name"],
              },
            },
          },
          ElicitResultSchema,
          { timeout: 10 * 60 * 1000 /* 10 minutes */ }
        );

        // Handle different response actions
        const content: CallToolResult["content"] = [];

        if (
          elicitationResult.action === "accept" &&
          elicitationResult.content
        ) {
          content.push({
            type: "text",
            text: `✅ User provided the requested information!`,
          });

          // Only access elicitationResult.content when action is accept
          const userData = elicitationResult.content;
          const lines = [];
          if (userData.name) lines.push(`- Name: ${userData.name}`);
          if (userData.check !== undefined)
            lines.push(`- Agreed to terms: ${userData.check}`);
          if (userData.color) lines.push(`- Favorite Color: ${userData.color}`);
          if (userData.email) lines.push(`- Email: ${userData.email}`);
          if (userData.homepage) lines.push(`- Homepage: ${userData.homepage}`);
          if (userData.birthdate)
            lines.push(`- Birthdate: ${userData.birthdate}`);
          if (userData.integer !== undefined)
            lines.push(`- Favorite Integer: ${userData.integer}`);
          if (userData.number !== undefined)
            lines.push(`- Favorite Number: ${userData.number}`);
          if (userData.petType) lines.push(`- Pet Type: ${userData.petType}`);

          content.push({
            type: "text",
            text: `User inputs:\n${lines.join("\n")}`,
          });
        } else if (elicitationResult.action === "decline") {
          content.push({
            type: "text",
            text: `❌ User declined to provide the requested information.`,
          });
        } else if (elicitationResult.action === "cancel") {
          content.push({
            type: "text",
            text: `⚠️ User cancelled the elicitation dialog.`,
          });
        }

        // Include raw result for debugging
        content.push({
          type: "text",
          text: `\nRaw result: ${JSON.stringify(elicitationResult, null, 2)}`,
        });

        return { content };
      }
    );
  }
};
