text: const crypto = require('crypto');
  const mongoose = require('mongoose');
  const bcrypt = require('bcryptjs');
  const validator = require('validator');
  const { use } = require('../routes/tourRoutes');
  
  const userSchema = mongoose.Schema({
    name: {
      type: String,
      required: [true, 'Please tell us your name!'],
    },
    email: {
      type: String,
      required: [true, 'Please provide your email'],
      unique: true,
      lowercase: true,
      validate: [validator.isEmail, 'Please provide a valid email'],
    },
    photo: {
      type: String,
      default: 'default.jpg'
    },
    role: {
      type: String,
      enum: ['user', 'guide', 'lead-guide', 'admin'],
      default: 'user',
    },
    password: {
      type: String,
      required: [true, 'Please provide a password'],
      minlength: 8,
      select: false,
    },
    passwordConfirm: {
      type: String,
      required: [true, 'Please confirm your password'],
      validate: {
        // THIS ONLY WORKS ON SAVE !!
        validator: function (val) {
          return val === this.password;
        },
        message: 'Passwords should match',
      },
    },
    passwordChangedAt: {
      type: Date,
    },
    passwordResetToken: String,
    passwordResetExpires: Date,
    active: {
      type: Boolean,
      default: true,
      select: false,
    },
  });
  
  userSchema.pre('save', async function (next) {
    // only run this function if password was actually modified
    if (!this.isModified('password')) return next();
  
    this.password = await bcrypt.hash(this.password, 12);
  
    // delete password confirm field
    this.passwordConfirm = undefined;
  
    next();
  });
  
  userSchema.pre('save', function (next) {
    if (!this.isModified('password') || this.isNew) return next();
  
    // HACKING TO ensure password is 1 second in the past. so that token expiry can be compared
    this.passwordChangedAt = Date.now() - 1000;
    next();
  });
  
  userSchema.pre(/^find/, function (next) {
    // this points to the current query
    this.find({ active: { $ne: false } });
    next();
  });
  
  // instance method
  userSchema.methods.correctPassword = async function (
    candidatePassword,
    userPassword
  ) {
    return await bcrypt.compare(candidatePassword, userPassword);
  };
  
  userSchema.methods.changedPasswordAfter = function (JWTTimestamp) {
    if (this.passwordChangedAt) {
      const changedTimestamp = parseInt(
        this.passwordChangedAt.getTime() / 1000,
        10
      );
      console.log(changedTimestamp, JWTTimestamp);
      return JWTTimestamp < changedTimestamp;
    }
    return false;
  };
  
  userSchema.methods.createPasswordResetToken = function () {
    // we use crypto a built in nodejs module
    const resetToken = crypto.randomBytes(32).toString('hex');
  
    this.passwordResetToken = crypto
      .createHash('sha256')
      .update(resetToken)
      .digest('hex');
  
    console.log({ resetToken }, this.passwordResetToken);
    this.passwordResetExpires = Date.now() + 10 * 60 * 1000;
  
    return resetToken;
  };
  
  const User = mongoose.model('User', userSchema);
  
  module.exports = User;
  