import * as plugins from '../../plugins.js';
import { EventEmitter } from 'node:events';
import { logger } from '../../logger.js';
import { SecurityLogger, SecurityLogLevel, SecurityEventType } from '../../security/index.js';

/**
 * Interface for rate limit configuration
 */
export interface IRateLimitConfig {
  maxMessagesPerMinute?: number;
  maxRecipientsPerMessage?: number;
  maxConnectionsPerIP?: number;
  maxErrorsPerIP?: number;
  maxAuthFailuresPerIP?: number;
  blockDuration?: number; // in milliseconds
}

/**
 * Interface for hierarchical rate limits
 */
export interface IHierarchicalRateLimits {
  // Global rate limits (applied to all traffic)
  global: IRateLimitConfig;
  
  // Pattern-specific rate limits (applied to matching patterns)
  patterns?: Record<string, IRateLimitConfig>;
  
  // IP-specific rate limits (applied to specific IPs)
  ips?: Record<string, IRateLimitConfig>;
  
  // Domain-specific rate limits (applied to specific email domains)
  domains?: Record<string, IRateLimitConfig>;
  
  // Temporary blocks list and their expiry times
  blocks?: Record<string, number>; // IP to expiry timestamp
}

/**
 * Counter interface for rate limiting
 */
interface ILimitCounter {
  count: number;
  lastReset: number;
  recipients: number;
  errors: number;
  authFailures: number;
  connections: number;
}

/**
 * Rate limiter statistics
 */
export interface IRateLimiterStats {
  activeCounters: number;
  totalBlocked: number;
  currentlyBlocked: number;
  byPattern: Record<string, {
    messagesPerMinute: number;
    totalMessages: number;
    totalBlocked: number;
  }>;
  byIp: Record<string, {
    messagesPerMinute: number;
    totalMessages: number;
    totalBlocked: number;
    connections: number;
    errors: number;
    authFailures: number;
    blocked: boolean;
  }>;
}

/**
 * Result of a rate limit check
 */
export interface IRateLimitResult {
  allowed: boolean;
  reason?: string;
  limit?: number;
  current?: number;
  resetIn?: number; // milliseconds until reset
}

/**
 * Unified rate limiter for all email processing modes
 */
export class UnifiedRateLimiter extends EventEmitter {
  private config: IHierarchicalRateLimits;
  private counters: Map<string, ILimitCounter> = new Map();
  private patternCounters: Map<string, ILimitCounter> = new Map();
  private ipCounters: Map<string, ILimitCounter> = new Map();
  private domainCounters: Map<string, ILimitCounter> = new Map();
  private cleanupInterval?: NodeJS.Timeout;
  private stats: IRateLimiterStats;
  
  /**
   * Create a new unified rate limiter
   * @param config Rate limit configuration
   */
  constructor(config: IHierarchicalRateLimits) {
    super();
    
    // Set default configuration
    this.config = {
      global: {
        maxMessagesPerMinute: config.global.maxMessagesPerMinute || 100,
        maxRecipientsPerMessage: config.global.maxRecipientsPerMessage || 100,
        maxConnectionsPerIP: config.global.maxConnectionsPerIP || 20,
        maxErrorsPerIP: config.global.maxErrorsPerIP || 10,
        maxAuthFailuresPerIP: config.global.maxAuthFailuresPerIP || 5,
        blockDuration: config.global.blockDuration || 3600000 // 1 hour
      },
      patterns: config.patterns || {},
      ips: config.ips || {},
      blocks: config.blocks || {}
    };
    
    // Initialize statistics
    this.stats = {
      activeCounters: 0,
      totalBlocked: 0,
      currentlyBlocked: 0,
      byPattern: {},
      byIp: {}
    };
    
    // Start cleanup interval
    this.startCleanupInterval();
  }
  
  /**
   * Start the cleanup interval
   */
  private startCleanupInterval(): void {
    if (this.cleanupInterval) {
      clearInterval(this.cleanupInterval);
    }
    
    // Run cleanup every minute
    this.cleanupInterval = setInterval(() => this.cleanup(), 60000);
  }
  
  /**
   * Stop the cleanup interval
   */
  public stop(): void {
    if (this.cleanupInterval) {
      clearInterval(this.cleanupInterval);
      this.cleanupInterval = undefined;
    }
  }
  
