import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { getClientAddress } from '@/lib/request';

const RATE_LIMIT_WINDOW = 60 * 1000;
const MAX_REQUESTS = 100;
const CLEANUP_THRESHOLD = 500;

const requestMap = new Map<string, { count: number; expires: number }>();
let nextCleanup = Date.now() + RATE_LIMIT_WINDOW;

function cleanupExpired(now: number) {
    if (requestMap.size <= CLEANUP_THRESHOLD && now < nextCleanup) return;

    for (const [key, value] of requestMap.entries()) {
        if (now > value.expires) {
            requestMap.delete(key);
        }
    }

    nextCleanup = now + RATE_LIMIT_WINDOW;
}

export function proxy(request: NextRequest) {
    const now = Date.now();
    cleanupExpired(now);

    const ip = getClientAddress(request.headers);
    const record = requestMap.get(ip);

    if (!record || now > record.expires) {
        requestMap.set(ip, { count: 1, expires: now + RATE_LIMIT_WINDOW });
    } else {
        record.count += 1;

        if (record.count > MAX_REQUESTS) {
            return new NextResponse('Too Many Requests', {
                status: 429,
                headers: {
                    'Retry-After': String(Math.ceil((record.expires - now) / 1000)),
                },
            });
        }
    }

    if (process.env.REQUEST_LOGS === 'true') {
        console.log(`[${new Date(now).toISOString()}] ${request.nextUrl.pathname} ${ip}`);
    }

    return NextResponse.next();
}

export const config = {
    matcher: ['/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico)$).*)'],
};
