import rateLimit, { type RateLimitRequestHandler } from 'express-rate-limit';
import type { Request, Response } from 'express';
import { nodeEnv } from '../config/environment';
import { logger } from '../config/logger';

export interface CreateRateLimiterOptions {
  windowMs: number;
  maxRequests: number;
  message: string;
  logContext: string;
}

type RateLimitedRequest = Request & {
  rateLimit?: {
    resetTime?: Date;
  };
};

function retryAfterSeconds(req: RateLimitedRequest): number | undefined {
  const resetTime = req.rateLimit?.resetTime;
  if (!(resetTime instanceof Date)) {
    return undefined;
  }
  return Math.max(1, Math.ceil((resetTime.getTime() - Date.now()) / 1000));
}

export function createRateLimiter(options: CreateRateLimiterOptions): RateLimitRequestHandler {
  const { windowMs, maxRequests, message, logContext } = options;

  return rateLimit({
    windowMs,
    max: maxRequests,
    standardHeaders: false,
    legacyHeaders: false,
    skip: (req) => {
      if (nodeEnv === 'test') {
        return true;
      }
      if (req.method === 'OPTIONS') {
        return true;
      }
      return false;
    },
    handler: (req: RateLimitedRequest, res: Response) => {
      const retryAfter = retryAfterSeconds(req);
      logger.warn(`Auth rate limit exceeded [${logContext}] IP: ${req.ip}`);
      if (retryAfter != null) {
        res.setHeader('Retry-After', String(retryAfter));
      }
      res.status(429).json({
        error: {
          code: 'RATE_LIMIT_EXCEEDED',
          message,
          retryAfter,
        },
      });
    },
  });
}
