/**
 * Individual rate limit window configuration
 */
export interface RateLimitWindow {
  points: number;         // Number of allowed points in the time window
  duration: number;       // Time window in seconds
  blockDuration?: number; // How long to block after limit is hit (seconds)
}

/**
 * Rate limit configuration for handlers and operations
 */
export interface RateLimitConfig {
  limits?: RateLimitWindow[];  // Array of rate limit windows
  cost?: number;               // How many points this operation costs (default: 1)
}

/**
 * Flexible rate limit configuration
 * Can be:
 * - A full config object with limits and cost
 * - Just a cost number (for operations inheriting handler limits)
 * - An array of limit windows (legacy support)
 * - A single limit window (legacy support)
 */
export type RateLimitOptions = RateLimitConfig | number | RateLimitWindow[] | RateLimitWindow;

/**
 * RateLimit decorator - configures rate limiting for handlers or operations
 * 
 * Can be applied to:
 * - Classes: Sets default rate limit for all operations in the handler
 * - Methods: Sets specific rate limit for individual operations (overrides handler-level)
 * 
 * @param options Rate limit configuration - flexible format
 * 
 * @example
 * // Handler-level rate limit with multiple windows
 * @Handler('myHandler')
 * @RateLimit({
 *   limits: [
 *     { points: 100, duration: 1 },      // 100 points/second
 *     { points: 10000, duration: 3600 }  // 10k points/hour
 *   ],
 *   cost: 1  // Default cost for all operations
 * })
 * class MyHandler extends BaseHandler {
 *   // All operations inherit these limits
 * }
 * 
 * @example
 * // Operation-specific cost only (inherits handler limits)
 * @Operation('fetch-simple')
 * @RateLimit(1)  // Costs 1 point
 * async fetchSimple() {}
 * 
 * @Operation('fetch-complex')
 * @RateLimit({ cost: 10 })  // Costs 10 points
 * async fetchComplex() {}
 * 
 * @example
 * // Operation with custom limits and cost
 * @Operation('special-operation')
 * @RateLimit({
 *   limits: [
 *     { points: 10, duration: 60 }  // More restrictive: 10/minute
 *   ],
 *   cost: 5
 * })
 * async specialOperation() {}
 */
export function RateLimit(options: RateLimitOptions) {
  return function (target: any, propertyKey?: string, descriptor?: PropertyDescriptor): any {
    // Normalize options to RateLimitConfig format
    let config: RateLimitConfig;
    
    if (typeof options === 'number') {
      // Just a cost number
      config = { cost: options };
    } else if (Array.isArray(options)) {
      // Array of limit windows (legacy support)
      config = { limits: options };
    } else if ('points' in options && 'duration' in options) {
      // Single limit window (legacy support)
      config = { limits: [options as RateLimitWindow] };
    } else {
      // Already a RateLimitConfig
      config = options as RateLimitConfig;
    }
    
    if (propertyKey) {
      // Method decorator - operation-specific rate limit
      const constructor = target.constructor;
      
      // Initialize rate limits array if not exists
      if (!constructor.__rateLimits) {
        constructor.__rateLimits = {};
      }
      
      // Store rate limit config for this operation
      constructor.__rateLimits[propertyKey] = config;
      
      return descriptor;
    } else {
      // Class decorator - handler-level rate limit
      (target as any).__handlerRateLimit = config;
      return target;
    }
  };
}