import { z } from 'zod';
import type { ToolDef } from '../types.js';
import { callCodecontext, type CodecontextResponse } from '../../codecontext_client.js';

// Shared factory for the 12 codecontext shim ToolDefs.
// Each shim provides name/schema/description/jsonParameters/mapArgs; the
// factory builds the ToolDef and returns both the ToolDef and the standalone
// execute function (used by tests that inject a custom fetcher).
export function makeCodecontextTool<TInput>(opts: {
  name: string;
  schema: z.ZodType<TInput>;
  description: string;
  jsonParameters: Record<string, unknown>;
  mapArgs: (input: TInput) => Record<string, unknown>;
}): {
  toolDef: ToolDef<TInput>;
  execute: (input: TInput, projectPath: string, fetcher?: typeof fetch) => Promise<CodecontextResponse>;
} {
  const { name, schema, description, jsonParameters, mapArgs } = opts;

  async function execute(
    input: TInput,
    projectPath: string,
    fetcher: typeof fetch = fetch,
  ): Promise<CodecontextResponse> {
    return callCodecontext({ toolName: name, args: mapArgs(input), projectPath }, fetcher);
  }

  const toolDef: ToolDef<TInput> = {
    name,
    description,
    inputSchema: schema,
    jsonSchema: {
      type: 'function',
      function: { name, description, parameters: jsonParameters },
    },
    async execute(input, projectRoot) {
      return execute(input, projectRoot);
    },
  };

  return { toolDef, execute };
}