  /**
   * Destroy the rate limiter and clean up all resources
   */
  public destroy(): void {
    // Stop the cleanup interval
    this.stop();
    
    // Clear all maps to free memory
    this.counters.clear();
    this.ipCounters.clear();
    this.patternCounters.clear();
    
    // Clear blocks
    if (this.config.blocks) {
      this.config.blocks = {};
    }
    
    // Clear statistics
    this.stats = {
      activeCounters: 0,
      totalBlocked: 0,
      currentlyBlocked: 0,
      byPattern: {},
      byIp: {}
    };
    
    logger.log('info', 'UnifiedRateLimiter destroyed');
  }
  
  /**
   * Clean up expired counters and blocks
   */
  private cleanup(): void {
    const now = Date.now();
    
    // Clean up expired blocks
    if (this.config.blocks) {
      for (const [ip, expiry] of Object.entries(this.config.blocks)) {
        if (expiry <= now) {
          delete this.config.blocks[ip];
          logger.log('info', `Rate limit block expired for IP ${ip}`);
          
          // Update statistics
          if (this.stats.byIp[ip]) {
            this.stats.byIp[ip].blocked = false;
          }
          this.stats.currentlyBlocked--;
        }
      }
    }
    
    // Clean up old counters (older than 10 minutes)
    const cutoff = now - 600000;
    
    // Clean global counters
    for (const [key, counter] of this.counters.entries()) {
      if (counter.lastReset < cutoff) {
        this.counters.delete(key);
      }
    }
    
    // Clean pattern counters
    for (const [key, counter] of this.patternCounters.entries()) {
      if (counter.lastReset < cutoff) {
        this.patternCounters.delete(key);
      }
    }
    
    // Clean IP counters
    for (const [key, counter] of this.ipCounters.entries()) {
      if (counter.lastReset < cutoff) {
        this.ipCounters.delete(key);
      }
    }
    
    // Clean domain counters
    for (const [key, counter] of this.domainCounters.entries()) {
      if (counter.lastReset < cutoff) {
        this.domainCounters.delete(key);
      }
    }
    
    // Update statistics
    this.updateStats();
  }
  
  /**
   * Check if a message is allowed by rate limits
   * @param email Email address
   * @param ip IP address
   * @param recipients Number of recipients
   * @param pattern Matched pattern
   * @param domain Domain name for domain-specific limits
   * @returns Result of rate limit check
   */
  public checkMessageLimit(email: string, ip: string, recipients: number, pattern?: string, domain?: string): IRateLimitResult {
    // Check if IP is blocked
    if (this.isIpBlocked(ip)) {
      return {
        allowed: false,
        reason: 'IP is blocked',
        resetIn: this.getBlockReleaseTime(ip)
      };
    }
    
    // Check global message rate limit
    const globalResult = this.checkGlobalMessageLimit(email);
    if (!globalResult.allowed) {
      return globalResult;
    }
    
    // Check pattern-specific limit if pattern is provided
    if (pattern) {
      const patternResult = this.checkPatternMessageLimit(pattern);
      if (!patternResult.allowed) {
        return patternResult;
      }
    }
    
    // Check domain-specific limit if domain is provided
    if (domain) {
      const domainResult = this.checkDomainMessageLimit(domain);
      if (!domainResult.allowed) {
        return domainResult;
      }
    }
    
    // Check IP-specific limit
    const ipResult = this.checkIpMessageLimit(ip);
    if (!ipResult.allowed) {
      return ipResult;
    }
    
    // Check recipient limit
    const recipientResult = this.checkRecipientLimit(email, recipients, pattern, domain);
    if (!recipientResult.allowed) {
      return recipientResult;
    }
    
    // All checks passed
    return { allowed: true };
  }
  
  /**
   * Check global message rate limit
   * @param email Email address
   */
  private checkGlobalMessageLimit(email: string): IRateLimitResult {
    const now = Date.now();
    const limit = this.config.global.maxMessagesPerMinute!;
    
    if (!limit) {
      return { allowed: true };
    }
    
    // Get or create counter
    const key = 'global';
    let counter = this.counters.get(key);
    
    if (!counter) {
      counter = {
        count: 0,
        lastReset: now,
        recipients: 0,
        errors: 0,
        authFailures: 0,
        connections: 0
      };
      this.counters.set(key, counter);
    }
    
    // Check if counter needs to be reset
    if (now - counter.lastReset >= 60000) {
      counter.count = 0;
      counter.lastReset = now;
    }
    
    // Check if limit is exceeded
    if (counter.count >= limit) {
      // Calculate reset time
      const resetIn = 60000 - (now - counter.lastReset);
      
      return {
        allowed: false,
        reason: 'Global message rate limit exceeded',
        limit,
        current: counter.count,
        resetIn
      };
    }
    
    // Increment counter
    counter.count++;
    
    // Update statistics
    this.updateStats();
    
    return { allowed: true };
  }
  
