import { Injectable, CanActivate, ExecutionContext, ForbiddenException } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { ROLES_KEY, UserRole } from '../../../common/decorators/roles.decorator';

/**
 * RolesGuard checks if the authenticated user has one of the required roles.
 * Supports multi-role: checks both `roles[]` (new) and `role` (backward compat).
 *
 * @example
 * @Roles(UserRole.TRAINER, UserRole.COORDINATOR)
 * @UseGuards(JwtAuthGuard, RolesGuard)
 * getTrainers() { ... }
 */
@Injectable()
export class RolesGuard implements CanActivate {
  constructor(private readonly reflector: Reflector) {}

  canActivate(context: ExecutionContext): boolean {
    const requiredRoles = this.reflector.getAllAndOverride<UserRole[]>(ROLES_KEY, [
      context.getHandler(),
      context.getClass(),
    ]);

    if (!requiredRoles || requiredRoles.length === 0) {
      return true;
    }

    const request = context
      .switchToHttp()
      .getRequest<{ user?: { role?: string; roles?: string[] } }>();
    const user = request.user;

    if (!user?.role) {
      throw new ForbiddenException('User role is not defined');
    }

    // Multi-role check: use roles[] if available, fallback to single role
    const userRoles: string[] =
      Array.isArray(user.roles) && user.roles.length > 0
        ? user.roles.map((r) => r.toLowerCase())
        : [user.role.toLowerCase()];

    const hasRole = requiredRoles.some((required) => userRoles.includes(required));

    if (!hasRole) {
      throw new ForbiddenException(`Access denied. Required roles: ${requiredRoles.join(', ')}`);
    }

    return true;
  }
}
