/**
 * @AgentTool() 装饰器 — 业务模块 service 方法上声明"我对 agent 暴露"。
 *
 * 用法 (详 docs/standards/21-agent-business-module-integration.md §2):
 *
 *   @Injectable()
 *   export class MyService {
 *     @AgentTool({
 *       name: 'my_action',
 *       description: '...',
 *       inputSchema: { foo: { type: 'string', required: true } },
 *       availability: { surface: ['web'], permissions: [MY_PERMISSIONS.READ] },
 *       writeAction: false,
 *     })
 *     async myActionForAgent(input: MyInput, ctx: AgentContext): Promise<MyOutput> {
 *       return this.myAction(input, ctx.userId);
 *     }
 *   }
 *
 * 装饰器仅**写入 reflect-metadata**;实际 ToolRegistry 注册由 `AgentToolsModule.forFeature([...])`
 * 在启动期触发 — 业务模块**必须**在自己的 NestJS module 通过 forFeature 显式登记被扫描的 service。
 *
 * 决策来源: #410 plan-review Q1.1 选 C(装饰器 + forFeature 显式收集),不用 DiscoveryService 全局扫。
 */

import 'reflect-metadata';
import type { AgentToolMetadata } from './types';

/** reflect-metadata 键 — 单一 service 方法存自己的 AgentToolMetadata */
export const AGENT_TOOL_METADATA = Symbol('AgentTool:Metadata');

/** reflect-metadata 键 — service class 上聚合存"本 class 哪些方法是 @AgentTool" */
export const AGENT_TOOL_METHODS = Symbol('AgentTool:Methods');

/**
 * @AgentTool(metadata) — 方法装饰器。
 *
 * @param metadata - AgentToolMetadata (即 ToolDescriptor 同字段)
 */
export function AgentTool(metadata: AgentToolMetadata): MethodDecorator {
  // 装饰器在 import 阶段执行,仅做元数据写入;不在此处校验业务规则
  // (重名 / forFeature 漏登记等 CI 强制校验由 ToolRegistry 启动期 + ESLint 完成)。
  return (target: object, propertyKey: string | symbol) => {
    // 1. 方法级元数据(让 ToolRegistry 启动扫描时能直接读)
    Reflect.defineMetadata(AGENT_TOOL_METADATA, metadata, target, propertyKey);

    // 2. class 级方法名清单(供 ToolRegistry 知道"这个 class 有哪些 @AgentTool 方法")
    const constructor = target.constructor;
    const existing: (string | symbol)[] = Reflect.getMetadata(AGENT_TOOL_METHODS, constructor) || [];
    if (!existing.includes(propertyKey)) {
      existing.push(propertyKey);
      Reflect.defineMetadata(AGENT_TOOL_METHODS, existing, constructor);
    }
  };
}

/**
 * 读取 service class 上的 @AgentTool 方法清单 — ToolRegistry 启动扫描用。
 *
 * @param target - service class constructor
 * @returns 方法名数组 (key 是装饰器写入时的 propertyKey)
 */
export function getAgentToolMethods(target: Function): (string | symbol)[] {
  return Reflect.getMetadata(AGENT_TOOL_METHODS, target) || [];
}

/**
 * 读取单个方法的 @AgentTool 元数据。
 *
 * @param prototype - service 的 prototype 对象 (装饰器 target = prototype)
 * @param method - 方法名
 */
export function getAgentToolMetadata(prototype: object, method: string | symbol): AgentToolMetadata | undefined {
  return Reflect.getMetadata(AGENT_TOOL_METADATA, prototype, method);
}