  /**
   * Check pattern-specific message rate limit
   * @param pattern Pattern to check
   */
  private checkPatternMessageLimit(pattern: string): IRateLimitResult {
    const now = Date.now();
    
    // Get pattern-specific limit or use global
    const patternConfig = this.config.patterns?.[pattern];
    const limit = patternConfig?.maxMessagesPerMinute || this.config.global.maxMessagesPerMinute!;
    
    if (!limit) {
      return { allowed: true };
    }
    
    // Get or create counter
    let counter = this.patternCounters.get(pattern);
    
    if (!counter) {
      counter = {
        count: 0,
        lastReset: now,
        recipients: 0,
        errors: 0,
        authFailures: 0,
        connections: 0
      };
      this.patternCounters.set(pattern, counter);
      
      // Initialize pattern stats if needed
      if (!this.stats.byPattern[pattern]) {
        this.stats.byPattern[pattern] = {
          messagesPerMinute: 0,
          totalMessages: 0,
          totalBlocked: 0
        };
      }
    }
    
    // Check if counter needs to be reset
    if (now - counter.lastReset >= 60000) {
      counter.count = 0;
      counter.lastReset = now;
    }
    
    // Check if limit is exceeded
    if (counter.count >= limit) {
      // Calculate reset time
      const resetIn = 60000 - (now - counter.lastReset);
      
      // Update statistics
      this.stats.byPattern[pattern].totalBlocked++;
      this.stats.totalBlocked++;
      
      return {
        allowed: false,
        reason: `Pattern "${pattern}" message rate limit exceeded`,
        limit,
        current: counter.count,
        resetIn
      };
    }
    
    // Increment counter
    counter.count++;
    
    // Update statistics
    this.stats.byPattern[pattern].messagesPerMinute = counter.count;
    this.stats.byPattern[pattern].totalMessages++;
    
    return { allowed: true };
  }
  
  /**
   * Check domain-specific message rate limit
   * @param domain Domain to check
   */
  private checkDomainMessageLimit(domain: string): IRateLimitResult {
    const now = Date.now();
    
    // Get domain-specific limit or use global
    const domainConfig = this.config.domains?.[domain];
    const limit = domainConfig?.maxMessagesPerMinute || this.config.global.maxMessagesPerMinute!;
    
    if (!limit) {
      return { allowed: true };
    }
    
    // Get or create counter
    let counter = this.domainCounters.get(domain);
    
    if (!counter) {
      counter = {
        count: 0,
        lastReset: now,
        recipients: 0,
        errors: 0,
        authFailures: 0,
        connections: 0
      };
      this.domainCounters.set(domain, counter);
    }
    
    // Check if counter needs to be reset
    if (now - counter.lastReset >= 60000) {
      counter.count = 0;
      counter.lastReset = now;
    }
    
    // Check if limit is exceeded
    if (counter.count >= limit) {
      // Calculate reset time
      const resetIn = 60000 - (now - counter.lastReset);
      
      logger.log('warn', `Domain ${domain} rate limit exceeded: ${counter.count}/${limit} messages per minute`);
      
      return {
        allowed: false,
        reason: `Domain "${domain}" message rate limit exceeded`,
        limit,
        current: counter.count,
        resetIn
      };
    }
    
    // Increment counter
    counter.count++;
    
    return { allowed: true };
  }
  
