import rateLimit, { ipKeyGenerator, type Options } from 'express-rate-limit';
import type { Request } from 'express';
import { hasPlatformRole } from '../utils/platform-admin.js';

/**
 * Rate limiting por endpoint con 4 tiers según sensibilidad / costo computacional.
 *
 * Todas las keys se generan por `userId` (no IP) — usuarios legítimos detrás de NAT
 * compartido (ej: oficina con 20 contadores) no se bloquean entre sí.
 *
 * Admin global (tenant dueño de la plataforma o platform_admin/platform_ti) está exento:
 * necesita hacer operaciones masivas ocasionalmente (backfill, corrección manual, etc).
 */

const keyByUser = (req: Request): string => {
  // User autenticado → rate-limit por userId. Anónimo → por IP normalizada con
  // ipKeyGenerator (maneja IPv6 correctamente). Sin esto, express-rate-limit
  // emite warning de potential bypass con IPv6 mal truncado.
  if (req.user?.userId) return req.user.userId;
  return ipKeyGenerator(req.ip || 'anonymous');
};

const skipForGlobalAdmin = async (req: Request): Promise<boolean> => {
  if (!req.user?.userId) return false;
  try {
    // hasPlatformRole(..., 'platform_admin') retorna true para superset (admin o TI).
    // Otros platform roles (support/sales/finance) sí respetan rate limits.
    return await hasPlatformRole(req.user.userId, 'platform_admin');
  } catch {
    return false;
  }
};

const baseConfig: Partial<Options> = {
  keyGenerator: keyByUser,
  standardHeaders: true,
  legacyHeaders: false,
  skip: skipForGlobalAdmin,
};

/**
 * Tier más estricto — 2 requests por día.
 * Para operaciones que disparan syncs largos con el SAT o cómputo muy pesado
 * (Playwright headless contra portal SAT).
 */
export const veryStrictLimit = rateLimit({
  ...baseConfig,
  windowMs: 24 * 60 * 60 * 1000,
  max: 2,
  message: {
    message: 'Has alcanzado el límite de esta operación (2 por día). Intenta mañana o contacta soporte si es urgente.',
  },
});

/**
 * Tier estricto — 10 requests por hora.
 * Operaciones costosas o con side-effects en terceros (Facturapi, MP).
 */
export const strictLimit = rateLimit({
  ...baseConfig,
  windowMs: 60 * 60 * 1000,
  max: 10,
  message: {
    message: 'Demasiadas solicitudes en esta operación. Intenta de nuevo en una hora.',
  },
});

/**
 * Tier normal — 100 requests por 15 min.
 * APIs de negocio (dashboard, cfdi list, reportes, cálculos fiscales).
 */
export const normalLimit = rateLimit({
  ...baseConfig,
  windowMs: 15 * 60 * 1000,
  max: 100,
  message: {
    message: 'Demasiadas solicitudes. Espera unos minutos e intenta de nuevo.',
  },
});

/**
 * Tier relajado — 500 requests por 15 min.
 * Endpoints de lectura barata (catálogos SAT, listas fijas).
 */
export const relaxedLimit = rateLimit({
  ...baseConfig,
  windowMs: 15 * 60 * 1000,
  max: 500,
  message: {
    message: 'Demasiadas solicitudes. Espera unos minutos e intenta de nuevo.',
  },
});
