import { UserType } from '@gadmin2/nest-common';
import {
  CanActivate,
  ExecutionContext,
  ForbiddenException,
  Injectable,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
type RolesGetter = (user: UserType) => Promise<string[] | undefined>;

@Injectable()
export default class RolesGuard implements CanActivate {
  constructor(
    private readonly getter: RolesGetter,
    private reflector: Reflector,
  ) {}

  canActivate(context: ExecutionContext): boolean | Promise<boolean> {
    const req = context.switchToHttp().getRequest();

    const allowUnauthorizedRequest = this.reflector.get<boolean>(
      'allowUnauthorizedRequest',
      context.getHandler(),
    );
    if (allowUnauthorizedRequest) {
      return true;
    }

    if (!req.user) {
      throw new ForbiddenException();
    }

    return this.getter(req.user)
      .then((roles) => {
        if (undefined === roles || roles.length === 0) {
          throw new ForbiddenException();
        }
        req.user.roles = roles;
        return true;
      })
      .catch((_) => {
        throw new ForbiddenException();
      });
  }
}
