import {
  CanActivate,
  ExecutionContext,
  ForbiddenException,
  Injectable,
} from "@nestjs/common";
import { Reflector } from "@nestjs/core";
import { Request } from "express";
import { ABILITY_KEY } from "./require-ability.decorator";
import { Ability, Role, can } from "./abilities";

/**
 * Enforces the ability matrix (abilities.ts) against req.user.role. A route
 * with no @RequireAbility passes through untouched — this guard only gates the
 * routes that declare one. It does NOT check authentication; always list it
 * after AuthenticatedGuard so an unauthenticated request is rejected first.
 */
@Injectable()
export class AbilityGuard implements CanActivate {
  constructor(private readonly reflector: Reflector) {}

  canActivate(context: ExecutionContext): boolean {
    const ability = this.reflector.getAllAndOverride<Ability | undefined>(
      ABILITY_KEY,
      [context.getHandler(), context.getClass()],
    );
    if (!ability) return true;

    const req = context.switchToHttp().getRequest<Request>();
    const user = req.user as { role?: Role } | undefined;
    if (!user?.role || !can(user.role, ability)) {
      throw new ForbiddenException("No tiene permisos para esta acción");
    }
    return true;
  }
}
