import { SemanticCacheManagerImpl } from './SemanticCacheManager';
import { SemanticCacheEntry, SemanticCacheManager } from "../types/cache";
import { EmbeddingProvider } from "../types/provider";

export interface CacheEntryWithTTL extends SemanticCacheEntry {
  createdAt: number;
  expiresAt: number;
}

export class EnhancedSemanticCacheManager implements SemanticCacheManager {
  private cacheManager: SemanticCacheManagerImpl;
  private defaultTTL: number = 3600000; // 1 hour in milliseconds
  private embeddingProvider: EmbeddingProvider;

  constructor(embeddingProvider: EmbeddingProvider, defaultTTL?: number) {
    this.cacheManager = new SemanticCacheManagerImpl(embeddingProvider);
    this.embeddingProvider = embeddingProvider;
    if (defaultTTL) {
      this.defaultTTL = defaultTTL;
    }
  }

  async set(key: string, value: any, ttl?: number): Promise<void> {
    const actualTTL = ttl || this.defaultTTL;
    const entry: CacheEntryWithTTL = {
      key,
      value,
      embedding: await this.embeddingProvider.embed(key),
      expiresAt: Date.now() + actualTTL,
      createdAt: Date.now(),
    };
    await this.cacheManager.set(key, entry, actualTTL);
  }

  async get(key: string): Promise<any> {
    const entry = await this.cacheManager.get(key) as CacheEntryWithTTL | undefined;
    if (entry && entry.expiresAt > Date.now()) {
      return entry.value;
    }
    return undefined;
  }

  async refresh(key: string): Promise<void> {
    const entry = await this.cacheManager.get(key) as CacheEntryWithTTL | undefined;
    if (entry) {
      const newTTL = entry.expiresAt - entry.createdAt;
      await this.set(key, entry.value, newTTL);
    }
  }

  async delete(key: string): Promise<void> {
    await this.cacheManager.delete(key);
  }

  async clear(): Promise<void> {
    await this.cacheManager.clear();
  }

  async search(query: string, threshold: number): Promise<SemanticCacheEntry[]> {
    const results = await this.cacheManager.search(query, threshold) as CacheEntryWithTTL[];
    return results.filter(entry => entry.expiresAt > Date.now());
  }

  setDefaultTTL(ttl: number): void {
    this.defaultTTL = ttl;
  }

  getDefaultTTL(): number {
    return this.defaultTTL;
  }
}