const User = require('../models/userModel'); const Provider = require('../models/providerModel'); const Newsletter = require('../models/newsletterModel'); const bcrypt = require('bcryptjs'); // Get all users (with filtering by role) exports.getAllUsers = async (req, res) => { try { const { role, isActive } = req.query; let users; if (role === 'subscriber') { // Find all active newsletter emails const subscribers = await Newsletter.find({ isActive: true }).select( 'email', ); const emails = subscribers.map((s) => s.email); // Find users whose email is in the subscribers list (for in-app notifications) users = await User.find({ email: { $in: emails } }).select('-password'); // For the results count, we show the total number of newsletter subscribers return res.status(200).json({ status: 'success', results: subscribers.length, data: { users, totalSubscribers: subscribers.length, }, }); } else { const filter = {}; if (role) filter.role = role; if (isActive !== undefined) filter.isActive = isActive === 'true'; users = await User.find(filter).select('-password'); } res.status(200).json({ status: 'success', results: users.length, data: { users, }, }); } catch (err) { res.status(500).json({ status: 'error', message: 'Failed to fetch users', error: err.message, }); } }; // Get single user by ID exports.getUser = async (req, res) => { try { const user = await User.findById(req.params.id).select('-password'); if (!user) { return res.status(404).json({ status: 'fail', message: 'User not found', }); } res.status(200).json({ status: 'success', data: { user, }, }); } catch (err) { res.status(500).json({ status: 'error', message: 'Failed to fetch user', error: err.message, }); } }; // Create user with specific role (admin only) exports.createUser = async (req, res) => { try { const { name, email, phone, password, role, permissions, providerData } = req.body; // Validate required fields if (!name || !email || !phone || !password) { return res.status(400).json({ status: 'fail', message: 'Please provide name, email, phone, and password', }); } // Check if email already exists const existingUser = await User.findOne({ email }); if (existingUser) { return res.status(400).json({ status: 'fail', message: 'Email already registered', }); } // Check if phone already exists const existingPhone = await User.findOne({ phone }); if (existingPhone) { return res.status(400).json({ status: 'fail', message: 'Phone number already registered', }); } // Create user data object const userData = { name, email, phone, password, role: role || 'customer', }; // Add permissions if role is employee if (role === 'employee' && permissions) { userData.permissions = permissions; } // Create the user first const newUser = await User.create(userData); // If role is vendor, create or link provider if (role === 'vendor' && providerData) { const provider = await Provider.create({ ...providerData, user: newUser._id, }); newUser.provider = provider._id; await newUser.save(); } // Remove password from response newUser.password = undefined; res.status(201).json({ status: 'success', data: { user: newUser, }, }); } catch (err) { res.status(500).json({ status: 'error', message: 'Failed to create user', error: err.message, }); } }; // Update user details (for employees) exports.updateUser = async (req, res) => { try { const { name, email, phone, password, permissions, isActive } = req.body; const user = await User.findById(req.params.id); if (!user) { return res.status(404).json({ status: 'fail', message: 'User not found', }); } // Update basic fields if provided if (name) user.name = name; if (email) { // Check if email is already taken by another user const existingUser = await User.findOne({ email, _id: { $ne: req.params.id }, }); if (existingUser) { return res.status(400).json({ status: 'fail', message: 'Email already in use', }); } user.email = email; } if (phone) { // Check if phone is already taken by another user const existingPhone = await User.findOne({ phone, _id: { $ne: req.params.id }, }); if (existingPhone) { return res.status(400).json({ status: 'fail', message: 'Phone number already in use', }); } user.phone = phone; } // Update password if provided if (password) { user.password = password; // Will be hashed by pre-save middleware } // Update permissions if user is employee if (user.role === 'employee' && permissions !== undefined) { user.permissions = permissions; } // Update isActive status if (isActive !== undefined) { user.isActive = isActive; } await user.save(); // Remove password from response user.password = undefined; res.status(200).json({ status: 'success', data: { user, }, }); } catch (err) { res.status(500).json({ status: 'error', message: 'Failed to update user', error: err.message, }); } }; // Update user role exports.updateUserRole = async (req, res) => { try { const { role } = req.body; if (!role || !['customer', 'admin', 'employee', 'vendor'].includes(role)) { return res.status(400).json({ status: 'fail', message: 'Please provide a valid role', }); } const user = await User.findById(req.params.id); if (!user) { return res.status(404).json({ status: 'fail', message: 'User not found', }); } user.role = role; // Clear permissions if changing from employee to another role if (role !== 'employee') { user.permissions = []; } await user.save(); res.status(200).json({ status: 'success', data: { user, }, }); } catch (err) { res.status(500).json({ status: 'error', message: 'Failed to update user role', error: err.message, }); } }; // Update employee permissions exports.updateEmployeePermissions = async (req, res) => { try { const { permissions } = req.body; if (!Array.isArray(permissions)) { return res.status(400).json({ status: 'fail', message: 'Permissions must be an array', }); } const user = await User.findById(req.params.id); if (!user) { return res.status(404).json({ status: 'fail', message: 'User not found', }); } if (user.role !== 'employee') { return res.status(400).json({ status: 'fail', message: 'Permissions can only be set for employees', }); } user.permissions = permissions; await user.save(); // Emit socket event to notify the employee of permission changes try { const io = require('../utils/socket').getIO(); io.to(user._id.toString()).emit('permissionsUpdated', { permissions: user.permissions, message: 'تم تحديث صلاحياتك من قبل المسؤول', }); } catch (socketError) { console.error('Failed to emit permission update:', socketError); // Don't fail the request if socket emission fails } res.status(200).json({ status: 'success', data: { user, }, }); } catch (err) { res.status(500).json({ status: 'error', message: 'Failed to update permissions', error: err.message, }); } }; // Update vendor information exports.updateVendorInfo = async (req, res) => { try { const { vendorInfo } = req.body; if (!vendorInfo) { return res.status(400).json({ status: 'fail', message: 'Please provide vendor information', }); } const user = await User.findById(req.params.id); if (!user) { return res.status(404).json({ status: 'fail', message: 'User not found', }); } if (user.role !== 'vendor') { return res.status(400).json({ status: 'fail', message: 'Vendor info can only be set for vendors', }); } user.vendorInfo = { ...user.vendorInfo, ...vendorInfo }; await user.save(); res.status(200).json({ status: 'success', data: { user, }, }); } catch (err) { res.status(500).json({ status: 'error', message: 'Failed to update vendor info', error: err.message, }); } }; // Deactivate user account exports.deactivateUser = async (req, res) => { try { const user = await User.findById(req.params.id); if (!user) { return res.status(404).json({ status: 'fail', message: 'User not found', }); } user.isActive = false; await user.save(); res.status(200).json({ status: 'success', message: 'User account deactivated successfully', data: { user, }, }); } catch (err) { res.status(500).json({ status: 'error', message: 'Failed to deactivate user', error: err.message, }); } }; // Activate user account exports.activateUser = async (req, res) => { try { const user = await User.findById(req.params.id); if (!user) { return res.status(404).json({ status: 'fail', message: 'User not found', }); } user.isActive = true; await user.save(); res.status(200).json({ status: 'success', message: 'User account activated successfully', data: { user, }, }); } catch (err) { res.status(500).json({ status: 'error', message: 'Failed to activate user', error: err.message, }); } }; // Delete user (permanent) exports.deleteUser = async (req, res) => { try { const user = await User.findByIdAndDelete(req.params.id); if (!user) { return res.status(404).json({ status: 'fail', message: 'User not found', }); } res.status(200).json({ status: 'success', message: 'User deleted successfully', }); } catch (err) { res.status(500).json({ status: 'error', message: 'Failed to delete user', error: err.message, }); } };