text: const mongoose = require('mongoose');
  const validator = require('validator');
  const bcrypt = require('bcryptjs');
  const { toJSON, paginate } = require('./plugins');
  const { roles } = require('../config/roles');
  const { number } = require('joi');
  
  const userSchema = mongoose.Schema(
    {
      name: {
        type: String,
        required: true,
        trim: true,
      },
      address: {
        type: String,
      },
      phone: {
        type: String,
      },
      email: {
        type: String,
        required: true,
        unique: true,
        trim: true,
        lowercase: true,
        validate(value) {
          if (!validator.isEmail(value)) {
            throw new Error('Invalid email');
          }
        },
      },
      avatar: {
        type: String,
        default: 'https://iupac.org/wp-content/uploads/2018/05/default-avatar.png',
      },
      password: {
        type: String,
        required: true,
        trim: true,
        minlength: 6,
        validate(value) {
          if (!value.match(/\d/) || !value.match(/[a-zA-Z]/)) {
            throw new Error('Password must contain at least one letter and one number');
          }
        },
        private: true, // used by the toJSON plugin
      },
      role: {
        type: String,
        enum: roles,
        default: 'user',
      },
      roleId: {
        type: Number,
        default: 1,
      }
    },
    {
      timestamps: true,
      versionKey: false,
    }
  );
  
  // add plugin that converts mongoose to json
  userSchema.plugin(toJSON);
  userSchema.plugin(paginate);
  
  /**
   * Check if email is taken
   * @param {string} email - The user's email
   * @param {ObjectId} [excludeUserId] - The id of the user to be excluded
   * @returns {Promise<boolean>}
   */
  userSchema.statics.isEmailTaken = async function (email, excludeUserId) {
    const user = await this.findOne({ email, _id: { $ne: excludeUserId } });
    return !!user;
  };
  
  /**
   * Check if password matches the user's password
   * @param {string} password
   * @returns {Promise<boolean>}
   */
  userSchema.methods.isPasswordMatch = async function (password) {
    const user = this;
    return bcrypt.compare(password, user.password);
  };
  
  userSchema.pre('save', async function (next) {
    const user = this;
    if (user.isModified('password')) {
      user.password = await bcrypt.hash(user.password, 8);
    }
    next();
  });
  
  /**
   * @typedef User
   */
  const User = mongoose.model('User', userSchema);
  
  module.exports = User;
  