// Rate Limiting Middleware

import { Request, Response, NextFunction } from 'express';
import rateLimit from 'express-rate-limit';
import { RATE_LIMITS } from '@/shared/constants';
import { AuthenticatedRequest } from './auth.middleware';

/**
 * Create rate limiter based on tier
 */
export function createRateLimiter(tier: 'TIER_1' | 'TIER_2' | 'PRIVATE_BANK') {
  const config = RATE_LIMITS[
    tier === 'TIER_1' ? 'SOVEREIGN_TIER_1' :
    tier === 'TIER_2' ? 'SOVEREIGN_TIER_2' :
    'PRIVATE_BANK'
  ];

  return rateLimit({
    windowMs: config.windowMs,
    max: config.max,
    message: {
      success: false,
      error: {
        code: 'RATE_LIMIT_EXCEEDED',
        message: `Rate limit exceeded. Maximum ${config.max} requests per ${config.windowMs / 1000} seconds.`,
      },
      timestamp: new Date(),
    },
    standardHeaders: true,
    legacyHeaders: false,
  });
}

const tierLimiters = {
  TIER_1: createRateLimiter('TIER_1'),
  TIER_2: createRateLimiter('TIER_2'),
  PRIVATE_BANK: createRateLimiter('PRIVATE_BANK'),
} as const;

/**
 * Dynamic rate limiter based on user role
 */
export function dynamicRateLimitMiddleware(
  req: AuthenticatedRequest,
  res: Response,
  next: NextFunction
): void {
  // Determine tier based on API role
  let tier: 'TIER_1' | 'TIER_2' | 'PRIVATE_BANK' = 'PRIVATE_BANK';
  
  if (req.apiRole === 'sovereign_master' || req.apiRole === 'treasury') {
    tier = 'TIER_1';
  } else if (req.apiRole === 'settlement' || req.apiRole === 'api') {
    tier = 'TIER_2';
  }

  const limiter = tierLimiters[tier];
  limiter(req, res, next);
}

function iruMarketplaceRateLimitNoop(_req: Request, _res: Response, next: NextFunction): void {
  next();
}

/** POST /iru/marketplace/inquiries — default 10 / 15m per IP. IRU_MARKETPLACE_RATE_LIMIT_IN_TEST=1 disables in Jest. */
export function createIruMarketplaceInquiryPostLimiter() {
  if (process.env.IRU_MARKETPLACE_RATE_LIMIT_IN_TEST === '1') {
    return iruMarketplaceRateLimitNoop;
  }
  const windowMs = parseInt(process.env.IRU_MARKETPLACE_INQUIRY_WINDOW_MS || '900000', 10);
  const max = parseInt(process.env.IRU_MARKETPLACE_INQUIRY_MAX || '10', 10);
  return rateLimit({
    windowMs,
    max,
    standardHeaders: true,
    legacyHeaders: false,
    message: {
      success: false,
      error: {
        code: 'RATE_LIMIT_EXCEEDED',
        message: `Too many inquiry submissions. Try again after ${Math.ceil(windowMs / 60000)} minutes.`,
      },
      timestamp: new Date(),
    },
  });
}

/** Public GETs (offerings, inquiry status, pricing) — default 200 / min per IP */
export function createIruMarketplacePublicReadLimiter() {
  if (process.env.IRU_MARKETPLACE_RATE_LIMIT_IN_TEST === '1') {
    return iruMarketplaceRateLimitNoop;
  }
  const windowMs = parseInt(process.env.IRU_MARKETPLACE_PUBLIC_WINDOW_MS || '60000', 10);
  const max = parseInt(process.env.IRU_MARKETPLACE_PUBLIC_MAX || '200', 10);
  return rateLimit({
    windowMs,
    max,
    standardHeaders: true,
    legacyHeaders: false,
    message: {
      success: false,
      error: {
        code: 'RATE_LIMIT_EXCEEDED',
        message: 'Too many requests. Please wait and retry.',
      },
      timestamp: new Date(),
    },
  });
}
