const User = require('../models/User');
const { NotFoundError, UnauthorizedError } = require('../utils/errors');

// @desc    Get all users
// @route   GET /api/v1/users
// @access  Private/Admin
exports.getAllUsers = async (req, res, next) => {
  try {
    const users = await User.find().select('-password');
    
    res.status(200).json({
      success: true,
      count: users.length,
      data: users
    });
  } catch (error) {
    next(error);
  }
};

// @desc    Get single user
// @route   GET /api/v1/users/:id
// @access  Private/Admin or same user
exports.getUser = async (req, res, next) => {
  try {
    const user = await User.findById(req.params.id).select('-password');

    if (!user) {
      return next(new NotFoundError(`No user found with id ${req.params.id}`));
    }

    // Check if user is admin or the same user
    if (req.user.role !== 'admin' && user._id.toString() !== req.user.id) {
      return next(new UnauthorizedError('Not authorized to access this route'));
    }

    res.status(200).json({
      success: true,
      data: user
    });
  } catch (error) {
    next(error);
  }
};

// @desc    Update user
// @route   PUT /api/v1/users/:id
// @access  Private/Admin or same user
exports.updateUser = async (req, res, next) => {
  try {
    // Don't allow updating password through this route
    if (req.body.password) {
      delete req.body.password;
    }

    const user = await User.findById(req.params.id);

    if (!user) {
      return next(new NotFoundError(`No user found with id ${req.params.id}`));
    }

    // Check if user is admin or the same user
    if (req.user.role !== 'admin' && user._id.toString() !== req.user.id) {
      return next(new UnauthorizedError('Not authorized to update this user'));
    }

    // Update user
    const updatedUser = await User.findByIdAndUpdate(
      req.params.id,
      { $set: req.body },
      { new: true, runValidators: true }
    ).select('-password');

    res.status(200).json({
      success: true,
      data: updatedUser
    });
  } catch (error) {
    next(error);
  }
};

// @desc    Delete user
// @route   DELETE /api/v1/users/:id
// @access  Private/Admin or same user
exports.deleteUser = async (req, res, next) => {
  try {
    const user = await User.findById(req.params.id);

    if (!user) {
      return next(new NotFoundError(`No user found with id ${req.params.id}`));
    }

    // Check if user is admin or the same user
    if (req.user.role !== 'admin' && user._id.toString() !== req.user.id) {
      return next(new UnauthorizedError('Not authorized to delete this user'));
    }

    await user.remove();

    res.status(200).json({
      success: true,
      data: {}
    });
  } catch (error) {
    next(error);
  }
};
