export interface ICacheEntry<T> {
  data: T;
  timestamp: number;
}

export class MetricsCache {
  private cache = new Map<string, ICacheEntry<any>>();
  private readonly defaultTTL: number;
  
  constructor(defaultTTL: number = 500) {
    this.defaultTTL = defaultTTL;
  }
  
  /**
   * Get cached data or compute and cache it
   */
  public get<T>(key: string, computeFn: () => T | Promise<T>, ttl?: number): T | Promise<T> {
    const cached = this.cache.get(key);
    const now = Date.now();
    const actualTTL = ttl ?? this.defaultTTL;
    
    if (cached && (now - cached.timestamp) < actualTTL) {
      return cached.data;
    }
    
    const result = computeFn();
    
    // Handle both sync and async compute functions
    if (result instanceof Promise) {
      return result.then(data => {
        this.cache.set(key, { data, timestamp: now });
        return data;
      });
    } else {
      this.cache.set(key, { data: result, timestamp: now });
      return result;
    }
  }
  
  /**
   * Invalidate a specific cache entry
   */
  public invalidate(key: string): void {
    this.cache.delete(key);
  }
  
  /**
   * Clear all cache entries
   */
  public clear(): void {
    this.cache.clear();
  }
  
  /**
   * Get cache statistics
   */
  public getStats(): { size: number; keys: string[] } {
    return {
      size: this.cache.size,
      keys: Array.from(this.cache.keys())
    };
  }
  
  /**
   * Clean up expired entries
   */
  public cleanup(): void {
    const now = Date.now();
    for (const [key, entry] of this.cache.entries()) {
      if (now - entry.timestamp > this.defaultTTL) {
        this.cache.delete(key);
      }
    }
  }
}