const TwoFactorService = require("../services/TwoFactorService");
const logger = require("../utils/logger");

/**
 * Middleware to require step-up authentication for sensitive actions.
 * Only applies to users who have 2FA enabled.
 *
 * @param {string} action - The sensitive action being protected
 * @returns {Function} Express middleware function
 */
const requireStepUpAuth = (action) => {
  return async (req, res, next) => {
    try {
      // If user doesn't have 2FA enabled, skip step-up requirement
      if (!req.user.twoFactorEnabled) {
        return next();
      }

      // Check if user has a valid step-up session (within 5 minutes)
      const isValid = TwoFactorService.validateStepUpSession(req.user);

      if (!isValid) {
        logger.info(
          `Step-up authentication required for user ${req.user.id}, action: ${action}`
        );

        return res.status(403).json({
          error: "Multi-factor authentication required",
          code: "STEP_UP_REQUIRED",
          action: action,
          methods: getTwoFactorMethods(req.user),
        });
      }

      next();
    } catch (error) {
      logger.error("Step-up auth middleware error:", error);
      return res.status(500).json({
        error: "An error occurred during authentication",
      });
    }
  };
};

/**
 * Get available 2FA methods for a user
 * @param {Object} user - User object
 * @returns {string[]} Array of available methods
 */
function getTwoFactorMethods(user) {
  const methods = [];

  // Primary method is always available
  if (user.twoFactorMethod === "totp") {
    methods.push("totp");
  }

  // Email is always available as a backup method
  methods.push("email");

  // Recovery codes are available if any remain
  if (user.recoveryCodesHash) {
    const recoveryData = JSON.parse(user.recoveryCodesHash);
    const remaining = TwoFactorService.getRemainingRecoveryCodesCount(recoveryData);
    if (remaining > 0) {
      methods.push("recovery");
    }
  }

  return methods;
}

module.exports = { requireStepUpAuth };