  /**
   * Check IP-specific message rate limit
   * @param ip IP address
   */
  private checkIpMessageLimit(ip: string): IRateLimitResult {
    const now = Date.now();
    
    // Get IP-specific limit or use global
    const ipConfig = this.config.ips?.[ip];
    const limit = ipConfig?.maxMessagesPerMinute || this.config.global.maxMessagesPerMinute!;
    
    if (!limit) {
      return { allowed: true };
    }
    
    // Get or create counter
    let counter = this.ipCounters.get(ip);
    
    if (!counter) {
      counter = {
        count: 0,
        lastReset: now,
        recipients: 0,
        errors: 0,
        authFailures: 0,
        connections: 0
      };
      this.ipCounters.set(ip, counter);
      
      // Initialize IP stats if needed
      if (!this.stats.byIp[ip]) {
        this.stats.byIp[ip] = {
          messagesPerMinute: 0,
          totalMessages: 0,
          totalBlocked: 0,
          connections: 0,
          errors: 0,
          authFailures: 0,
          blocked: false
        };
      }
    }
    
    // Check if counter needs to be reset
    if (now - counter.lastReset >= 60000) {
      counter.count = 0;
      counter.lastReset = now;
    }
    
    // Check if limit is exceeded
    if (counter.count >= limit) {
      // Calculate reset time
      const resetIn = 60000 - (now - counter.lastReset);
      
      // Update statistics
      this.stats.byIp[ip].totalBlocked++;
      this.stats.totalBlocked++;
      
      return {
        allowed: false,
        reason: `IP ${ip} message rate limit exceeded`,
        limit,
        current: counter.count,
        resetIn
      };
    }
    
    // Increment counter
    counter.count++;
    
    // Update statistics
    this.stats.byIp[ip].messagesPerMinute = counter.count;
    this.stats.byIp[ip].totalMessages++;
    
    return { allowed: true };
  }
  
  /**
   * Check recipient limit
   * @param email Email address
   * @param recipients Number of recipients
   * @param pattern Matched pattern
   * @param domain Domain name
   */
  private checkRecipientLimit(email: string, recipients: number, pattern?: string, domain?: string): IRateLimitResult {
    // Get the most specific limit available
    let limit = this.config.global.maxRecipientsPerMessage!;
    
    // Check pattern-specific limit
    if (pattern && this.config.patterns?.[pattern]?.maxRecipientsPerMessage) {
      limit = this.config.patterns[pattern].maxRecipientsPerMessage!;
    }
    
    // Check domain-specific limit (overrides pattern if present)
    if (domain && this.config.domains?.[domain]?.maxRecipientsPerMessage) {
      limit = this.config.domains[domain].maxRecipientsPerMessage!;
    }
    
    if (!limit) {
      return { allowed: true };
    }
    
    // Check if limit is exceeded
    if (recipients > limit) {
      return {
        allowed: false,
        reason: 'Recipient limit exceeded',
        limit,
        current: recipients
      };
    }
    
    return { allowed: true };
  }
  
  /**
   * Record a connection from an IP
   * @param ip IP address
   * @returns Result of rate limit check
   */
  public recordConnection(ip: string): IRateLimitResult {
    const now = Date.now();
    
    // Check if IP is blocked
    if (this.isIpBlocked(ip)) {
      return {
        allowed: false,
        reason: 'IP is blocked',
        resetIn: this.getBlockReleaseTime(ip)
      };
    }
    
    // Get IP-specific limit or use global
    const ipConfig = this.config.ips?.[ip];
    const limit = ipConfig?.maxConnectionsPerIP || this.config.global.maxConnectionsPerIP!;
    
    if (!limit) {
      return { allowed: true };
    }
    
    // Get or create counter
    let counter = this.ipCounters.get(ip);
    
    if (!counter) {
      counter = {
        count: 0,
        lastReset: now,
        recipients: 0,
        errors: 0,
        authFailures: 0,
        connections: 0
      };
      this.ipCounters.set(ip, counter);
      
      // Initialize IP stats if needed
      if (!this.stats.byIp[ip]) {
        this.stats.byIp[ip] = {
          messagesPerMinute: 0,
          totalMessages: 0,
          totalBlocked: 0,
          connections: 0,
          errors: 0,
          authFailures: 0,
          blocked: false
        };
      }
    }
    
    // Check if counter needs to be reset
    if (now - counter.lastReset >= 60000) {
      counter.connections = 0;
      counter.lastReset = now;
    }
    
    // Check if limit is exceeded
    if (counter.connections >= limit) {
      // Calculate reset time
      const resetIn = 60000 - (now - counter.lastReset);
      
      // Update statistics
      this.stats.byIp[ip].totalBlocked++;
      this.stats.totalBlocked++;
      
      return {
        allowed: false,
        reason: `IP ${ip} connection rate limit exceeded`,
        limit,
        current: counter.connections,
        resetIn
      };
    }
    
    // Increment counter
    counter.connections++;
    
    // Update statistics
    this.stats.byIp[ip].connections = counter.connections;
    
    return { allowed: true };
  }
  
