/**
 * LRU cache for filter decisions.
 *
 * Caches whether a given tool name + response size combination should be
 * filtered by the LLM pipeline. Avoids redundant LLM calls for repeated
 * queries that produce similar-sized responses.
 */

export interface FilterCacheConfig {
  /** Maximum number of entries in the cache (default 256) */
  maxEntries: number;
  /** TTL in milliseconds for cache entries (default 3_600_000 = 1 hour) */
  ttlMs: number;
}

export const DEFAULT_FILTER_CACHE_CONFIG: FilterCacheConfig = {
  maxEntries: 256,
  ttlMs: 3_600_000,
};

interface CacheEntry {
  shouldFilter: boolean;
  createdAt: number;
}

/**
 * Simple LRU cache for filter decisions keyed by tool name.
 *
 * Uses a Map to maintain insertion order for LRU eviction.
 * No external dependencies.
 */
export class FilterCache {
  private cache = new Map<string, CacheEntry>();
  private readonly config: FilterCacheConfig;

  constructor(config: Partial<FilterCacheConfig> = {}) {
    this.config = { ...DEFAULT_FILTER_CACHE_CONFIG, ...config };
  }

  /**
   * Look up a cached filter decision.
   *
   * @param toolName - The MCP tool name.
   * @returns `true`/`false` if a cached decision exists, or `null` if no valid entry.
   */
  shouldFilter(toolName: string): boolean | null {
    const entry = this.cache.get(toolName);
    if (!entry) return null;

    // Check TTL expiration
    if (Date.now() - entry.createdAt > this.config.ttlMs) {
      this.cache.delete(toolName);
      return null;
    }

    // Move to end for LRU freshness
    this.cache.delete(toolName);
    this.cache.set(toolName, entry);

    return entry.shouldFilter;
  }

  /**
   * Record a filter decision in the cache.
   *
   * @param toolName - The MCP tool name.
   * @param shouldFilter - Whether the response should be filtered.
   */
  recordDecision(toolName: string, shouldFilter: boolean): void {
    // If already present, remove to refresh position
    this.cache.delete(toolName);

    // Evict oldest entry if at capacity
    if (this.cache.size >= this.config.maxEntries) {
      const oldest = this.cache.keys().next();
      if (!oldest.done) {
        this.cache.delete(oldest.value);
      }
    }

    this.cache.set(toolName, {
      shouldFilter,
      createdAt: Date.now(),
    });
  }

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

  /** Number of entries currently in the cache. */
  get size(): number {
    return this.cache.size;
  }
}
