import { NextRequest, NextResponse } from 'next/server';

/**
 * Rate limiting middleware for all /api/* routes.
 * Adds X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset,
 * and Retry-After headers to every API response.
 *
 * In-memory sliding window per IP. Vercel serverless means this resets
 * per instance, but it protects against burst abuse and — critically —
 * tells agents exactly what their limits are via standard headers.
 */

const WINDOW_MS = 60_000; // 1 minute
const MAX_REQUESTS = 120; // 120 requests per minute per IP

interface WindowEntry {
  timestamps: number[];
}

const store = new Map<string, WindowEntry>();

// Cleanup stale entries every 2 minutes
let lastCleanup = Date.now();
function cleanup() {
  const now = Date.now();
  if (now - lastCleanup < 120_000) return;
  lastCleanup = now;
  const cutoff = now - WINDOW_MS;
  for (const [key, entry] of store) {
    entry.timestamps = entry.timestamps.filter(t => t > cutoff);
    if (entry.timestamps.length === 0) store.delete(key);
  }
}

function getClientIp(req: NextRequest): string {
  return (
    req.headers.get('x-forwarded-for')?.split(',')[0]?.trim() ||
    req.headers.get('x-real-ip') ||
    'unknown'
  );
}

export function middleware(req: NextRequest) {
  // Only apply to API routes
  if (!req.nextUrl.pathname.startsWith('/api/')) {
    return NextResponse.next();
  }

  cleanup();

  const ip = getClientIp(req);
  const now = Date.now();
  const cutoff = now - WINDOW_MS;

  let entry = store.get(ip);
  if (!entry) {
    entry = { timestamps: [] };
    store.set(ip, entry);
  }

  // Remove timestamps outside the window
  entry.timestamps = entry.timestamps.filter(t => t > cutoff);

  const remaining = Math.max(0, MAX_REQUESTS - entry.timestamps.length);
  const resetAt = entry.timestamps.length > 0
    ? Math.ceil((entry.timestamps[0] + WINDOW_MS) / 1000)
    : Math.ceil((now + WINDOW_MS) / 1000);

  // Rate limited
  if (entry.timestamps.length >= MAX_REQUESTS) {
    const retryAfterMs = entry.timestamps[0] + WINDOW_MS - now;
    const retryAfterSec = Math.ceil(retryAfterMs / 1000);

    return NextResponse.json(
      {
        error: 'Rate limit exceeded',
        retryAfterSeconds: retryAfterSec,
        limit: MAX_REQUESTS,
        window: '60s',
        message: `Maximum ${MAX_REQUESTS} requests per minute. Retry after ${retryAfterSec}s.`,
      },
      {
        status: 429,
        headers: {
          'X-RateLimit-Limit': String(MAX_REQUESTS),
          'X-RateLimit-Remaining': '0',
          'X-RateLimit-Reset': String(resetAt),
          'Retry-After': String(retryAfterSec),
        },
      },
    );
  }

  // Allow request, record it
  entry.timestamps.push(now);

  // Add rate limit headers to the response
  const response = NextResponse.next();
  response.headers.set('X-RateLimit-Limit', String(MAX_REQUESTS));
  response.headers.set('X-RateLimit-Remaining', String(remaining - 1));
  response.headers.set('X-RateLimit-Reset', String(resetAt));
  return response;
}

export const config = {
  matcher: '/api/:path*',
};