  /**
   * Record an error from an IP
   * @param ip IP address
   * @returns True if IP should be blocked
   */
  public recordError(ip: string): boolean {
    const now = Date.now();
    
    // Get IP-specific limit or use global
    const ipConfig = this.config.ips?.[ip];
    const limit = ipConfig?.maxErrorsPerIP || this.config.global.maxErrorsPerIP!;
    
    if (!limit) {
      return false;
    }
    
    // Get or create counter
    let counter = this.ipCounters.get(ip);
    
    if (!counter) {
      counter = {
        count: 0,
        lastReset: now,
        recipients: 0,
        errors: 0,
        authFailures: 0,
        connections: 0
      };
      this.ipCounters.set(ip, counter);
      
      // Initialize IP stats if needed
      if (!this.stats.byIp[ip]) {
        this.stats.byIp[ip] = {
          messagesPerMinute: 0,
          totalMessages: 0,
          totalBlocked: 0,
          connections: 0,
          errors: 0,
          authFailures: 0,
          blocked: false
        };
      }
    }
    
    // Check if counter needs to be reset
    if (now - counter.lastReset >= 60000) {
      counter.errors = 0;
      counter.lastReset = now;
    }
    
    // Increment counter
    counter.errors++;
    
    // Update statistics
    this.stats.byIp[ip].errors = counter.errors;
    
    // Check if limit is exceeded
    if (counter.errors >= limit) {
      // Block the IP
      this.blockIp(ip);
      
      logger.log('warn', `IP ${ip} blocked due to excessive errors (${counter.errors}/${limit})`);
      
      SecurityLogger.getInstance().logEvent({
        level: SecurityLogLevel.WARN,
        type: SecurityEventType.RATE_LIMITING,
        message: 'IP blocked due to excessive errors',
        ipAddress: ip,
        details: {
          errors: counter.errors,
          limit
        },
        success: false
      });
      
      return true;
    }
    
    return false;
  }
  
  /**
   * Record an authentication failure from an IP
   * @param ip IP address
   * @returns True if IP should be blocked
   */
  public recordAuthFailure(ip: string): boolean {
    const now = Date.now();
    
    // Get IP-specific limit or use global
    const ipConfig = this.config.ips?.[ip];
    const limit = ipConfig?.maxAuthFailuresPerIP || this.config.global.maxAuthFailuresPerIP!;
    
    if (!limit) {
      return false;
    }
    
    // Get or create counter
    let counter = this.ipCounters.get(ip);
    
    if (!counter) {
      counter = {
        count: 0,
        lastReset: now,
        recipients: 0,
        errors: 0,
        authFailures: 0,
        connections: 0
      };
      this.ipCounters.set(ip, counter);
      
      // Initialize IP stats if needed
      if (!this.stats.byIp[ip]) {
        this.stats.byIp[ip] = {
          messagesPerMinute: 0,
          totalMessages: 0,
          totalBlocked: 0,
          connections: 0,
          errors: 0,
          authFailures: 0,
          blocked: false
        };
      }
    }
    
    // Check if counter needs to be reset
    if (now - counter.lastReset >= 60000) {
      counter.authFailures = 0;
      counter.lastReset = now;
    }
    
    // Increment counter
    counter.authFailures++;
    
    // Update statistics
    this.stats.byIp[ip].authFailures = counter.authFailures;
    
    // Check if limit is exceeded
    if (counter.authFailures >= limit) {
      // Block the IP
      this.blockIp(ip);
      
      logger.log('warn', `IP ${ip} blocked due to excessive authentication failures (${counter.authFailures}/${limit})`);
      
      SecurityLogger.getInstance().logEvent({
        level: SecurityLogLevel.WARN,
        type: SecurityEventType.AUTHENTICATION,
        message: 'IP blocked due to excessive authentication failures',
        ipAddress: ip,
        details: {
          authFailures: counter.authFailures,
          limit
        },
        success: false
      });
      
      return true;
    }
    
    return false;
  }
  
  /**
   * Block an IP address
   * @param ip IP address to block
   * @param duration Override the default block duration (milliseconds)
   */
  public blockIp(ip: string, duration?: number): void {
    if (!this.config.blocks) {
      this.config.blocks = {};
    }
    
    // Set block expiry time
    const expiry = Date.now() + (duration || this.config.global.blockDuration || 3600000);
    this.config.blocks[ip] = expiry;
    
    // Update statistics
    if (!this.stats.byIp[ip]) {
      this.stats.byIp[ip] = {
        messagesPerMinute: 0,
        totalMessages: 0,
        totalBlocked: 0,
        connections: 0,
        errors: 0,
        authFailures: 0,
        blocked: false
      };
    }
    this.stats.byIp[ip].blocked = true;
    this.stats.currentlyBlocked++;
    
    // Emit event
    this.emit('ipBlocked', {
      ip,
      expiry,
      duration: duration || this.config.global.blockDuration
    });
    
    logger.log('warn', `IP ${ip} blocked until ${new Date(expiry).toISOString()}`);
  }
  
