import {
  CanActivate,
  ExecutionContext,
  HttpException,
  HttpStatus,
  Injectable,
} from '@nestjs/common';
import { Request } from 'express';

type Bucket = {
  count: number;
  resetAt: number;
};

@Injectable()
export class AuditEventsRateLimitGuard implements CanActivate {
  private readonly buckets = new Map<string, Bucket>();
  private readonly windowMs = 60_000;
  private readonly maxRequests = 120;

  canActivate(context: ExecutionContext): boolean {
    const request = context.switchToHttp().getRequest<Request>();
    const key = this.getKey(request);
    const now = Date.now();
    const bucket = this.buckets.get(key);

    if (!bucket || bucket.resetAt <= now) {
      this.buckets.set(key, { count: 1, resetAt: now + this.windowMs });
      return true;
    }

    bucket.count += 1;
    if (bucket.count > this.maxRequests) {
      throw new HttpException(
        'Audit event rate limit exceeded',
        HttpStatus.TOO_MANY_REQUESTS,
      );
    }

    return true;
  }

  private getKey(request: Request): string {
    // trust proxy is set in main.ts; req.ip already reflects the correct client IP
    // (leftmost untrusted hop in x-forwarded-for as resolved by Express). Using the
    // raw x-forwarded-for header directly is spoofable by clients — do not do that.
    return request.ip || request.socket.remoteAddress || 'unknown';
  }
}
