import { getRedis } from "./redis";
import { NextResponse } from "next/server";

export async function rateLimit(
  key: string,
  limit: number,
  windowSeconds: number
): Promise<{ ok: boolean; remaining: number; reset: number }> {
  const redis = getRedis();
  const now = Date.now();
  const windowStart = now - windowSeconds * 1000;
  const reset = Math.ceil((now + windowSeconds * 1000) / 1000);

  const pipeline = redis.pipeline();
  pipeline.zremrangebyscore(key, "-inf", windowStart);
  pipeline.zadd(key, now, `${now}-${Math.random()}`);
  pipeline.zcard(key);
  pipeline.expire(key, windowSeconds);
  const results = await pipeline.exec();

  const count = (results?.[2]?.[1] as number) ?? 0;
  const remaining = Math.max(0, limit - count);
  const ok = count <= limit;

  return { ok, remaining, reset };
}

export async function applyRateLimit(
  key: string,
  limit: number,
  windowSeconds: number
): Promise<NextResponse | null> {
  const { ok, remaining, reset } = await rateLimit(key, limit, windowSeconds);

  if (!ok) {
    return NextResponse.json(
      { error: "Too many requests", retryAfter: reset },
      {
        status: 429,
        headers: {
          "X-RateLimit-Limit": String(limit),
          "X-RateLimit-Remaining": "0",
          "X-RateLimit-Reset": String(reset),
          "Retry-After": String(reset - Math.floor(Date.now() / 1000)),
        },
      }
    );
  }

  return null;
}
