import { Injectable, CanActivate, ExecutionContext, ForbiddenException } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { AbilityFactory, Action, Subjects } from '../abilities/ability.factory';

/**
 * Interface for required permissions
 */
export interface RequiredPermission {
  action: Action;
  subject: Subjects;
}

/**
 * Metadata key for permissions
 */
export const CHECK_ABILITY = 'check_ability';

/**
 * Guard that checks CASL abilities
 */
@Injectable()
export class AbilitiesGuard implements CanActivate {
  constructor(
    private reflector: Reflector,
    private abilityFactory: AbilityFactory,
  ) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const requiredPermissions =
      this.reflector.get<RequiredPermission[]>(
        CHECK_ABILITY,
        context.getHandler(),
      ) || [];

    // If no permissions required, allow access
    if (requiredPermissions.length === 0) {
      return true;
    }

    const request = context.switchToHttp().getRequest();
    const user = request.user;

    // User should be attached by JwtAuthGuard
    if (!user) {
      throw new ForbiddenException('User not authenticated');
    }

    // Build abilities for user
    const ability = this.abilityFactory.defineAbilitiesFor(user);

    // Check if user has all required permissions
    const hasPermission = requiredPermissions.every((permission) =>
      ability.can(permission.action, permission.subject),
    );

    if (!hasPermission) {
      throw new ForbiddenException(
        `User does not have required permissions`,
      );
    }

    return true;
  }
}
