import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { gsbEntityTools } from "./gsb-entity-tools.js";
import { gsbEntityDefTools } from "./gsb-entity-def-tools.js";
import { z } from "zod";
import { getDocs, getSummary, getApiDocs, getServerlessFunctionDocs, getSchemaDocs } from "@gsb-core/mcp-docs";


function getToolSummary(toolName: string) {
  return getSummary(toolName) + "\n\n ***Important: Make sure to run getDocs(\"" + toolName + "\") to get the full documentation before using the tool";
}

export const toolHelper = {
    applyToMcp: async ({ server, getToken, getTenantCode }: { server: McpServer, getToken: (token?: string) => string, getTenantCode: (tenantCode?: string) => string }) => {




// Entity tools
server.tool(
  "getById",
  getToolSummary("getById") || "Retrieves an entity by its ID",
  {
    definitionType: z.string().describe("The entity definition type name"),
    id: z.string().describe("The unique identifier of the entity"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ definitionType, id, token, tenantCode }, extra) => {
    const result = await gsbEntityTools.getById({ definitionType, id, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

server.tool(
  "getCopy",
  getToolSummary("getCopy") || "Creates a copy of an entity by its ID, excluding the ID field",
  {
    request: z.any().describe("The copy request containing definitionType and id"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ request, token, tenantCode }, extra) => {
    const result = await gsbEntityTools.getCopy({ request, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

server.tool(
  "query",
  getToolSummary("query") || "Performs a query operation to fetch entities",
  {
    queryParams: z.any().describe("The query parameters object"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ queryParams, token, tenantCode }, extra) => {
    const result = await gsbEntityTools.query({ queryParams, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

server.tool(
  "queryMapped",
  getToolSummary("queryMapped") || "Performs a mapped query operation to fetch entities with mapping",
  {
    queryParams: z.any().describe("The query parameters object"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ queryParams, token, tenantCode }, extra) => {
    const result = await gsbEntityTools.queryMapped({ queryParams, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

server.tool(
  "save",
  getToolSummary("save") || "Saves a single entity",
  {
    entity: z.any().describe("The entity to save"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ entity, token, tenantCode }, extra) => {
    const result = await gsbEntityTools.save({ request: entity, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

server.tool(
  "saveMulti",
  getToolSummary("saveMulti") || "Saves multiple entities in a single operation",
  {
    request: z.any().describe("The save request with entities array"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ request, token, tenantCode }, extra) => {
    const result = await gsbEntityTools.saveMulti({ request, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

server.tool(
  "delete",
  getToolSummary("delete") || "Deletes an entity or entities based on criteria",
  {
    request: z.any().describe("The delete request"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ request, token, tenantCode }, extra) => {
    const result = await gsbEntityTools.delete({ request, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

server.tool(
  "deleteQuery",
  getToolSummary("deleteQuery") || "Deletes entities based on a query",
  {
    queryParams: z.any().describe("The query parameters object"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ queryParams, token, tenantCode }, extra) => {
    const result = await gsbEntityTools.deleteQuery({ queryParams, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

server.tool(
  "saveMappedItems",
  getToolSummary("saveMappedItems") || "Saves mapped items for an entity",
  {
    request: z.any().describe("The mapped save request"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ request, token, tenantCode }, extra) => {
    const result = await gsbEntityTools.saveMappedItems({ request, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

server.tool(
  "removeMappedItems",
  getToolSummary("removeMappedItems") || "Removes mapped items from an entity",
  {
    request: z.any().describe("The mapped remove request"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ request, token, tenantCode }, extra) => {
    const result = await gsbEntityTools.removeMappedItems({ request, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);


server.tool(
  "runWorkflow",
  getToolSummary("runWorkflow") || "Runs a workflow",
  {
    request: z.any().describe("The workflow request"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ request, token, tenantCode }, extra) => {
    const result = await gsbEntityTools.runWorkflow({ request, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

server.tool(
  "startWorkflow",
  getToolSummary("startWorkflow") || "Starts a workflow",
  {
    request: z.any().describe("The workflow start request"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ request, token, tenantCode }, extra) => {
    const result = await gsbEntityTools.startWorkflow({ request, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

server.tool(
  "runWfFunction",
  getToolSummary("runWfFunction") || "Runs a workflow function",
  {
    request: z.any().describe("The function execution request"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ request, token, tenantCode }, extra) => {
    const result = await gsbEntityTools.runWfFunction({ request, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

server.tool(
  "testWfFunction",
  getToolSummary("testWfFunction") || "Tests a workflow function",
  {
    request: z.any().describe("The function execution request"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ request, token, tenantCode }, extra) => {
    const result = await gsbEntityTools.testWfFunction({ request, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);


server.tool(
  "iterateTask",
  getToolSummary("iterateTask") || "Iterates a workflow task",
  {
    request: z.any().describe("The task iteration request"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ request, token, tenantCode }, extra) => {
    const result = await gsbEntityTools.iterateTask({ request, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

// Entity Definition tools
server.tool(
  "getCommonPropertyDefs",
  getToolSummary("getCommonPropertyDefs") || "Gets common property definitions that can be used when creating entity properties",
  {
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ token, tenantCode }, extra) => {
    const result = await gsbEntityDefTools.getCommonPropertyDefs({ token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

server.tool(
  "createEntityDef",
  getToolSummary("createEntityDef") || "Creates a new entity definition with the specified schema",
  {
    entityDef: z.any().describe("The entity definition to create"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ entityDef, token, tenantCode }, extra) => {
    const result = await gsbEntityDefTools.createEntityDef({ entityDef, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

server.tool(
  "updateEntityDef",
  getToolSummary("updateEntityDef") || "Updates an existing entity definition",
  {
    entityDef: z.any().describe("The entity definition to update"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ entityDef, token, tenantCode }, extra) => {
    const result = await gsbEntityDefTools.updateEntityDef({ entityDef, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

server.tool(
  "addProperty",
  getToolSummary("addProperty") || "Adds a new property to an entity definition",
  {
    property: z.any().describe("The property to add"),
    entityDef: z.any().optional().describe("The entity definition object containing id or name"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ property, entityDef, token, tenantCode }, extra) => {
    const result = await gsbEntityDefTools.addProperty({ property, entityDef, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

server.tool(
  "removeProperty",
  getToolSummary("removeProperty") || "Removes a property from an entity definition",
  {
    property: z.any().describe("The property to remove"),
    entityDef: z.any().optional().describe("The entity definition object containing id or name"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ property, entityDef, token, tenantCode }, extra) => {
    const result = await gsbEntityDefTools.removeProperty({ property, entityDef, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

server.tool(
  "updateProperty",
  getToolSummary("updateProperty") || "Updates an existing property in an entity definition",
  {
    property: z.any().describe("The updated property definition"),
    entityDef: z.any().describe("The entity definition object containing id or name"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ property, entityDef, token, tenantCode }, extra) => {
    const result = await gsbEntityDefTools.updateProperty({ property, entityDef, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

server.tool(
  "getEntityDef",
  getToolSummary("getEntityDef") || "Gets an entity definition by ID or name",
  {
    entityDef: z.any().describe("The entity definition object containing id or name"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ entityDef, token, tenantCode }, extra) => {
    const result = await gsbEntityDefTools.getEntityDef({ entityDef, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

server.tool(
  "queryEntityDefs",
  getToolSummary("queryEntityDefs") || "Queries entity definitions",
  {
    searchTerm: z.string().describe("Search term for entity definitions"),
    page: z.number().int().describe("Page number (0-based)"),
    pageSize: z.number().int().describe("Number of items per page"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ searchTerm, page, pageSize, token, tenantCode }, extra) => {
    const result = await gsbEntityDefTools.queryEntityDefs({ searchTerm, page, pageSize, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

// Add the createOrUpdateSchema tool
server.tool(
  "createOrUpdateSchema",
  getToolSummary("createOrUpdateSchema") || "Creates or updates multiple entity definitions and their properties with intelligent reference handling",
  {
    entityDefs: z.array(z.any()).describe("Array of entity definitions to create or update"),
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ entityDefs, token, tenantCode }, extra) => {
    const result = await gsbEntityDefTools.createOrUpdateSchema({ entityDefs, token: getToken(token), tenantCode: getTenantCode(tenantCode) });
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);

// Add API documentation tools
server.tool(
  "getDocs",
  getToolSummary("getDocs") || "Gets comprehensive API documentation",
  {
    methodName: z.string().optional().describe("Optional method name to get specific documentation")
  },
  async ({ methodName }, extra) => {
    const docs = getDocs(methodName);
    return {
      content: [{ type: "text", text: docs }],
    };
  }
);

server.tool(
  "getApiDocs",
  getToolSummary("getApiDocs") || "Gets general API information",
  {
    token: z.string().optional().describe("The authentication token for your request"),
    tenantCode: z.string().optional().describe("Optional tenant code (extracted from token if not provided)")
  },
  async ({ token, tenantCode }, extra) => {
    const docs = getApiDocs();
    return {
      content: [{ type: "text", text: docs }],
    };
  }
);

// New tool for GSB Serverless Functions Documentation
server.tool(
  "getServerlessFunctionDocs",
  "Gets comprehensive documentation for GSB Serverless Functions",
  {},
  async (args, extra) => {
    const docs = getServerlessFunctionDocs();
    return {
      content: [{ type: "text", text: docs }],
    };
  }
);

// New tool for GSB Schema Docs
server.tool(
  "getSchemaDocs",
  "Gets comprehensive documentation for GSB Schema Management",
  {},
  async (args, extra) => {
    const docs = getSchemaDocs();
    return {
      content: [{ type: "text", text: docs }],
    };
  }
);

// Add Schema Manager Documentation
server.tool(
  "getSchemaManagerDocs",
  "Gets documentation specific to the Schema Manager service",
  {},
  async (args, extra) => {
    const docs = getDocs("createOrUpdateSchema");
    return {
      content: [{ type: "text", text: docs }],
    };
  }
);

}

}; // Added missing closing brace
