/**
 * @cc-platform/server/rate — In-memory rate limiter middleware
 *
 * Extracted from Inventory-Manager-CC/web/server/server.js which has rate
 * limiting while remoteturtle does not. Both services benefit from this
 * protection.
 *
 * Usage:
 *   const { createRateLimiter } = require('@cc-platform/server/rate');
 *   const limiter = createRateLimiter({ windowMs: 60000, maxRequests: 30 });
 *   app.use(limiter);
 *
 *   // Or protect specific routes:
 *   app.post('/api/sensitive', limiter, handler);
 */

'use strict';

/**
 * Create an in-memory rate limiter middleware.
 *
 * @param {Object} [opts={}] - Options
 * @param {number} [opts.windowMs=60000] - Time window in milliseconds
 * @param {number} [opts.maxRequests=30] - Maximum requests per window per IP
 * @param {string} [opts.message] - Custom error message
 * @param {boolean} [opts.mutationsOnly=true] - Only rate-limit non-GET methods
 * @returns {Function} Express middleware
 */
function createRateLimiter(opts = {}) {
  const windowMs = opts.windowMs || 60000;
  const maxRequests = opts.maxRequests || 30;
  const message = opts.message || 'Too many requests — please try again later';
  const mutationsOnly = opts.mutationsOnly !== false;

  // Map of IP → { count, resetTime }
  const clients = new Map();

  // Periodic cleanup of expired entries
  const cleanupInterval = setInterval(() => {
    const now = Date.now();
    for (const [ip, entry] of clients) {
      if (now > entry.resetTime) {
        clients.delete(ip);
      }
    }
  }, windowMs);

  // Don't prevent process exit
  if (cleanupInterval.unref) {
    cleanupInterval.unref();
  }

  return function rateLimiter(req, res, next) {
    // Skip GET/HEAD/OPTIONS if mutationsOnly
    if (mutationsOnly && ['GET', 'HEAD', 'OPTIONS'].includes(req.method)) {
      return next();
    }

    const ip = req.ip || req.socket.remoteAddress || 'unknown';
    const now = Date.now();

    let entry = clients.get(ip);
    if (!entry || now > entry.resetTime) {
      entry = { count: 0, resetTime: now + windowMs };
      clients.set(ip, entry);
    }

    entry.count++;

    if (entry.count > maxRequests) {
      const retryAfter = Math.ceil((entry.resetTime - now) / 1000);
      res.set('Retry-After', String(retryAfter));
      return res.status(429).json({
        error: message,
        retryAfter,
      });
    }

    // Add rate limit headers
    res.set('X-RateLimit-Limit', String(maxRequests));
    res.set('X-RateLimit-Remaining', String(Math.max(0, maxRequests - entry.count)));

    return next();
  };
}

module.exports = { createRateLimiter };
