// ==================================================================================================
// Rate limiter sederhana, in-memory (tanpa dependency).
// Cocok buat single-instance. Sliding window per-key (mis. IP) dengan lockout.
//
// Pakai:
//   const rl = createRateLimiter({ windowMs: 15*60_000, max: 5, lockoutMs: 15*60_000 });
//   const r = rl.check(ip);   // { allowed, remaining, retryAfter }
//   if (!r.allowed) -> 429
//   rl.reset(ip)              // panggil saat login SUKSES
// ==================================================================================================

export function createRateLimiter({ windowMs = 15 * 60_000, max = 5, lockoutMs = 0 } = {}) {
  const hits = new Map();      // key -> number[] (timestamps)
  const lockedUntil = new Map(); // key -> epoch ms

  // Bersih-bersih berkala biar Map gak numpuk
  const sweep = () => {
    const now = Date.now();
    for (const [k, arr] of hits) {
      const fresh = arr.filter(t => now - t < windowMs);
      if (fresh.length) hits.set(k, fresh); else hits.delete(k);
    }
    for (const [k, until] of lockedUntil) {
      if (until <= now) lockedUntil.delete(k);
    }
  };
  const timer = setInterval(sweep, Math.min(windowMs, 60_000));
  if (timer.unref) timer.unref(); // jangan tahan proses exit

  return {
    // Catat 1 percobaan & cek apakah masih boleh
    check(key) {
      const now = Date.now();
      const lock = lockedUntil.get(key);
      if (lock && lock > now) {
        return { allowed: false, remaining: 0, retryAfter: Math.ceil((lock - now) / 1000) };
      }
      const arr = (hits.get(key) || []).filter(t => now - t < windowMs);
      arr.push(now);
      hits.set(key, arr);

      if (arr.length > max) {
        if (lockoutMs > 0) lockedUntil.set(key, now + lockoutMs);
        const retryAfter = Math.ceil((lockoutMs > 0 ? lockoutMs : windowMs) / 1000);
        return { allowed: false, remaining: 0, retryAfter };
      }
      return { allowed: true, remaining: max - arr.length, retryAfter: 0 };
    },
    // Reset counter (dipanggil saat aksi sukses, mis. login berhasil)
    reset(key) {
      hits.delete(key);
      lockedUntil.delete(key);
    },
  };
}
