import { LRUCache } from "lru-cache";

export interface RateLimitResult {
  success: boolean;
  remaining: number;
  resetAt: number;
}

interface Bucket {
  count: number;
  resetAt: number;
}

export class RateLimiter {
  private cache: LRUCache<string, Bucket>;
  private maxTokens: number;
  private windowMs: number;

  constructor(maxTokens: number, windowMs: number, capacity = 10000) {
    this.maxTokens = maxTokens;
    this.windowMs = windowMs;
    this.cache = new LRUCache<string, Bucket>({
      max: capacity,
      ttl: windowMs,
      ttlResolution: windowMs,
    });
  }

  limit(key: string): RateLimitResult {
    const now = Date.now();
    const existing = this.cache.get(key);
    if (!existing || existing.resetAt <= now) {
      const resetAt = now + this.windowMs;
      const bucket: Bucket = { count: 1, resetAt };
      this.cache.set(key, bucket);
      return { success: true, remaining: this.maxTokens - 1, resetAt };
    }
    if (existing.count >= this.maxTokens) {
      return { success: false, remaining: 0, resetAt: existing.resetAt };
    }
    existing.count += 1;
    return {
      success: true,
      remaining: this.maxTokens - existing.count,
      resetAt: existing.resetAt,
    };
  }
}

export const adminLoginLimiter = new RateLimiter(5, 60_000);
export const validateCodeLimiter = new RateLimiter(20, 60_000);
export const checkSubdomainLimiter = new RateLimiter(60, 60_000);
export const uploadLimiter = new RateLimiter(10, 60_000);

export function rateLimitHeaders(result: RateLimitResult): Record<string, string> {
  return {
    "X-RateLimit-Limit": String(result.success ? result.remaining + 1 : result.remaining),
    "X-RateLimit-Remaining": String(Math.max(result.remaining, 0)),
    "X-RateLimit-Reset": String(Math.floor(result.resetAt / 1000)),
  };
}