  /**
   * Unblock an IP address
   * @param ip IP address to unblock
   */
  public unblockIp(ip: string): void {
    if (!this.config.blocks) {
      return;
    }
    
    // Remove block
    delete this.config.blocks[ip];
    
    // Update statistics
    if (this.stats.byIp[ip]) {
      this.stats.byIp[ip].blocked = false;
      this.stats.currentlyBlocked--;
    }
    
    // Emit event
    this.emit('ipUnblocked', { ip });
    
    logger.log('info', `IP ${ip} unblocked`);
  }
  
  /**
   * Check if an IP is blocked
   * @param ip IP address to check
   */
  public isIpBlocked(ip: string): boolean {
    if (!this.config.blocks) {
      return false;
    }
    
    // Check if IP is in blocks
    if (!(ip in this.config.blocks)) {
      return false;
    }
    
    // Check if block has expired
    const expiry = this.config.blocks[ip];
    if (expiry <= Date.now()) {
      // Remove expired block
      delete this.config.blocks[ip];
      
      // Update statistics
      if (this.stats.byIp[ip]) {
        this.stats.byIp[ip].blocked = false;
        this.stats.currentlyBlocked--;
      }
      
      return false;
    }
    
    return true;
  }
  
  /**
   * Get the time until a block is released
   * @param ip IP address
   * @returns Milliseconds until release or 0 if not blocked
   */
  public getBlockReleaseTime(ip: string): number {
    if (!this.config.blocks || !(ip in this.config.blocks)) {
      return 0;
    }
    
    const expiry = this.config.blocks[ip];
    const now = Date.now();
    
    return expiry > now ? expiry - now : 0;
  }
  
  /**
   * Update rate limiter statistics
   */
  private updateStats(): void {
    // Update active counters count
    this.stats.activeCounters = this.counters.size + this.patternCounters.size + this.ipCounters.size;
    
    // Emit statistics update
    this.emit('statsUpdated', this.stats);
  }
  
  /**
   * Get rate limiter statistics
   */
  public getStats(): IRateLimiterStats {
    return { ...this.stats };
  }
  
  /**
   * Update rate limiter configuration
   * @param config New configuration
   */
  public updateConfig(config: Partial<IHierarchicalRateLimits>): void {
    if (config.global) {
      this.config.global = {
        ...this.config.global,
        ...config.global
      };
    }
    
    if (config.patterns) {
      this.config.patterns = {
        ...this.config.patterns,
        ...config.patterns
      };
    }
    
    if (config.ips) {
      this.config.ips = {
        ...this.config.ips,
        ...config.ips
      };
    }
    
    logger.log('info', 'Rate limiter configuration updated');
  }
  
  /**
   * Get configuration for debugging
   */
  public getConfig(): IHierarchicalRateLimits {
    return { ...this.config };
  }
  
  /**
   * Apply domain-specific rate limits
   * Merges domain limits with existing configuration
   * @param domain Domain name
   * @param limits Rate limit configuration for the domain
   */
  public applyDomainLimits(domain: string, limits: IRateLimitConfig): void {
    if (!this.config.domains) {
      this.config.domains = {};
    }
    
    // Merge the limits with any existing domain config
    this.config.domains[domain] = {
      ...this.config.domains[domain],
      ...limits
    };
    
    logger.log('info', `Applied rate limits for domain ${domain}:`, limits);
  }
  
  /**
   * Remove domain-specific rate limits
   * @param domain Domain name
   */
  public removeDomainLimits(domain: string): void {
    if (this.config.domains && this.config.domains[domain]) {
      delete this.config.domains[domain];
      // Also remove the counter
      this.domainCounters.delete(domain);
      logger.log('info', `Removed rate limits for domain ${domain}`);
    }
  }
  
  /**
   * Get domain-specific rate limits
   * @param domain Domain name
   * @returns Domain rate limit config or undefined
   */
  public getDomainLimits(domain: string): IRateLimitConfig | undefined {
    return this.config.domains?.[domain];
  }
}