import z from "zod"
import { Effect } from "effect"
import { Tool } from "./tool"
import { EditTool } from "./edit"
import DESCRIPTION from "./multiedit.txt"
import path from "path"
import { Instance } from "../project/instance"

export const MultiEditTool = Tool.define(
  "multiedit",
  Effect.gen(function* () {
    const editInfo = yield* EditTool
    const edit = yield* editInfo.init()

    return {
      description: DESCRIPTION,
      parameters: z.object({
        filePath: z.string().describe("The absolute path to the file to modify"),
        edits: z
          .array(
            z.object({
              filePath: z.string().describe("The absolute path to the file to modify"),
              oldString: z.string().describe("The text to replace"),
              newString: z.string().describe("The text to replace it with (must be different from oldString)"),
              replaceAll: z.boolean().optional().describe("Replace all occurrences of oldString (default false)"),
            }),
          )
          .describe("Array of edit operations to perform sequentially on the file"),
      }),
      execute: (
        params: {
          filePath: string
          edits: Array<{ filePath: string; oldString: string; newString: string; replaceAll?: boolean }>
        },
        ctx: Tool.Context,
      ) =>
        Effect.gen(function* () {
          const results = []
          for (const [, entry] of params.edits.entries()) {
            const result = yield* edit.execute(
              {
                filePath: params.filePath,
                oldString: entry.oldString,
                newString: entry.newString,
                replaceAll: entry.replaceAll,
              },
              ctx,
            )
            results.push(result)
          }
          return {
            title: path.relative(Instance.worktree, params.filePath),
            metadata: {
              results: results.map((r) => r.metadata),
            },
            output: results.at(-1)!.output,
          }
        }),
    }
  }),
)
