import type { MiddlewareHandler } from 'hono';

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

const DEFAULT_CONFIG: RateLimitConfig = { windowMs: 60_000, maxRequests: 100 };

// Initial bulk sync from a Mac with thousands of conversations pushes batches in
// parallel. The pre-merge ceiling (600/min) bottlenecked first-time syncs at ~6h
// real-time. Trusted single-tenant deployment, so the client limit is generous.
const SURFACE_RATE_LIMITS: Record<string, RateLimitConfig> = {
  client: { windowMs: 60_000, maxRequests: 20_000 },
  my: { windowMs: 60_000, maxRequests: 300 },
  admin: { windowMs: 60_000, maxRequests: 200 },
};

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

const buckets = new Map<string, Bucket>();

setInterval(() => {
  const now = Date.now();
  for (const [key, bucket] of buckets) {
    if (now >= bucket.resetAt) buckets.delete(key);
  }
}, 300_000);

export function rateLimitMiddleware(surface: string): MiddlewareHandler {
  const config = SURFACE_RATE_LIMITS[surface] ?? DEFAULT_CONFIG;

  return async (c, next) => {
    const ip =
      c.req.header('x-forwarded-for')?.split(',')[0]?.trim() ??
      c.req.header('x-real-ip') ??
      'unknown';
    const key = `${surface}:${ip}`;
    const now = Date.now();
    const bucket = buckets.get(key);

    if (bucket && now < bucket.resetAt) {
      if (bucket.count >= config.maxRequests) {
        const retryAfter = Math.ceil((bucket.resetAt - now) / 1000);
        return c.json(
          { error: 'rate_limit_exceeded', code: 'rate_limit' },
          429,
          { 'Retry-After': String(retryAfter) },
        );
      }
      bucket.count++;
    } else {
      buckets.set(key, { count: 1, resetAt: now + config.windowMs });
    }

    await next();
  };
}
