"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createRateLimiter = void 0;
exports.rateLimitMiddleware = rateLimitMiddleware;
const rate_limiter_flexible_1 = require("rate-limiter-flexible");
const ioredis_1 = __importDefault(require("ioredis"));
/**
 * Get or create rate limiter instance
 */
function getRateLimiter(config) {
    const points = config.max;
    const duration = Math.ceil(config.windowMs / 1000); // Convert to seconds
    // Try to use Redis if available
    if (process.env.REDIS_URL) {
        try {
            const redis = new ioredis_1.default(process.env.REDIS_URL);
            return new rate_limiter_flexible_1.RateLimiterRedis({
                storeClient: redis,
                keyPrefix: 'rl:nlp:',
                points,
                duration,
                blockDuration: 10, // Block for 10 seconds after limit reached
            });
        }
        catch (error) {
            console.warn('Failed to create Redis rate limiter, falling back to memory:', error);
        }
    }
    // Fallback to in-memory rate limiter
    return new rate_limiter_flexible_1.RateLimiterMemory({
        keyPrefix: 'rl:nlp:',
        points,
        duration,
        blockDuration: 10,
    });
}
/**
 * Rate limiting middleware factory
 */
function rateLimitMiddleware(config) {
    const rateLimiter = getRateLimiter(config);
    const message = config.message || 'Too many requests, please try again later';
    return async (req, res, next) => {
        try {
            // Use IP address as key, with fallback
            const key = req.ip || req.socket.remoteAddress || 'unknown';
            // Try to consume a point
            await rateLimiter.consume(key);
            next();
        }
        catch (rejRes) {
            // Rate limit exceeded
            res.status(429).json({
                success: false,
                error: message,
                retryAfter: Math.round(rejRes.msBeforeNext / 1000) || 60,
            });
        }
    };
}
/**
 * Create a rate limiter for specific endpoint groups
 */
exports.createRateLimiter = {
    // Standard API rate limit (60 requests per minute)
    standard: () => rateLimitMiddleware({
        windowMs: 60 * 1000,
        max: 60,
        message: 'Too many requests, please try again later',
    }),
    // Strict rate limit for expensive operations (10 requests per minute)
    strict: () => rateLimitMiddleware({
        windowMs: 60 * 1000,
        max: 10,
        message: 'Too many requests to this resource, please try again later',
    }),
    // Relaxed rate limit for read operations (120 requests per minute)
    relaxed: () => rateLimitMiddleware({
        windowMs: 60 * 1000,
        max: 120,
        message: 'Too many requests, please slow down',
    }),
    // Custom rate limiter
    custom: (config) => rateLimitMiddleware(config),
};
exports.default = rateLimitMiddleware;
//# sourceMappingURL=rate-limit.middleware.js.map