/**
 * Site Tag — In-Memory Cache & Rate Limiter
 * --------------------------------------------
 * Production optimizations for the /api/collect endpoint.
 *
 * 1. SITE CACHE: caches TrackedSite lookups so we don't hit the DB
 *    on every single event. Entries expire after 60 seconds.
 *
 * 2. RATE LIMITER: limits events per siteId to prevent abuse.
 *    Default: 100 events per minute per site.
 *
 * Both use simple Map-based storage (no Redis needed for Phase 1).
 * In a multi-server deployment, replace with Redis.
 */

// ─── Site Cache ──────────────────────────────────────────────────────────────

interface CachedSite {
  id: string;
  siteId: string;
  brandId: string;
  status: string;
  allowedDomains: string[];
  fetchedAt: number;
}

const siteCache = new Map<string, CachedSite>();
const CACHE_TTL_MS = 60_000; // 60 seconds

/**
 * Get a cached site by siteId. Returns null if not cached or expired.
 */
export function getCachedSite(siteId: string): CachedSite | null {
  const entry = siteCache.get(siteId);
  if (!entry) return null;
  if (Date.now() - entry.fetchedAt > CACHE_TTL_MS) {
    siteCache.delete(siteId);
    return null;
  }
  return entry;
}

/**
 * Store a site in the cache.
 */
export function setCachedSite(site: { id: string; siteId: string; brandId: string; status: string; allowedDomains: string[] }): void {
  siteCache.set(site.siteId, { ...site, fetchedAt: Date.now() });
}

/**
 * Remove a site from the cache (call when status or domains change).
 */
export function invalidateSiteCache(siteId: string): void {
  siteCache.delete(siteId);
}

// ─── Rate Limiter ────────────────────────────────────────────────────────────

interface RateBucket {
  count: number;
  windowStart: number;
}

const rateBuckets = new Map<string, RateBucket>();
const RATE_WINDOW_MS = 60_000;       // 1-minute window
const RATE_LIMIT_PER_WINDOW = 100;   // max 100 events per site per minute

/**
 * Check if a siteId is within its rate limit.
 * Returns { allowed: true } or { allowed: false, retryAfterMs }.
 */
export function checkRateLimit(siteId: string): { allowed: boolean; retryAfterMs?: number } {
  const now = Date.now();
  const bucket = rateBuckets.get(siteId);

  if (!bucket || now - bucket.windowStart > RATE_WINDOW_MS) {
    // Start a new window
    rateBuckets.set(siteId, { count: 1, windowStart: now });
    return { allowed: true };
  }

  if (bucket.count >= RATE_LIMIT_PER_WINDOW) {
    const retryAfterMs = RATE_WINDOW_MS - (now - bucket.windowStart);
    return { allowed: false, retryAfterMs };
  }

  bucket.count++;
  return { allowed: true };
}

// ─── Cleanup (prevent memory leaks) ─────────────────────────────────────────

/**
 * Remove expired cache entries and old rate buckets.
 * Call this on an interval (e.g. every 5 minutes).
 */
export function cleanupCaches(): void {
  const now = Date.now();

  for (const [key, entry] of siteCache) {
    if (now - entry.fetchedAt > CACHE_TTL_MS * 2) siteCache.delete(key);
  }

  for (const [key, bucket] of rateBuckets) {
    if (now - bucket.windowStart > RATE_WINDOW_MS * 2) rateBuckets.delete(key);
  }
}

// Auto-cleanup every 5 minutes
if (typeof setInterval !== "undefined") {
  setInterval(cleanupCaches, 5 * 60_000);
}
