// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
//
// SPDX-License-Identifier: GPL-3.0-or-later

import { readFile } from "node:fs/promises";
import { expandHomePath } from "../../util/path.js";
import { applyConfigOverrides, loadConfig } from "../../config/loader.js";
import { createWorkspace } from "../../workspace/manager.js";
import { createGrepTool } from "../../agent/tools/grep.js";
import { createReadTool } from "../../agent/tools/read.js";
import { createLsTool } from "../../agent/tools/ls.js";
import { createFindTool } from "../../agent/tools/find.js";
import { createGitLogTool } from "../../agent/tools/git/log.js";
import { createGitShowTool } from "../../agent/tools/git/show.js";
import { createGitBlameTool } from "../../agent/tools/git/blame.js";
import { createGitDiffTool } from "../../agent/tools/git/diff.js";
import { createGitRefsTool } from "../../agent/tools/git/refs.js";
import { createGitCheckoutTool } from "../../agent/tools/git/checkout.js";
import { runAgent } from "../../agent/runner.js";
import { buildRepoPrompt } from "../../agent/prompts/repo.js";
import { createEventLogger, printUsageSummary } from "../output.js";
import { CloneError } from "../../util/errors.js";
import simpleGit from "simple-git";

export interface RepoCommandOptions {
  query: string;
  uri: string;
  ref?: string;
  full: boolean;
  model?: string;
  verbose: boolean;
  cleanup: boolean;
}

export async function runRepoCommand(options: RepoCommandOptions): Promise<void> {
  const { config } = await loadConfig();
  const overrides = applyConfigOverrides(config, {
    defaults: { model: options.model ?? config.defaults.model, cleanup: options.cleanup },
    repo: { model: options.model ?? config.repo.model },
  });

  const workspace = await createWorkspace({ cleanup: overrides.defaults.cleanup });

  try {
    const logger = createEventLogger({ verbose: options.verbose });

    let systemPrompt = buildRepoPrompt({
      currentTime: new Date().toISOString(),
      hasHistory: options.full,
    });
    const promptPath = overrides.repo.system_prompt_path;
    if (promptPath) {
      systemPrompt = await readFile(expandHomePath(promptPath), "utf8");
    }

    const git = simpleGit();
    const cloneArgs: string[] = [];
    if (!options.full) {
      const depth = overrides.repo.default_depth ?? 1;
      const blobLimit = overrides.repo.blob_limit ?? "5m";
      cloneArgs.push("--depth", String(depth), `--filter=blob:limit=${blobLimit}`);
    }

    try {
      await git.clone(options.uri, workspace.path, cloneArgs);
    } catch (error: any) {
      if (!overrides.defaults.cleanup) {
        console.error(`Workspace preserved at ${workspace.path}`);
      }
      throw new CloneError(options.uri, error?.message ?? String(error));
    }

    const repoGit = simpleGit(workspace.path);
    if (options.ref) {
      await repoGit.checkout(options.ref);
    }

    const tools = [
      createReadTool(workspace.path),
      createGrepTool(workspace.path),
      createLsTool(workspace.path),
      createFindTool(workspace.path),
      createGitLogTool(workspace.path),
      createGitShowTool(workspace.path),
      createGitBlameTool(workspace.path),
      createGitDiffTool(workspace.path),
      createGitRefsTool(workspace.path),
      createGitCheckoutTool(workspace.path),
    ];

    const result = await runAgent(options.query, {
      model: overrides.repo.model ?? overrides.defaults.model,
      systemPrompt,
      tools,
      onEvent: logger,
      config: overrides,
    });

    process.stdout.write(result.message + "\n");
    printUsageSummary(result.usage as any, result.requestCount);
  } finally {
    await workspace.cleanup();
  }
}
