const DEFAULT_CONFIG = {
  maxPerMinute: 10,
  maxPerHour: 100,
  maxPerDay: 1e3
};
const MINUTE_MS = 60 * 1e3;
const HOUR_MS = 60 * 60 * 1e3;
const DAY_MS = 24 * 60 * 60 * 1e3;
const fallbackBuckets = /* @__PURE__ */ new Map();
const FALLBACK_MAX_KEYS = 1e4;
function pruneFallbackBuckets(now) {
  if (fallbackBuckets.size <= FALLBACK_MAX_KEYS) return;
  for (const [key, timestamps] of fallbackBuckets) {
    const recent = timestamps.filter((timestamp) => timestamp > now - DAY_MS);
    if (recent.length === 0) {
      fallbackBuckets.delete(key);
    } else {
      fallbackBuckets.set(key, recent);
    }
    if (fallbackBuckets.size <= FALLBACK_MAX_KEYS) break;
  }
}
function evaluate(timestamps, now, config) {
  const cutoffDay = now - DAY_MS;
  const recentTimestamps = timestamps.filter((timestamp) => timestamp > cutoffDay);
  const countPerMinute = recentTimestamps.filter((timestamp) => timestamp > now - MINUTE_MS).length;
  if (countPerMinute >= config.maxPerMinute) {
    const oldestInWindow = recentTimestamps.find((timestamp) => timestamp > now - MINUTE_MS);
    const retryAfter = oldestInWindow ? Math.ceil((oldestInWindow + MINUTE_MS - now) / 1e3) : 60;
    return { result: { allowed: false, retryAfterSeconds: retryAfter }, nextTimestamps: recentTimestamps };
  }
  const countPerHour = recentTimestamps.filter((timestamp) => timestamp > now - HOUR_MS).length;
  if (countPerHour >= config.maxPerHour) {
    const oldestInWindow = recentTimestamps.find((timestamp) => timestamp > now - HOUR_MS);
    const retryAfter = oldestInWindow ? Math.ceil((oldestInWindow + HOUR_MS - now) / 1e3) : 3600;
    return { result: { allowed: false, retryAfterSeconds: retryAfter }, nextTimestamps: recentTimestamps };
  }
  if (recentTimestamps.length >= config.maxPerDay) {
    const oldestInWindow = recentTimestamps[0];
    const retryAfter = oldestInWindow ? Math.ceil((oldestInWindow + DAY_MS - now) / 1e3) : 86400;
    return { result: { allowed: false, retryAfterSeconds: retryAfter }, nextTimestamps: recentTimestamps };
  }
  recentTimestamps.push(now);
  return { result: { allowed: true }, nextTimestamps: recentTimestamps };
}
function checkFallback(key, now, config) {
  const cacheKey = `inbox_ops:rate_limit:${key}`;
  const existing = fallbackBuckets.get(cacheKey) ?? [];
  const { result, nextTimestamps } = evaluate(existing, now, config);
  fallbackBuckets.set(cacheKey, nextTimestamps);
  pruneFallbackBuckets(now);
  return result;
}
async function checkRateLimit(cache, key, tenantId, config = DEFAULT_CONFIG) {
  const now = Date.now();
  if (!cache) {
    return checkFallback(key, now, config);
  }
  const cacheKey = `inbox_ops:rate_limit:${key}`;
  try {
    const raw = await cache.get(cacheKey);
    const timestamps = Array.isArray(raw) ? raw : [];
    const { result, nextTimestamps } = evaluate(timestamps, now, config);
    if (!result.allowed) {
      return result;
    }
    const tags = tenantId ? [`inbox_ops:rate_limit:${tenantId}`] : [];
    await cache.set(cacheKey, nextTimestamps, { ttl: DAY_MS, tags });
    return result;
  } catch {
    return checkFallback(key, now, config);
  }
}
function __resetRateLimiterFallback() {
  fallbackBuckets.clear();
}
export {
  __resetRateLimiterFallback,
  checkRateLimit
};
//# sourceMappingURL=rateLimiter.js.map
