import { Injectable, CanActivate, ExecutionContext, HttpException, HttpStatus } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { RedisService } from '../../infrastructure/redis/redis.service';
import { RATE_LIMIT_KEY, type RateLimitConfig } from '../decorators/rate-limit.decorator';

@Injectable()
export class RateLimitGuard implements CanActivate {
  constructor(
    private readonly reflector: Reflector,
    private readonly redis: RedisService,
  ) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const config = this.reflector.get<RateLimitConfig>(
      RATE_LIMIT_KEY,
      context.getHandler(),
    );
    if (!config) return true;

    const request = context.switchToHttp().getRequest();

    let identifier: string;
    if (config.byIp) {
      identifier = request.ip || request.connection?.remoteAddress || 'unknown';
    } else {
      identifier = request.user?.id || request.ip || request.connection?.remoteAddress || 'unknown';
    }

    const key = `rate:${config.key}:${identifier}`;

    const count = await this.redis.incr(key);
    if (count === 1) {
      await this.redis.expire(key, config.windowSeconds);
    }

    if (count > config.maxRequests) {
      throw new HttpException(
        {
          statusCode: HttpStatus.TOO_MANY_REQUESTS,
          message: `请求过于频繁，请${config.windowSeconds >= 3600 ? `${Math.round(config.windowSeconds / 3600)}小时` : `${Math.round(config.windowSeconds / 60)}分钟`}后再试`,
          retryAfter: config.windowSeconds,
        },
        HttpStatus.TOO_MANY_REQUESTS,
      );
    }

    return true;
  }
}
