import { Request, Response, NextFunction } from 'express';
import logger from '../utils/logger';

/**
 * Lista de patrones de User-Agent de bots conocidos
 * Estos bots no deberían acceder a endpoints de autenticación
 */
const BOT_PATTERNS = [
  /bot/i,
  /crawl/i,
  /spider/i,
  /slurp/i,
  /mediapartners/i,
  /googlebot/i,
  /bingbot/i,
  /yandex/i,
  /baidu/i,
  /duckduck/i,
  /teoma/i,
  /archive\.org_bot/i,
  /ia_archiver/i,
  /facebookexternalhit/i,
  /whatsapp/i,
  /telegrambot/i,
  /twitterbot/i,
  /linkedinbot/i,
  /slackbot/i,
  /discordbot/i,
  /headlesschrome/i,
  /phantom/i,
  /selenium/i,
  /puppeteer/i,
  /chrome-lighthouse/i,
  /pagespeed/i,
  /gtmetrix/i,
  /pingdom/i,
  /uptimerobot/i,
];

/**
 * Middleware para detectar y bloquear bots en rutas sensibles
 * Especialmente útil para prevenir que bots de renderizado ejecuten 
 * JavaScript y hagan peticiones a endpoints de autenticación
 */
export const blockBotsOnAuth = (req: Request, res: Response, next: NextFunction) => {
  const userAgent = req.get('User-Agent') || '';
  
  // Verificar si el User-Agent coincide con algún patrón de bot
  const isBot = BOT_PATTERNS.some(pattern => pattern.test(userAgent));
  
  if (isBot) {
    logger.warn('🤖 Bot detected and blocked on authentication endpoint', {
      userAgent,
      path: req.path,
      method: req.method,
      ip: req.ip,
      origin: req.get('Origin'),
      referer: req.get('Referer'),
    });
    
    // Retornar 403 Forbidden de inmediato sin procesar más
    return res.status(403).json({
      success: false,
      error: 'Bots are not allowed to access this endpoint',
    });
  }
  
  next();
};

/**
 * Middleware para detectar y bloquear bots en cualquier ruta
 * Versión más permisiva que solo bloquea bots obvios
 */
export const detectBots = (req: Request, res: Response, next: NextFunction) => {
  const userAgent = req.get('User-Agent') || '';
  
  // Solo bloquear bots muy obvios (más estricto)
  const isObviousBot = /bot|crawl|spider|slurp|yandex/i.test(userAgent);
  
  if (isObviousBot) {
    logger.info('🤖 Bot detectado', {
      userAgent,
      path: req.path,
      method: req.method,
      ip: req.ip,
    });
  }
  
  next();
};

/**
 * Middleware para validar que existe un refresh token antes de procesarlo
 * Evita que el código llegue a la validación costosa de Zod
 */
export const requireRefreshToken = (req: Request, res: Response, next: NextFunction) => {
  const hasRefreshTokenInCookie = !!req.cookies?.refreshToken;
  const hasRefreshTokenInBody = !!req.body?.refreshToken;
  
  if (!hasRefreshTokenInCookie && !hasRefreshTokenInBody) {
    logger.warn('⚠️ Intento de refresh sin token - bloqueado temprano', {
      ip: req.ip,
      userAgent: req.get('User-Agent'),
      origin: req.get('Origin'),
      referer: req.get('Referer'),
      hasCookies: !!req.cookies && Object.keys(req.cookies).length > 0,
      hasBody: !!req.body && Object.keys(req.body).length > 0,
    });
    
    // Fail fast - retornar error inmediatamente sin llegar a Zod
    return res.status(401).json({
      success: false,
      error: 'Refresh token is required',
      message: 'No refresh token provided in cookies or request body',
    });
  }
  
  next();
};

