/**
 * Public lifecycle aliases exposed by CodeFlowMu's FCoP adapter.
 *
 * Authorization is defined over the lifecycle operation, not the spelling
 * selected by an MCP client. Keep this mapping in Runtime so every Host
 * applies the same equivalence rule.
 */
export const LIFECYCLE_TOOL_ALIASES: Readonly<Record<string, string>> = {
  submit_review: "submit_task",
  approve_review: "approve_task",
  reject_review: "reject_task",
};

const CANONICAL_TO_ALIASES: Readonly<Record<string, readonly string[]>> = (() => {
  const values: Record<string, string[]> = {};
  for (const [alias, canonical] of Object.entries(LIFECYCLE_TOOL_ALIASES)) {
    (values[canonical] ??= []).push(alias);
  }
  return values;
})();

export function lifecycleToolPeerNames(toolName: string): readonly string[] {
  const normalized = toolName.trim();
  const peers = new Set<string>([normalized]);
  const canonical = LIFECYCLE_TOOL_ALIASES[normalized];
  if (canonical) {
    peers.add(canonical);
    for (const alias of CANONICAL_TO_ALIASES[canonical] ?? []) peers.add(alias);
  }
  for (const alias of CANONICAL_TO_ALIASES[normalized] ?? []) peers.add(alias);
  return [...peers];
}

export function isLifecycleToolNameAllowed(
  toolName: string,
  allowed: ReadonlySet<string>,
): boolean {
  return lifecycleToolPeerNames(toolName).some((peer) => allowed.has(peer));
}
