import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import { logger } from "../monitoring/logger.js";
class LRUQueryCache {
  cache = /* @__PURE__ */ new Map();
  maxSize;
  ttlMs;
  enableMetrics;
  // Metrics
  metrics = {
    hits: 0,
    misses: 0,
    evictions: 0,
    totalQueries: 0
  };
  constructor(options = {}) {
    this.maxSize = options.maxSize ?? 1e3;
    this.ttlMs = options.ttlMs ?? 3e5;
    this.enableMetrics = options.enableMetrics ?? true;
    logger.info("Query cache initialized", {
      maxSize: this.maxSize,
      ttlMs: this.ttlMs,
      enableMetrics: this.enableMetrics
    });
  }
  /**
   * Get a value from cache
   */
  get(key) {
    if (this.enableMetrics) {
      this.metrics.totalQueries++;
    }
    const entry = this.cache.get(key);
    if (!entry) {
      if (this.enableMetrics) {
        this.metrics.misses++;
      }
      return void 0;
    }
    const now = Date.now();
    if (now - entry.createdAt > this.ttlMs) {
      this.cache.delete(key);
      if (this.enableMetrics) {
        this.metrics.misses++;
        this.metrics.evictions++;
      }
      logger.debug("Cache entry expired", { key, age: now - entry.createdAt });
      return void 0;
    }
    entry.accessCount++;
    entry.lastAccessed = now;
    this.cache.delete(key);
    this.cache.set(key, entry);
    if (this.enableMetrics) {
      this.metrics.hits++;
    }
    logger.debug("Cache hit", { key, accessCount: entry.accessCount });
    return entry.value;
  }
  /**
   * Set a value in cache
   */
  set(key, value) {
    const now = Date.now();
    if (this.cache.has(key)) {
      this.cache.delete(key);
    }
    while (this.cache.size >= this.maxSize) {
      const firstKey = this.cache.keys().next().value;
      if (firstKey !== void 0) {
        this.cache.delete(firstKey);
        if (this.enableMetrics) {
          this.metrics.evictions++;
        }
        logger.debug("Evicted LRU entry", { key: firstKey });
      } else {
        break;
      }
    }
    const entry = {
      value,
      createdAt: now,
      accessCount: 0,
      lastAccessed: now
    };
    this.cache.set(key, entry);
    logger.debug("Cache set", { key, size: this.cache.size });
  }
  /**
   * Delete a specific key
   */
  delete(key) {
    const deleted = this.cache.delete(key);
    if (deleted) {
      logger.debug("Cache delete", { key });
    }
    return deleted;
  }
  /**
   * Clear all cached entries
   */
  clear() {
    const size = this.cache.size;
    this.cache.clear();
    logger.info("Cache cleared", { previousSize: size });
  }
  /**
   * Invalidate entries matching a pattern
   */
  invalidatePattern(pattern) {
    let count = 0;
    for (const key of this.cache.keys()) {
      if (pattern.test(key)) {
        this.cache.delete(key);
        count++;
      }
    }
    logger.info("Pattern invalidation", {
      pattern: pattern.source,
      invalidated: count
    });
    return count;
  }
  /**
   * Get cache metrics
   */
  getMetrics() {
    return {
      ...this.metrics,
      hitRate: this.metrics.totalQueries > 0 ? this.metrics.hits / this.metrics.totalQueries : 0,
      size: this.cache.size,
      maxSize: this.maxSize
    };
  }
  /**
   * Get cache contents for debugging
   */
  debug() {
    return Array.from(this.cache.entries()).map(([key, entry]) => ({
      key,
      entry
    }));
  }
  /**
   * Cleanup expired entries
   */
  cleanup() {
    const now = Date.now();
    let removed = 0;
    for (const [key, entry] of this.cache.entries()) {
      if (now - entry.createdAt > this.ttlMs) {
        this.cache.delete(key);
        removed++;
        if (this.enableMetrics) {
          this.metrics.evictions++;
        }
      }
    }
    if (removed > 0) {
      logger.info("Cache cleanup completed", {
        removed,
        remaining: this.cache.size
      });
    }
    return removed;
  }
}
class StackMemoryQueryCache {
  frameCache = new LRUQueryCache({ maxSize: 500, ttlMs: 3e5 });
  // 5 min
  eventCache = new LRUQueryCache({ maxSize: 1e3, ttlMs: 18e4 });
  // 3 min
  anchorCache = new LRUQueryCache({ maxSize: 200, ttlMs: 6e5 });
  // 10 min
  digestCache = new LRUQueryCache({ maxSize: 100, ttlMs: 9e5 });
  // 15 min
  /**
   * Cache frame data
   */
  cacheFrame(frameId, data) {
    this.frameCache.set(`frame:${frameId}`, data);
  }
  getFrame(frameId) {
    return this.frameCache.get(`frame:${frameId}`);
  }
  /**
   * Cache frame context assemblies (expensive operations)
   */
  cacheFrameContext(frameId, context) {
    this.frameCache.set(`context:${frameId}`, context);
  }
  getFrameContext(frameId) {
    return this.frameCache.get(`context:${frameId}`);
  }
  /**
   * Cache events for a frame
   */
  cacheFrameEvents(frameId, events) {
    this.eventCache.set(`events:${frameId}`, events);
  }
  getFrameEvents(frameId) {
    return this.eventCache.get(`events:${frameId}`);
  }
  /**
   * Cache anchors
   */
  cacheAnchors(frameId, anchors) {
    this.anchorCache.set(`anchors:${frameId}`, anchors);
  }
  getAnchors(frameId) {
    return this.anchorCache.get(`anchors:${frameId}`);
  }
  /**
   * Cache digest data
   */
  cacheDigest(frameId, digest) {
    this.digestCache.set(`digest:${frameId}`, digest);
  }
  getDigest(frameId) {
    return this.digestCache.get(`digest:${frameId}`);
  }
  /**
   * Invalidate caches for a specific frame
   */
  invalidateFrame(frameId) {
    this.frameCache.delete(`frame:${frameId}`);
    this.frameCache.delete(`context:${frameId}`);
    this.eventCache.delete(`events:${frameId}`);
    this.anchorCache.delete(`anchors:${frameId}`);
    this.digestCache.delete(`digest:${frameId}`);
    logger.info("Invalidated frame caches", { frameId });
  }
  /**
   * Invalidate all caches for a project
   */
  invalidateProject(projectId) {
    const pattern = new RegExp(`^(frame|context|events|anchors|digest):.+`);
    let total = 0;
    total += this.frameCache.invalidatePattern(pattern);
    total += this.eventCache.invalidatePattern(pattern);
    total += this.anchorCache.invalidatePattern(pattern);
    total += this.digestCache.invalidatePattern(pattern);
    logger.info("Invalidated project caches", {
      projectId,
      totalInvalidated: total
    });
  }
  /**
   * Get comprehensive cache metrics
   */
  getMetrics() {
    return {
      frame: this.frameCache.getMetrics(),
      event: this.eventCache.getMetrics(),
      anchor: this.anchorCache.getMetrics(),
      digest: this.digestCache.getMetrics()
    };
  }
  /**
   * Cleanup all caches
   */
  cleanup() {
    this.frameCache.cleanup();
    this.eventCache.cleanup();
    this.anchorCache.cleanup();
    this.digestCache.cleanup();
  }
  /**
   * Clear all caches
   */
  clear() {
    this.frameCache.clear();
    this.eventCache.clear();
    this.anchorCache.clear();
    this.digestCache.clear();
    logger.info("All StackMemory caches cleared");
  }
}
let globalCache = null;
function getQueryCache() {
  if (!globalCache) {
    globalCache = new StackMemoryQueryCache();
  }
  return globalCache;
}
function createCacheKey(queryName, params) {
  const paramsStr = params.map((p) => typeof p === "object" ? JSON.stringify(p) : String(p)).join(":");
  return `${queryName}:${paramsStr}`;
}
export {
  LRUQueryCache,
  StackMemoryQueryCache,
  createCacheKey,
  getQueryCache
};
//# sourceMappingURL=query-cache.js.map
