/**
 * Simple in-memory cache with TTL support
 */
import type { TUniversalValue } from '@robota-sdk/agent-core';

interface IWebCacheEntry<T> {
  data: T;
  timestamp: number;
  ttl: number;
}

export class SimpleCache<TValue extends TUniversalValue = TUniversalValue> {
  private cache = new Map<string, IWebCacheEntry<TValue>>();
  private defaultTTL = 5 * 60 * 1000; // 5 minutes

  /**
   * Get value from cache
   */
  get(key: string): TValue | null {
    const entry = this.cache.get(key);
    if (!entry) return null;

    // Check if expired
    if (Date.now() - entry.timestamp > entry.ttl) {
      this.cache.delete(key);
      return null;
    }

    return entry.data;
  }

  /**
   * Set value in cache with optional TTL
   */
  set(key: string, data: TValue, ttl?: number): void {
    this.cache.set(key, {
      data,
      timestamp: Date.now(),
      ttl: ttl || this.defaultTTL,
    });
  }

  /**
   * Delete value from cache
   */
  delete(key: string): void {
    this.cache.delete(key);
  }

  /**
   * Clear all cache entries
   */
  clear(): void {
    this.cache.clear();
  }

  /**
   * Get cache size
   */
  size(): number {
    return this.cache.size;
  }

  /**
   * Clean up expired entries
   */
  cleanup(): void {
    const now = Date.now();
    for (const [key, entry] of this.cache.entries()) {
      if (now - entry.timestamp > entry.ttl) {
        this.cache.delete(key);
      }
    }
  }

  /**
   * Get or set pattern - if value exists return it, otherwise compute and cache
   */
  async getOrSet(
    key: string,
    factory: () => Promise<TValue> | TValue,
    ttl?: number,
  ): Promise<TValue> {
    const cached = this.get(key);
    if (cached !== null) {
      return cached;
    }

    const value = await factory();
    this.set(key, value, ttl);
    return value;
  }
}

// Cache instances for different data types
const userCache = new SimpleCache();
const apiCache = new SimpleCache();

// Default cache instance
export const cache = new SimpleCache();

// Cleanup expired entries every 10 minutes
if (typeof window !== 'undefined') {
  setInterval(
    () => {
      cache.cleanup();
      userCache.cleanup();
      apiCache.cleanup();
    },
    10 * 60 * 1000,
  );
}
