import { redis } from "./redis";

interface RateLimitConfig {
  windowMs: number;
  maxAttempts: number;
}

interface RateLimitResult {
  allowed: boolean;
  remaining: number;
  resetAt: number;
}

export async function checkRateLimit(
  key: string,
  config: RateLimitConfig
): Promise<RateLimitResult> {
  const now = Date.now();
  const windowStart = now - config.windowMs;
  const redisKey = `rl:${key}`;

  try {
    await redis.zremrangebyscore(redisKey, 0, windowStart);
    const count = await redis.zcard(redisKey);

    if (count >= config.maxAttempts) {
      const oldestEntry = await redis.zrange(redisKey, 0, 0, "WITHSCORES");
      const resetAt = oldestEntry.length >= 2
        ? parseInt(oldestEntry[1], 10) + config.windowMs
        : now + config.windowMs;
      return { allowed: false, remaining: 0, resetAt };
    }

    await redis.zadd(redisKey, now, `${now}:${Math.random()}`);
    await redis.pexpire(redisKey, config.windowMs);

    return {
      allowed: true,
      remaining: config.maxAttempts - count - 1,
      resetAt: now + config.windowMs,
    };
  } catch {
    return { allowed: true, remaining: config.maxAttempts, resetAt: now + config.windowMs };
  }
}

export const AUTH_RATE_LIMITS = {
  login: { windowMs: 15 * 60 * 1000, maxAttempts: 10 },
  register: { windowMs: 60 * 60 * 1000, maxAttempts: 5 },
  forgotPassword: { windowMs: 60 * 60 * 1000, maxAttempts: 5 },
  resetPassword: { windowMs: 15 * 60 * 1000, maxAttempts: 5 },
} as const;
