// v1.13.16: Levenshtein + suggestion + formatter for the unknown-tool error
// returned to the model when an XML-extracted tool call references a name
// that isn't in TOOLS_BY_NAME. The drift incident this targets: qwen3.6
// emitting <invoke name="read_file"> from its Claude Code training residue
// when BooCode's actual file-read tool is view_file. Hand-rolled distance
// function — no new dep.

export function levenshtein(a: string, b: string): number {
  if (a.length === 0) return b.length;
  if (b.length === 0) return a.length;
  const dp: number[][] = Array.from(
    { length: a.length + 1 },
    () => new Array<number>(b.length + 1).fill(0),
  );
  for (let i = 0; i <= a.length; i++) dp[i]![0] = i;
  for (let j = 0; j <= b.length; j++) dp[0]![j] = j;
  for (let i = 1; i <= a.length; i++) {
    for (let j = 1; j <= b.length; j++) {
      const cost = a[i - 1] === b[j - 1] ? 0 : 1;
      dp[i]![j] = Math.min(
        dp[i - 1]![j]! + 1,
        dp[i]![j - 1]! + 1,
        dp[i - 1]![j - 1]! + cost,
      );
    }
  }
  return dp[a.length]![b.length]!;
}

// Threshold per the v1.13.16 dispatch: distance <= 3 OR substring match
// (either direction). Ties broken by smallest distance, then alphabetical.
export function suggestToolName(
  name: string,
  available: readonly string[],
): string | null {
  const lower = name.toLowerCase();
  let best: { name: string; dist: number } | null = null;
  for (const tool of available) {
    const tlower = tool.toLowerCase();
    const dist = levenshtein(lower, tlower);
    const isSubstr = tlower.includes(lower) || lower.includes(tlower);
    if (dist > 3 && !isSubstr) continue;
    if (
      best === null ||
      dist < best.dist ||
      (dist === best.dist && tool.localeCompare(best.name) < 0)
    ) {
      best = { name: tool, dist };
    }
  }
  return best?.name ?? null;
}

export function formatUnknownToolError(
  name: string,
  available: readonly string[],
): string {
  const sorted = [...available].sort();
  const suggestion = suggestToolName(name, sorted);
  const list = sorted.join(', ');
  const tail = suggestion ? ` Did you mean: ${suggestion}?` : '';
  return `Tool '${name}' not found. Available tools: [${list}].${tail}`;
}
