/**
 * Phase 3b post-review — collapse tool names into a bounded label set
 * before they reach `aao_worker_tool_calls_total{tool_name}`.
 *
 * Without this normalization, a piece that calls `mcp__foo__bar` or a
 * user-defined ad-hoc tool would inject a fresh `tool_name` label on
 * every distinct name — `mcp__` names are user-controllable and can
 * grow unbounded, especially through Brainstorm-generated piece
 * variations. Once the cardinality explodes we either OOM prom-client
 * or get rate-limited by the scrape side.
 *
 * Policy:
 *   - Known built-in tool name → pass through verbatim.
 *   - Any `mcp__*` name → collapse to single label `mcp`.
 *   - Anything else → collapse to `unknown`.
 *
 * Maintenance: when a new built-in tool ships, add its name to
 * BUILTIN_TOOL_NAMES below. The set is intentionally hard-coded (not
 * auto-derived from getToolDefs) so the metric label space is stable
 * across hot-reloads — if a tool module fails to load at runtime its
 * historical labels remain visible in Grafana instead of disappearing.
 */

/**
 * Pseudo-tools the agent loop fires that aren't user-callable but
 * still show up in the metric stream (transition / complete are
 * control-flow tools the runtime injects).
 */
const RUNTIME_TOOLS: ReadonlyArray<string> = [
  'transition',
  'complete',
];

/**
 * Built-in tools listed in `src/engine/tools/*.ts`. Keep alphabetized
 * for easy maintenance + grep.
 */
const BUILTIN_TOOL_NAMES_LIST: ReadonlyArray<string> = [
  // core.ts
  'Bash', 'Edit', 'Glob', 'Grep', 'Read', 'Write',
  // web.ts
  'DownloadFile', 'WebFetch', 'WebSearch',
  // image.ts
  'AnnotateImage', 'ReadImage',
  // office.ts
  'PdfToImages', 'ReadDocx', 'ReadExcel', 'ReadPdf', 'ReadPPTX',
  'SplitDocxSections', 'SplitExcelSheets',
  // data.ts
  'SQLite',
  // review.ts
  'BatchReviewTextWithLLM', 'MergeReviewedResults',
  // browser.ts
  'BrowseWeb',
  // knowledge.ts
  'IngestDocument', 'IngestStatus', 'ListDocuments', 'ListNamespaces',
  'SearchKnowledge',
  // orchestration.ts
  'SpawnSubTask',
  // x.ts
  'XPostDetail', 'XSearch', 'XTimeline', 'XUserPosts',
  // maps.ts
  'GetDirections', 'ReverseGeocode', 'SearchPlaces',
  // youtube.ts
  'GetYouTubeTranscript', 'SearchYouTube',
  // amazon.ts
  'SearchAmazon',
  // speech.ts
  'TranscribeAudio',
  // checklist.ts
  'CheckItem', 'CreateChecklist', 'GetChecklist',
  // pieces.ts
  'CreatePiece', 'GetPiece', 'ListPieces', 'UpdatePiece',
  // docs.ts
  'ReadToolDoc',
  // mission.ts
  'MissionUpdate',
  // user-folder.ts
  'ListUserAssets', 'ReadUserTemplate', 'RenderUserTemplate', 'RunUserScript',
  // brainstorm.ts
  'Brainstorm',
  // app-docs.ts
  'GetMyOrchestratorState', 'ListAppDocs', 'ReadAppDoc',
  // ssh.ts
  'SshDownload', 'SshExec', 'SshListConnections', 'SshUpload',
  // ssh-console.ts
  'SshConsoleEnsure', 'SshConsoleSendKeys', 'SshConsoleSnapshot',
  // notes.ts
  'ReadNote', 'SearchNotes', 'WriteNote',
  // dashboard.ts
  'UpdateDashboardWidget',
  // ms-learn.ts (Microsoft Learn search)
  'MsLearnFetch', 'MsLearnRead', 'MsLearnSearch', 'MsLearnSummarize',
  // slide.ts
  'CreateSlide',
];

export const BUILTIN_TOOL_NAMES: ReadonlySet<string> = new Set<string>([
  ...BUILTIN_TOOL_NAMES_LIST,
  ...RUNTIME_TOOLS,
]);

/**
 * Map an arbitrary tool name into the bounded label space.
 *
 * Examples:
 *   normalizeToolNameForMetric('Read')           → 'Read'
 *   normalizeToolNameForMetric('mcp__alpha__x')  → 'mcp'
 *   normalizeToolNameForMetric('user_custom')    → 'unknown'
 */
export function normalizeToolNameForMetric(name: string): string {
  if (BUILTIN_TOOL_NAMES.has(name)) return name;
  if (name.startsWith('mcp__')) return 'mcp';
  return 'unknown';
}
