import mongoose from "mongoose";
import validator from "validator";
import bcrypt from "bcrypt";
import modelNameRegister from "./modelNameRegister.js";

const Types = mongoose.Schema.Types;

const userSchema = new mongoose.Schema({
    email: {
        type: String,
        required: true,
        minlength: 1,
        trim: true,
        unique: true,
        validate: {
            validator: validator.isEmail,
            message: "String not email.",
        }
    },
    firstName: { type: String, required: true, trim: true },
    lastName: { type: String, required: true, trim: true },
    joinDate: { type: Date, default: Date.now, required: true },
    phone: { type: Number, required: false, min: 0 },
    password: {
        type: String,
        required: true,
        minlength: 8
        // TODO: Custom validator for password requirements?
    },
    createdMatches: { type: [{ type: Types.ObjectId, ref: modelNameRegister.Match }], required: true, default: [] },
    participatingMatches: { type: [{ type: Types.ObjectId, ref: modelNameRegister.Match }], required: true, default: [] },
    createdRentals: { type: [{ type: Types.ObjectId, ref: modelNameRegister.Rental }], required: true, default: [] },
    emailPublicity: { type: Number, required: true, default: 0 },
    bioPublicity: { type: Boolean, required: true, default: false },
    phonePublicity: { type: Boolean, required: true, default: false },
    participatingMatchesPublicity: { type: Boolean, required: true, default: false },
    friends: { type: Types.ObjectId, ref: modelNameRegister.User },
    accessLevel: { type: Number, required: true, default: 0 },
});

userSchema.statics.credentialsExist = async function (email, password) {
    let userModel = this;
    let user = await userModel.findOne({ email: email });
    if (!user) {
        return Promise.reject(new Error("Credentials do not exist."));
    }
    if (await bcrypt.compare(password, user.password)) {
        return user;
    }
};

userSchema.pre("save", function (next) {
    let user = this;
    if (user.isModified("password")) { // Only perform hashing if the password has changed.
        bcrypt.genSalt(10, (err, salt) => {
            bcrypt.hash(user.password, salt, (err, hash) => {
                if (err) {
                    throw err; // Probably not, but I'm gonna leave this here for now.
                }
                user.password = hash;
                next();
            });
        });
    } else {
        next();
    }
});

export default mongoose.model(modelNameRegister.User, userSchema);