/**
 * 频率限制装饰器
 *
 * 功能描述：
 * - 提供API接口的频率限制功能
 * - 防止恶意请求和系统滥用
 * - 支持基于IP和用户的限制策略
 *
 * 职责分离：
 * - 装饰器定义和配置接口管理
 * - 预设配置常量的维护
 * - 频率限制元数据的设置逻辑
 *
 * 使用场景：
 * - 登录接口防暴力破解
 * - 注册接口防批量注册
 * - 验证码接口防频繁发送
 * - 敏感操作接口保护
 *
 * 最近修改：
 * - 2026-01-07: 代码规范优化 - 更新注释规范，完善装饰器说明
 *
 * @author moyin
 * @version 1.0.1
 * @since 2025-12-24
 * @lastModified 2026-01-07
 */

import { SetMetadata, applyDecorators, UseGuards } from '@nestjs/common';
import { ThrottleGuard } from './throttle.guard';

/**
 * 频率限制元数据键
 */
export const THROTTLE_KEY = 'throttle';

/**
 * 频率限制配置接口
 */
export interface ThrottleConfig {
  /** 时间窗口内允许的最大请求次数 */
  limit: number;
  /** 时间窗口长度（秒） */
  ttl: number;
  /** 限制类型：ip（基于IP）、user（基于用户）或 email（基于邮箱） */
  type?: 'ip' | 'user' | 'email';
  /** 自定义错误消息 */
  message?: string;
}

/**
 * 频率限制装饰器
 *
 * 业务逻辑：
 * 1. 接收频率限制配置参数
 * 2. 设置频率限制元数据到方法或类上
 * 3. 应用ThrottleGuard守卫进行实际限制检查
 * 4. 支持自定义错误消息和限制类型
 *
 * @param config 频率限制配置
 * @returns 装饰器函数
 * @throws HttpException 当请求频率超过限制时
 *
 * @example
 * ```typescript
 * // 每分钟最多5次登录尝试
 * @Throttle({ limit: 5, ttl: 60, message: '登录尝试过于频繁，请稍后再试' })
 * @Post('login')
 * async login() { ... }
 *
 * // 每5分钟最多3次注册
 * @Throttle({ limit: 3, ttl: 300, type: 'ip' })
 * @Post('register')
 * async register() { ... }
 * ```
 */
export function Throttle(config: ThrottleConfig) {
  return applyDecorators(
    SetMetadata(THROTTLE_KEY, config),
    UseGuards(ThrottleGuard)
  );
}

/**
 * 预定义的频率限制配置
 */
export const ThrottlePresets = {
  /** 登录接口：每分钟5次（基于IP，防止暴力破解） */
  LOGIN: { limit: 5, ttl: 60, message: '登录尝试过于频繁，请1分钟后再试' },

  /** 登录接口（基于账号）：每个账号每分钟3次，但不同账号不互相影响 */
  LOGIN_PER_ACCOUNT: { limit: 3, ttl: 60, type: 'email' as any, message: '该账号登录尝试过于频繁，请1分钟后再试' },

  /** 注册接口：每5分钟10次（开发环境放宽限制） */
  REGISTER: { limit: 10, ttl: 300, message: '注册请求过于频繁，请5分钟后再试' },

  /** 发送验证码：每分钟1次（基于IP，用于防止滥用） */
  SEND_CODE: { limit: 1, ttl: 60, message: '验证码发送过于频繁，请1分钟后再试' },

  /** 发送验证码（基于邮箱）：每个邮箱每分钟1次，但不同邮箱不互相影响 */
  SEND_CODE_PER_EMAIL: { limit: 1, ttl: 60, type: 'email' as any, message: '该邮箱验证码发送过于频繁，请1分钟后再试' },

  /** 密码重置：每小时3次 */
  RESET_PASSWORD: { limit: 3, ttl: 3600, message: '密码重置请求过于频繁，请1小时后再试' },

  /** 令牌刷新：每分钟10次 */
  REFRESH_TOKEN: { limit: 10, ttl: 60, message: '令牌刷新请求过于频繁，请稍后再试' },

  /** 管理员操作：每分钟10次 */
  ADMIN_OPERATION: { limit: 10, ttl: 60, message: '管理员操作过于频繁，请稍后再试' },

  /** 一般API：每分钟30次 */
  GENERAL_API: { limit: 30, ttl: 60, message: 'API调用过于频繁，请稍后再试' }
} as const;