import { Response, NextFunction } from 'express';
import { AuthenticatedRequest } from './auth';
import { QuotaService } from '../services/quotaService';
import logger from '../utils/logger';

/**
 * Middleware para validar cuota mensual antes de endpoints de ElevenLabs
 * Se aplica a rutas que consumen tiempo de conversación
 */
export async function enforceUserMonthlyQuota(
  req: AuthenticatedRequest, 
  res: Response, 
  next: NextFunction
) {
  const startTime = Date.now();
  
  try {
    const user = req.user;
    if (!user) {
      logger.warn('❌ Quota check failed - user not authenticated', {
        path: req.path,
        ip: req.ip,
        userAgent: req.get('User-Agent')
      });
      return res.status(401).json({ 
        success: false, 
        message: 'Not authenticated' 
      });
    }

    logger.info('🔍 Checking monthly quota for user', {
      userId: user.id,
      email: user.email,
      path: req.path,
      method: req.method
    });

    // Calcular segundos restantes para el mes actual
    const quotaInfo = await QuotaService.getRemainingSeconds(user.id);

    if (quotaInfo.remainingSeconds <= 0) {
      logger.warn('❌ Monthly quota exceeded', {
        userId: user.id,
        email: user.email,
        path: req.path,
        allocatedSeconds: quotaInfo.allocatedSeconds,
        usedSeconds: quotaInfo.usedSeconds,
        remainingSeconds: quotaInfo.remainingSeconds,
        periodStart: quotaInfo.periodStart,
        periodEnd: quotaInfo.periodEnd
      });
      
      return res.status(403).json({ 
        success: false, 
        message: 'You have consumed your monthly minutes quota. Please contact your teacher or admin for more time.',
        data: {
          allocatedMinutes: Math.floor(quotaInfo.allocatedSeconds / 60),
          usedMinutes: Math.floor(quotaInfo.usedSeconds / 60),
          remainingMinutes: 0,
          periodStart: quotaInfo.periodStart,
          periodEnd: quotaInfo.periodEnd
        }
      });
    }

    // Adjuntar información de cuota a la request para que los controladores puedan usarla
    (req as any).quotaInfo = quotaInfo;
    
    const totalTime = Date.now() - startTime;
    
    logger.info('✅ Monthly quota check passed', {
      userId: user.id,
      email: user.email,
      path: req.path,
      allocatedSeconds: quotaInfo.allocatedSeconds,
      usedSeconds: quotaInfo.usedSeconds,
      remainingSeconds: quotaInfo.remainingSeconds,
      remainingMinutes: Math.floor(quotaInfo.remainingSeconds / 60),
      totalTime: `${totalTime}ms`
    });
    
    next();
  } catch (err: any) {
    const totalTime = Date.now() - startTime;
    
    logger.error('❌ Quota check failed with error', {
      userId: req.user?.id,
      email: req.user?.email,
      path: req.path,
      error: err?.message,
      stack: err?.stack,
      totalTime: `${totalTime}ms`
    });
    
    return res.status(500).json({ 
      success: false, 
      message: err?.message || 'Quota check failed' 
    });
  }
}

/**
 * Middleware opcional para adjuntar información de cuota sin bloquear el acceso
 * Útil para endpoints que muestran información de cuota
 */
export async function attachQuotaInfo(
  req: AuthenticatedRequest, 
  res: Response, 
  next: NextFunction
) {
  try {
    const user = req.user;
    if (user) {
      const quotaInfo = await QuotaService.getRemainingSeconds(user.id);
      (req as any).quotaInfo = quotaInfo;
      
      logger.info('📊 Quota info attached to request', {
        userId: user.id,
        remainingSeconds: quotaInfo.remainingSeconds,
        path: req.path
      });
    }
    
    next();
  } catch (err: any) {
    logger.warn('⚠️ Failed to attach quota info, continuing anyway', {
      userId: req.user?.id,
      path: req.path,
      error: err?.message
    });
    
    // No bloquear la request si falla la obtención de cuota
    next();
  }
}
