import { z } from "zod";
import { ConvexTool } from "./index.js";
import { loadSelectedDeploymentCredentials } from "../../api.js";
import { parseArgs, parseFunctionName } from "../../run.js";
import { readProjectConfig } from "../../config.js";
import { ConvexHttpClient } from "../../../../browser/index.js";
import { Value } from "../../../../values/index.js";
import { DefaultLogger } from "../../../../browser/logging.js";
import { getMcpDeploymentSelection } from "../requestContext.js";
const inputSchema = z.object({
  deploymentSelector: z
    .string()
    .describe(
      "Deployment selector (from the status tool) to run the function on.",
    ),
  functionName: z
    .string()
    .describe(
      "The name of the function to run (e.g. 'path/to/my/module.js:myFunction').",
    ),
  args: z
    .string()
    .describe(
      "The argument object to pass to the function, JSON-encoded as a string.",
    ),
});

const outputSchema = z.object({
  result: z.any().describe("The result returned by the function"),
  logLines: z
    .array(z.string())
    .describe("The log lines generated by the function"),
});

const description = `
Run a Convex function (query, mutation, or action) on your deployment.

Returns the result and any log lines generated by the function.
`.trim();

export const RunTool: ConvexTool<typeof inputSchema, typeof outputSchema> = {
  name: "run",
  description,
  inputSchema,
  outputSchema,
  handler: async (ctx, args) => {
    const { projectDir, deployment } = await ctx.decodeDeploymentSelector(
      args.deploymentSelector,
    );
    process.chdir(projectDir);
    const metadata = await getMcpDeploymentSelection(ctx, deployment);
    const credentials = await loadSelectedDeploymentCredentials(ctx, metadata);
    const parsedArgs = await parseArgs(ctx, args.args);
    const { projectConfig } = await readProjectConfig(ctx);
    const parsedFunctionName = await parseFunctionName(
      ctx,
      args.functionName,
      projectConfig.functions,
    );
    const logger = new DefaultLogger({ verbose: true });
    const logLines: string[] = [];
    logger.addLogLineListener((level, ...args) => {
      logLines.push(`${level}: ${args.join(" ")}`);
    });
    const client = new ConvexHttpClient(credentials.url, {
      logger: logger,
    });
    client.setAdminAuth(credentials.adminKey);
    let result: Value;
    try {
      result = await client.function(parsedFunctionName, undefined, parsedArgs);
    } catch (err) {
      return await ctx.crash({
        exitCode: 1,
        errorType: "invalid filesystem or env vars",
        printedMessage: `Failed to run function "${args.functionName}":\n${(err as Error).toString().trim()}`,
      });
    }
    return {
      result,
      logLines,
    };
  },
};
