const jwt = require('jsonwebtoken');
const User = require('../models/User');
const Role = require('../models/Role');

// Protect routes
exports.protect = async (req, res, next) => {
  try {
    let token;
    
    if (req.headers.authorization && req.headers.authorization.startsWith('Bearer')) {
      token = req.headers.authorization.split(' ')[1];
    }
    
    if (!token) {
      return res.status(401).json({
        success: false,
        message: 'You are not logged in. Please log in to get access.'
      });
    }
    
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    
    // Updated: populate companies array instead of single companyId
    const user = await User.findById(decoded.userId)
      .populate('companies', 'name code')
      .populate('roleId')
      .select('+refreshToken'); // Include refreshToken for logout
    
    if (!user) {
      return res.status(401).json({
        success: false,
        message: 'The user belonging to this token no longer exists.'
      });
    }
    
    if (user.changedPasswordAfter(decoded.iat)) {
      return res.status(401).json({
        success: false,
        message: 'User recently changed password. Please log in again.'
      });
    }
    
    if (user.status !== 'active') {
      return res.status(403).json({
        success: false,
        message: 'Your account has been suspended.'
      });
    }
    
    req.user = user;
    next();
    
  } catch (error) {
    return res.status(401).json({
      success: false,
      message: 'Invalid token or token expired'
    });
  }
};

// Updated: Multi-company access check
exports.checkCompanyAccess = async (req, res, next) => {
  try {
    const userRole = await Role.findById(req.user.roleId);
    
    // Global scope users have access to everything
    if (userRole.scope === 'global') {
      return next();
    }
    
    // Extract target company from request
    const targetCompanyId = req.params.companyId || 
                           req.body.companyId || 
                           req.query.companyId ||
                           req.body.companies?.[0];
    
    if (!targetCompanyId) {
      // No specific company requested, allow access
      return next();
    }
    
    // Check if user has access to the target company
    const hasCompanyAccess = req.user.companies.some(company => 
      company._id.toString() === targetCompanyId.toString()
    );
    
    if (!hasCompanyAccess) {
      return res.status(403).json({
        success: false,
        message: 'You do not have access to this company data'
      });
    }
    
    next();
  } catch (error) {
    console.error('Company access error:', error);
    res.status(500).json({
      success: false,
      message: 'Error checking company access'
    });
  }
};

// NEW: Restrict access to specific roles
exports.authorize = (...roles) => {
  return (req, res, next) => {
    if (!roles.includes(req.user.roleId.name)) {
      return res.status(403).json({
        success: false,
        message: `Role ${req.user.roleId.name} is not authorized to access this route`
      });
    }
    next();
  };
};

// NEW: Multi-company user operations check
exports.checkUserCompanyAccess = async (req, res, next) => {
  try {
    const userRole = await Role.findById(req.user.roleId);
    
    // Global scope users bypass all checks
    if (userRole.scope === 'global') {
      return next();
    }
    
    // For user operations (create/update/delete), check target user companies
    const targetUserId = req.params.id || req.body.userId;
    
    if (targetUserId) {
      const targetUser = await User.findById(targetUserId).select('companies');
      
      if (targetUser && targetUser.companies.length > 0) {
        // Check if there's at least one common company
        const hasCommonCompany = targetUser.companies.some(targetCompany => 
          req.user.companies.some(userCompany => 
            targetCompany.toString() === userCompany.toString()
          )
        );
        
        if (!hasCommonCompany) {
          return res.status(403).json({
            success: false,
            message: 'You can only manage users from your companies'
          });
        }
      }
    }
    
    next();
  } catch (error) {
    console.error('User company access error:', error);
    res.status(500).json({
      success: false,
      message: 'Error checking user company access'
    });
  }
};