import { CanActivate, ExecutionContext, ForbiddenException, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { UserRole } from '@prisma/client';
import { RequestUser } from '../common/request-user';
import { REQUIRE_FEATURE_KEY } from '../features/require-feature.decorator';
import { REQUIRE_ROLE_KEY } from './require-role.decorator';

/**
 * Guard to enforce role-based access control on routes decorated with @RequireRole.
 * 
 * Must be registered globally or on specific routes:
 * 
 * Global registration in app.module.ts:
 * providers: [
 *   { provide: APP_GUARD, useClass: RolesGuard }
 * ]
 * 
 * Or use on specific routes:
 * @UseGuards(RolesGuard)
 */
@Injectable()
export class RolesGuard implements CanActivate {
  constructor(private reflector: Reflector) {}

  canActivate(context: ExecutionContext): boolean {
    // Get required roles from @RequireRole decorator metadata
    const requiredRoles = this.reflector.getAllAndOverride<UserRole[]>(
      REQUIRE_ROLE_KEY,
      [context.getHandler(), context.getClass()]
    );

    // If no @RequireRole decorator, allow all authenticated users
    if (!requiredRoles || requiredRoles.length === 0) {
      return true;
    }

    const request = context.switchToHttp().getRequest<{ user?: RequestUser }>();
    const user = request.user;

    if (!user) {
      throw new ForbiddenException('User context not found');
    }

    // SUPER_ADMIN always has access
    if (user.role === UserRole.SUPER_ADMIN) {
      return true;
    }

    // Check if user's role is in required roles list
    if (requiredRoles.includes(user.role)) {
      return true;
    }

    const requiredFeature = this.reflector.getAllAndOverride<string>(
      REQUIRE_FEATURE_KEY,
      [context.getHandler(), context.getClass()]
    );

    if (requiredFeature && user.role === UserRole.SALES_ADMIN) {
      return true;
    }

    throw new ForbiddenException(
      `This route requires one of: ${requiredRoles.join(', ')}. You have: ${user.role}`
    );
  }
}
