import { Injectable } from '@nestjs/common';
import { CaslAction } from '../authorization/casl.constants';
import type { AppAbility } from '../authorization';
import type { ToolDef } from './agent-tool.types';

/**
 * Internal tool registry — NOT exported from the module.
 *
 * Holds all registered Agent Tools. Lookups are delegated from
 * {@link AgentToolExecutor}, which handles authorization, context
 * validation, and audit logging.
 *
 * SDK consumers MUST NOT access this directly — use
 * {@link AgentToolExecutor.listAvailable} and
 * {@link AgentToolExecutor.execute} instead.
 */
@Injectable()
export class AgentToolRegistry {
  private readonly tools: ToolDef[] = [];

  /** Register a tool (called once at module init). */
  register(tool: ToolDef): void {
    const idx = this.tools.findIndex((t) => t.name === tool.name);
    if (idx >= 0) {
      this.tools[idx] = tool;
    } else {
      this.tools.push(tool);
    }
  }

  /**
   * Return tools whose required permission the given ability satisfies.
   * The ability is built by the caller (Executor) — this is a pure
   * filter, not an authorization decision.
   */
  listAvailableInternal(ability: AppAbility): ToolDef[] {
    return this.tools.filter((tool) => {
      // Super admin ability has manage all — passes everything
      if (ability.can(CaslAction.Manage, 'all')) return true;
      // Exact permission-code check via CASL Access
      return ability.can(CaslAction.Access, `PermissionCode:${tool.requiredPermission}`);
    });
  }

  /**
   * Look up an internal {@link ToolDef} by name.
   * Returns `undefined` if not found.
   */
  getForExecution(name: string): ToolDef | undefined {
    return this.tools.find((t) => t.name === name);
  }
}
