import type { Context, Next } from "hono";

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

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

function getClientIp(c: Context): string {
	return c.req.header("x-forwarded-for")?.split(",")[0]?.trim() || "unknown";
}

function cleanup() {
	const now = Date.now();
	for (const [key, entry] of store) {
		if (now >= entry.resetAt) {
			store.delete(key);
		}
	}
}

export function createRateLimit(maxAttempts: number, windowMs: number) {
	return async function rateLimitMiddleware(c: Context, next: Next) {
		cleanup();
		const ip = getClientIp(c);
		const key = `${ip}:${c.req.path}`;
		const now = Date.now();
		const entry = store.get(key);
		if (!entry || now >= entry.resetAt) {
			store.set(key, { count: 1, resetAt: now + windowMs });
			return next();
		}
		if (entry.count >= maxAttempts) {
			const retryAfter = Math.ceil((entry.resetAt - now) / 1000);
			c.header("Retry-After", String(retryAfter));
			return c.json({ error: "Too many attempts. Try again later." }, 429);
		}
		entry.count++;
		return next();
	};
}

export const rateLimit = createRateLimit(5, 15 * 60 * 1000);

/** @internal — only for testing */
export function _resetForTesting() {
	store.clear();
}
