import { isRecord, stringField } from "@best-agent/foundation";
import type { ThreadMetadata, ToolInputValue } from "@best-agent/protocol";
import { isAbsolute, resolve } from "node:path";
import { isToolInputRecord } from "../../tool/tool-history-input.js";

export type WorkspaceSnapshotDigest = {
  digest: string;
  paths: string[];
  pathsKey: string;
};

export function extractWorkspaceMutationCandidatePaths(
  input: ToolInputValue,
  cwd: string,
): string[] {
  const paths: string[] = [];
  collectWorkspaceMutationCandidatePaths(input, paths);
  return Array.from(new Set(paths.map((path) => (isAbsolute(path) ? path : resolve(cwd, path)))));
}

export function workspaceSnapshotPathsKey(paths: string[], cwd: string): string | undefined {
  const resolvedPaths = Array.from(
    new Set(paths.map((path) => (isAbsolute(path) ? path : resolve(cwd, path)))),
  ).sort();
  return resolvedPaths.length > 0 ? resolvedPaths.join("\0") : undefined;
}

export function readWorkspaceSnapshotDigest(
  payload: ThreadMetadata,
): WorkspaceSnapshotDigest | undefined {
  const snapshot = payload.workspaceSnapshot;
  if (!isRecord(snapshot)) {
    return undefined;
  }
  const digest = stringField(snapshot, "digest");
  const pathsKey = stringField(snapshot, "pathsKey");
  const paths = snapshot.paths;
  if (
    digest === undefined ||
    pathsKey === undefined ||
    !Array.isArray(paths) ||
    !paths.every((path): path is string => typeof path === "string")
  ) {
    return undefined;
  }
  return { digest, paths, pathsKey };
}

function collectWorkspaceMutationCandidatePaths(input: ToolInputValue, paths: string[]): void {
  if (typeof input === "string") {
    return;
  }
  if (Array.isArray(input)) {
    for (const entry of input) {
      collectWorkspaceMutationCandidatePaths(entry, paths);
    }
    return;
  }
  if (!isToolInputRecord(input)) {
    return;
  }
  const value = input.file_path;
  if (typeof value === "string" && value.trim()) {
    paths.push(value);
  }
}
