import { createHmac, randomBytes } from "node:crypto";
const DEFAULT_SUCCESS_TTL_MS = 3e4;
const DEFAULT_NEGATIVE_TTL_MS = 5e3;
const DEFAULT_LAST_USED_WRITE_INTERVAL_MS = 6e4;
const DEFAULT_MAX_ENTRIES = 1e3;
const FINGERPRINT_BYTES = 16;
function createSecretFingerprinter() {
  const key = randomBytes(32);
  return (secret) => createHmac("sha256", key).update(secret, "utf8").digest("hex").slice(0, FINGERPRINT_BYTES * 2);
}
function resolveTtlEnv(name, fallback) {
  const raw = process.env?.[name];
  if (!raw) return fallback;
  const parsed = Number(raw);
  if (!Number.isFinite(parsed) || parsed < 0) return fallback;
  return parsed;
}
function createApiKeyAuthCache(options = {}) {
  const successTtlMs = options.successTtlMs ?? resolveTtlEnv("OM_API_KEY_AUTH_TTL_MS", DEFAULT_SUCCESS_TTL_MS);
  const negativeTtlMs = options.negativeTtlMs ?? resolveTtlEnv("OM_API_KEY_AUTH_NEGATIVE_TTL_MS", DEFAULT_NEGATIVE_TTL_MS);
  const lastUsedWriteIntervalMs = options.lastUsedWriteIntervalMs ?? resolveTtlEnv(
    "OM_API_KEY_LAST_USED_WRITE_INTERVAL_MS",
    DEFAULT_LAST_USED_WRITE_INTERVAL_MS
  );
  const maxEntries = options.maxEntries ?? DEFAULT_MAX_ENTRIES;
  const now = options.now ?? (() => Date.now());
  const fingerprint = createSecretFingerprinter();
  const entries = /* @__PURE__ */ new Map();
  const lastUsedWrites = /* @__PURE__ */ new Map();
  function touch(key, entry) {
    entries.delete(key);
    entries.set(key, entry);
    if (entries.size > maxEntries) {
      const oldest = entries.keys().next().value;
      if (typeof oldest === "string") entries.delete(oldest);
    }
  }
  function purgeStale(key, entry, currentMs) {
    if (entry.expiresAtMs > currentMs) return false;
    entries.delete(key);
    return true;
  }
  return {
    get(secret) {
      if (!secret) return void 0;
      const key = fingerprint(secret);
      const entry = entries.get(key);
      if (!entry) return void 0;
      const currentMs = now();
      if (purgeStale(key, entry, currentMs)) return void 0;
      entries.delete(key);
      entries.set(key, entry);
      return entry.auth;
    },
    setSuccess(secret, auth, expiresAtMs) {
      if (!secret) return;
      if (successTtlMs <= 0) return;
      const currentMs = now();
      const ttlEnd = currentMs + successTtlMs;
      const effectiveExpiry = expiresAtMs != null ? Math.min(ttlEnd, expiresAtMs) : ttlEnd;
      if (effectiveExpiry <= currentMs) return;
      touch(fingerprint(secret), { auth, cachedAtMs: currentMs, expiresAtMs: effectiveExpiry });
    },
    setMiss(secret) {
      if (!secret) return;
      if (negativeTtlMs <= 0) return;
      const currentMs = now();
      touch(fingerprint(secret), { auth: null, cachedAtMs: currentMs, expiresAtMs: currentMs + negativeTtlMs });
    },
    invalidateByKeyId(keyId) {
      if (!keyId) return;
      for (const [key, entry] of entries) {
        const auth = entry.auth;
        if (auth && typeof auth === "object" && auth.keyId === keyId) {
          entries.delete(key);
        }
      }
      lastUsedWrites.delete(keyId);
    },
    shouldWriteLastUsed(keyId) {
      if (!keyId) return true;
      if (lastUsedWriteIntervalMs <= 0) return true;
      const currentMs = now();
      const previous = lastUsedWrites.get(keyId);
      if (previous != null && currentMs - previous < lastUsedWriteIntervalMs) return false;
      lastUsedWrites.set(keyId, currentMs);
      return true;
    },
    clear() {
      entries.clear();
      lastUsedWrites.clear();
    },
    size() {
      return entries.size;
    },
    inspectEntryKeysForTests() {
      return Array.from(entries.keys());
    }
  };
}
let sharedCache = null;
function getSharedApiKeyAuthCache() {
  if (!sharedCache) sharedCache = createApiKeyAuthCache();
  return sharedCache;
}
function resetSharedApiKeyAuthCacheForTests() {
  sharedCache = null;
}
export {
  createApiKeyAuthCache,
  getSharedApiKeyAuthCache,
  resetSharedApiKeyAuthCacheForTests
};
//# sourceMappingURL=apiKeyAuthCache.js.map
