import { SetMetadata } from '@nestjs/common';
import { AppAbility } from './casl-ability.factory';

/**
 * A policy handler decides whether a request is allowed given the caller's
 * ability. It can be an object with a `handle` method or a plain callback.
 */
export interface IPolicyHandler {
  handle(ability: AppAbility): boolean;
}

export type PolicyHandlerCallback = (ability: AppAbility) => boolean;

export type PolicyHandler = IPolicyHandler | PolicyHandlerCallback;

export const CHECK_POLICIES_KEY = 'check_policies';

/**
 * Attach one or more policy handlers to a route or controller. All handlers
 * must pass for the PoliciesGuard to allow the request.
 *
 * @example
 * @CheckPolicies((ability) => ability.can(Action.Read, 'Role'))
 */
export const CheckPolicies = (...handlers: PolicyHandler[]) =>
  SetMetadata(CHECK_POLICIES_KEY, handlers);
