const jwt = require('jsonwebtoken');
const { logger } = require('./logger');
const UnitOfWork = require('../database/UnitOfWork');
const UserStatusRepository = require('../repositories/status/UserStatusRepository');
const UserSettingsRepository = require('../repositories/settings/UserSettingsRepository');
const { normalizeLanguageCode } = require('../utils/languageUtils');

async function authMiddleware(req, res, next) {
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    logger.warn('authMiddleware:missingToken', {
      method: req.method,
      route: req.originalUrl
    });
    return res.status(401).json({ success: false, message: 'No access token provided' });
  }

  const token = authHeader.split(' ')[1];
  try {
    const payload = jwt.verify(token, process.env.JWT_SECRET);

    // edit profile context awareness
    const isEditProfile =
      req.originalUrl?.includes('/profile/personal') ||
      req.baseUrl?.includes('/profile/personal');

    // derive and log user type data
    const derivedUserType = payload.userType ?? payload.user_type ?? payload.type;
    const authDebug = {
      context: isEditProfile ? 'edit-profile' : 'general',
      method: req.method,
      route: req.originalUrl,
      id: payload.id ?? payload.userId ?? payload.sub,
      email: payload.email,
      userType: payload.userType,
      user_type: payload.user_type,
      derivedUserType,
      payloadKeys: Object.keys(payload || {})
    };
    logger.info(`authMiddleware:verified context=${authDebug.context} userType=${authDebug.derivedUserType}`, authDebug);
    // console fallback for local dev
    console.log('[authMiddleware] verified', authDebug);

    // Normalize common user fields for downstream checks
    const normalizedUserId = payload.userId ?? payload.id ?? payload.sub;
    const normalizedRole = payload.role ?? payload.userRole ?? payload.user_role ?? payload.type;

    // Attach user info to request (with normalized userType for downstream checks)
    req.user = {
      ...payload,
      userId: normalizedUserId,
      role: normalizedRole ?? payload.role,
      userType: payload.userType ?? payload.user_type,
      user_type: payload.user_type ?? payload.userType
    };

    // Block suspended users
    try {
      const unitOfWork = new UnitOfWork();
      await unitOfWork.start();
      unitOfWork.registerRepository('status', new UserStatusRepository(unitOfWork));
      unitOfWork.registerRepository('settings', new UserSettingsRepository(unitOfWork));
      const statusRepo = unitOfWork.getRepository('status');
      const settingsRepo = unitOfWork.getRepository('settings');
      const userStatus = await statusRepo.getStatusByUserId(normalizedUserId);
      const userSettings = await settingsRepo.getSettingsByUserId(normalizedUserId, unitOfWork);
      await unitOfWork.commit();

      const preferredLanguage = normalizeLanguageCode(
        userSettings?.preferred_language
          || userSettings?.preferredLanguage
          || req.user?.preferred_language
          || req.user?.preferredLanguage
          || req.user?.language
          || req.user?.lang
      ) || null;

      if (preferredLanguage) {
        req.user.preferred_language = preferredLanguage;
        req.user.preferredLanguage = preferredLanguage;
        req.user.language = preferredLanguage;
        req.user.lang = preferredLanguage;
      }

      if (userStatus && userStatus.status === 'suspended') {
        logger.warn('authMiddleware:user_suspended', {
          userId: normalizedUserId,
          route: req.originalUrl
        });
        return res.status(403).json({ success: false, message: 'Account suspended' });
      }
    } catch (statusError) {
      logger.error('authMiddleware:statusCheckFailed', {
        userId: normalizedUserId,
        route: req.originalUrl,
        error: statusError?.message
      });
      return res.status(500).json({ success: false, message: 'Internal server error' });
    }

    // Guest restriction: guest users can only access abo-related routes
    if (normalizedRole === 'guest') {
      const guestRestriction = require('./guestRestriction');
      return guestRestriction(req, res, next);
    }

    next();
  } catch (error) {
    logger.warn('authMiddleware:tokenInvalid', {
      method: req.method,
      route: req.originalUrl,
      reason: error?.message
    });
    return res.status(401).json({ success: false, message: 'Invalid or expired access token' });
  }
}

module.exports = authMiddleware;
