import {
  CanActivate,
  ExecutionContext,
  HttpException,
  HttpStatus,
  Injectable,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { AppCacheService } from '../../infrastructure/cache/app-cache.service';
import { THROTTLE_META_KEY, ThrottleMeta } from '../decorators/throttle.decorator';

@Injectable()
export class ThrottleGuard implements CanActivate {
  constructor(
    private readonly reflector: Reflector,
    private readonly cacheService: AppCacheService,
  ) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const meta = this.reflector.getAllAndOverride<ThrottleMeta>(THROTTLE_META_KEY, [
      context.getHandler(),
      context.getClass(),
    ]);
    if (!meta) {
      return true;
    }

    const req = context.switchToHttp().getRequest<
      Request & {
        ip?: string;
        originalUrl?: string;
        baseUrl?: string;
        route?: { path?: string };
        user?: { sub?: string };
      }
    >();
    const actorKey = req.user?.sub ?? req.ip ?? 'unknown';
    const routePath = `${req.baseUrl ?? ''}${req.route?.path ?? req.originalUrl ?? 'unknown-route'}`;
    const windowSeconds = Math.max(1, Math.ceil(meta.windowMs / 1000));
    const bucketKey = `rate-limit:${routePath}:${actorKey}`;
    const currentCount = await this.cacheService.incr(bucketKey, windowSeconds);

    if (currentCount > meta.limit) {
      throw new HttpException('Too many requests, please try again later', HttpStatus.TOO_MANY_REQUESTS);
    }

    return true;
  }
}
