import { SetMetadata, UseGuards, applyDecorators } from '@nestjs/common';
import type { Privilege } from 'shared-auth';
import { RequirePrivilegeGuard } from './require-privilege.guard';

/**
 * Reflector metadata key carrying the privilege list a route
 * requires. Re-exported by the guard module so the two stay in
 * lockstep.
 */
export const REQUIRE_PRIVILEGE_METADATA = 'auth:require-privilege';

/**
 * `@RequirePrivilege('Portal.X', ...)` — gates a route on
 * `principal.privileges` containing at least one of the listed
 * `Portal.*` values per [ADR-0025 §"Guard surface"](../../../../docs/decisions/0025-authorization-model-privileges-roles-scopes.md).
 *
 * Multiple slugs compose as **OR** within the decorator. Stacking
 * `@RequirePrivilege` with another guard (`@RequireRole`,
 * `@RequireMfa`) **AND**-combines at the Nest level — each guard
 * runs separately and a single denial stops the request.
 *
 * Calling with an empty privilege list is rejected at the type
 * level by the `[Privilege, ...Privilege[]]` tuple — a route can
 * not opt out of authorization by passing zero values.
 */
export function RequirePrivilege(
  ...privileges: [Privilege, ...Privilege[]]
): ClassDecorator & MethodDecorator {
  return applyDecorators(
    SetMetadata(REQUIRE_PRIVILEGE_METADATA, privileges),
    UseGuards(RequirePrivilegeGuard),
  );
}
