import { Console } from "console";
import { nextTick, off, title } from "process";

const _ = require('lodash');
require('dotenv').config({ path: __dirname + '../.env' })
const mongoose = require("mongoose");
const { User } = require('../../models/user');
const { Role } = require('../../models/role');
const { MobileOtp } = require("../../core/utilities/mobileOtp")
const { Fcm } = require("../../models/fcm-tokens");
const { Category } = require("../../models/admin/category")
const { Contact } = require("../../models/admin/contact")
const { loginHistory } = require("../../models/login-history")
const { Language } = require("../../models/admin/language")
const { DepartmentCity } = require('../../models/department-city');
const { CronEmail } = require('../../models/email')
const { apiResponse } = require("../../core/response/response")
const { SUCCESS, REDIRECTION, CLIENT_ERROR, SERVER_ERROR } = require("../../core/response/statusCode")
const { ERROR_MSG, SUCCESS_MSG } = require("../../core/response/messages")
const { sendEmail } = require('../../core/utilities/emailService');
const { OTP } = require("../../models/otp")
const { signUpTemplate_ar, signUpTemplate, forgotPasswordUpdatedSuccessfullyTemplate, forgotPasswordTemplate, contactUsTemplate, signUpTemplate_fr, forgetPasswordTemplate, forgetPasswordTemplate_fr, forgetPasswordTemplate_ar } = require('../../core/email-templates/email-web');
const userObject = new User();

/*
* Here we would probably call the DB to confirm the user exists
* Then validate if they're authorized to login
* Then confirm their password
* Create a JWT or a cookie
* And finally send it back if all's good
*/
// //Login with email & password
exports.login = async (req, res) => {
    let lang = req.headers["accept-language"] || 'en'
    // If no validation errors, get the req.body objects that were validated and are needed
    try {
        const { email, password, login_type, phone_number, role_type, device_token, device_type } = req.body
        let lan = req.headers["accept-language"] || 'en'

        let condition
        if (login_type == 'email') {
            condition = {
                email: email.toLowerCase(),
                //is_deleted: false
            }
        } else {
            condition = {
                'phone_number.e164Number': phone_number.e164Number,
                //is_deleted: false
            }
        }


        let userInformation = await User.findOne(condition);
        // if(userInformation){
        //     const updateLang = await User.findOneAndUpdate({ _id: userInformation._id }, { $set: { selected_language: lang } }, { new: true })
        //     return apiResponse(res, false, [], '', SUCCESS.OK, 0, [updateLang], req);
        // }

        var UNREGISTERED = "";
        if(login_type == 'phone_number'){
            UNREGISTERED = ERROR_MSG[`UNREGISTERED-MOBILE-${lang}`];
        }else{
            UNREGISTERED = ERROR_MSG[`UNREGISTERED-${lang}`];
        }

        if (!userInformation) return apiResponse(res, true, [], UNREGISTERED, CLIENT_ERROR.badRequest, 0, [], req);


        if (userInformation && userInformation.is_deleted === true) return apiResponse(res, true, [], ERROR_MSG[`ACCOUNT-DELETED-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);

        if (role_type) {
            const userRole = await Role.findOne({ _id: new mongoose.Types.ObjectId(userInformation.user_role) }, { _id: 1, title: 1 })
            if (role_type == "doctor") {
                if ((userRole.title == "hospital") || (userRole.title == "doctor")) {

                } else {
                    return apiResponse(res, true, [], ERROR_MSG[`WRONG-CREDENTIALS-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);
                }

            }
            else {
                if (!(userRole.title == "patient")) return apiResponse(res, true, [], ERROR_MSG[`WRONG-CREDENTIALS-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);
            }

        }
        // await OTP.updateMany({user_id : new mongoose.Types.ObjectId(userInformation._id.toString()), is_expired:  false}, {is_expired: true}, {new:true});


        // if (userInformation.is_signup_otp_varify == false) return apiResponse(res, true, [], ERROR_MSG[`SIGNUP-OTP-NOT-VARIFY-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);




        const isValidPassword = await userObject.passwordCompare(userInformation.salt_key, userInformation.password, password);
        if (!isValidPassword) return apiResponse(res, true, [], ERROR_MSG[`PASSWORD-MISMATCH-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);




        //checking password match
        if (userInformation.is_account_active == false) return apiResponse(res, true, [], ERROR_MSG[`ACCOUNT-DEACTIVATED-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);

        if (userInformation.is_completed == true && userInformation.user_account_status == "PENDING") return apiResponse(res, true, [], ERROR_MSG[`ADMIN-NOT-VERIFIED-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);

        // rejected
        if (userInformation && userInformation.user_account_status == "REJECTED") return apiResponse(res, true, [], ERROR_MSG[`ADMIN-REJECTED-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);

        if (userInformation.is_signup_otp_varify == false) {
            await User.findByIdAndUpdate({ _id: userInformation._id }, { is_signup_otp_varify: true })
        }

        //generate OTP and send on mobile number
        // let generatedOTP = await Math.floor(Math.random() * (9999 - 1000 + 1) + 1000)
        // await Math.floor(Math.random() * (9999 - 1000 + 1) + 1000);
        // if (login_type != 'phone_number') {
        //     MobileOtp(userInformation.phone_number.e164Number, `DOCTOME: Your login verification code is ${generatedOTP}. Please enter this code to proceed. If you did not request this, please ignore this message.`);
        // }
        // else {
        //     const mailOptions = {
        //         to: userInformation.email,
        //         subject: "Login one-time-password",
        //         html: `Your login one-time-password is: ${generatedOTP}`
        //     };
        //     await sendEmail(mailOptions);
        // }

        //Update LoginUser to keep the OTP
        // await User.findOneAndUpdate({ '_id': userInformation._id }, { $set: { otp: generatedOTP } }, { new: true })
        //OTP save & update   
        // let otpObj = {
        //     user_id: userInformation._id,
        //     otp: generatedOTP,
        //     action: 'LOGIN'
        // }
        // let newRecord = new OTP(_.pick(otpObj, ['user_id', 'otp', 'action']));
        // let result = {
        //     _id: userInformation._id,
        //     is_completed: userInformation.is_completed,
        //     phone: `******${userInformation.last_digit_phone}`,
        //     email: userInformation.show_email
        // }
        // newRecord.save()
        // .then(async function (data) {

        //     return apiResponse(res, false, [], SUCCESS_MSG[`OTP-SEND-${lang}`], SUCCESS.OK, 0, result, req)
        // })
        // .catch(function (err) {
        //     return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
        // });

        // new code
        const updateResult = await User.updateOne(
            { _id: new mongoose.Types.ObjectId(userInformation._id) },
            { $set: { selected_language: lang } }
        );
        const token = await userObject.generateToken(userInformation.salt_key)
        const [data, count] = await Promise.all([
            User.aggregate([
                { $match: { _id: new mongoose.Types.ObjectId(userInformation._id) } },

                {
                    $lookup: {
                        from: "roles",
                        as: "userRole",
                        let: { userRole_id: "$user_role" },
                        pipeline: [
                            {
                                $match: {
                                    $and: [
                                        {
                                            $expr: { $eq: ["$$userRole_id", "$_id"] },
                                        },
                                        // filteredQueryUsersTable
                                    ]
                                },
                            },
                            { $project: { _id: 1, title: 1 } },

                        ],
                    },
                },
                { "$unwind": "$userRole" },
                { $project: { _id: 1, first_name: 1, last_name: 1, is_completed: 1, phone: 1, user_role: "$userRole.title", dob: 1, gender: 1, email: 1, phone_number: 1, user_account_status: 1, selected_language: 1 } },
            ]),
            await User.countDocuments({ _id: new mongoose.Types.ObjectId(userInformation._id) })
        ]);
        await User.findByIdAndUpdate({ _id: userInformation._id }, { $push: { auth_token: token } }, { new: true });
        let user_id = userInformation._id.toString()
        let fcmtoken = await Fcm.create({ user_id, device_token, device_type });
        console.log(fcmtoken, "fcmtoken===");
        return res.json({
            is_error: false,
            response_code: 200,
            count: count,
            token: token,
            data: data
        })
    } catch (error) {
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }


}

// login otp varification
exports.loginOTPVerification = async (req, res) => {
    let lang = req.headers["accept-language"] || 'en'
    const { user_id, otp } = req.body
    //Match OTP with login user id
    let existingRecord = await OTP.findOne({ user_id: user_id, otp: otp }, { otp: 1, user_id: 1, is_expired: 1 }, { sort: { createdAt: -1 } })
    if (existingRecord) {
        if (existingRecord && existingRecord.is_expired == true) {
            return apiResponse(res, true, [], ERROR_MSG[`OTP-EXPIRED-${lang}`], CLIENT_ERROR.badRequest, 0, [], req)
        }
        let userRecord = await User.findOne({ _id: user_id }, { _id: 1, first_name: 1, login_count: 1, last_name: 1, dob: 1, phone: 1, email: 1, is_account_active: 1, is_verified: 1, last_login: 1 })
        const token = await userObject.generateToken(userRecord.salt_key);//generate token 
        //login count++
        let login_count = (userRecord.login_count) + 1;
        await User.findOneAndUpdate({ _id: userRecord._id }, { auth_token: token, last_login: Date.now(), login_count: login_count }, { new: true })
        await loginHistory.create({ user_id: userRecord._id, action: "LOGIN" })
        const [data, count] = await Promise.all([
            User.aggregate([
                { $match: { _id: new mongoose.Types.ObjectId(user_id) } },

                {
                    $lookup: {
                        from: "roles",
                        as: "userRole",
                        let: { userRole_id: "$user_role" },
                        pipeline: [
                            {
                                $match: {
                                    $and: [
                                        {
                                            $expr: { $eq: ["$$userRole_id", "$_id"] },
                                        },
                                        // filteredQueryUsersTable
                                    ]
                                },
                            },
                            { $project: { _id: 1, title: 1 } },

                        ],
                    },
                },
                { "$unwind": "$userRole" },
                { $project: { _id: 1, first_name: 1, last_name: 1, is_completed: 1, phone: 1, user_role: "$userRole.title", dob: 1, gender: 1, email: 1, phone_number: 1, user_account_status: 1 } },
            ]),
            await User.countDocuments({ _id: new mongoose.Types.ObjectId(user_id) })
        ])


        //expired otp

        await OTP.findOneAndUpdate({ _id: existingRecord._id }, { is_expired: true }, { new: true });

        return res.json({
            is_error: false,
            response_code: 200,
            count: count,
            token: token,
            data: data
        })
    } else {


        return apiResponse(res, true, '', ERROR_MSG[`OTP-MISMATCH-${lang}`], CLIENT_ERROR.badRequest, 0, [], req)
    }
}

// forgot password otp varufucation
exports.forgotPasswordOTPVerification = async (req, res) => {
    let lang = req.headers["accept-language"] || 'en'
    const { user_id, otp } = req.body
    //Match OTP with login user id
    let existingRecord = await OTP.findOne({ user_id: user_id, otp: otp }, { otp: 1, user_id: 1, is_expired: 1 }, { sort: { createdAt: -1 } })
    if (existingRecord) {
        if (existingRecord && existingRecord.is_expired == true) {
            return apiResponse(res, true, [], ERROR_MSG[`OTP-EXPIRED-${lang}`], CLIENT_ERROR.badRequest, 0, [], req)
        }
        let userRecord = await User.findOne({ _id: user_id }, { _id: 1, first_name: 1, login_count: 1, last_name: 1, dob: 1, phone: 1, email: 1, salt_key: 1, is_account_active: 1, is_verified: 1, last_login: 1 })

        const resetPasswordToken = await userObject.generateResetPasswordToken(userRecord.salt_key);//generate reset password token 
        await User.findOneAndUpdate({ _id: userRecord._id }, { $set: { reset_password_token: resetPasswordToken, updatedAt: new Date() } }, { new: true })
        const [data, count] = await Promise.all([
            User.aggregate([
                { $match: { _id: new mongoose.Types.ObjectId(user_id) } },

                {
                    $lookup: {
                        from: "roles",
                        as: "userRole",
                        let: { userRole_id: "$user_role" },
                        pipeline: [
                            {
                                $match: {
                                    $and: [
                                        {
                                            $expr: { $eq: ["$$userRole_id", "$_id"] },
                                        },
                                        // filteredQueryUsersTable
                                    ]
                                },
                            },
                            { $project: { _id: 1, title: 1 } },

                        ],
                    },
                },
                { "$unwind": "$userRole" },
                { $project: { _id: 1, first_name: 1, last_name: 1, phone: 1, reset_password_token: 1, user_role: "$userRole.title" } },
            ]),
            await User.countDocuments({ _id: new mongoose.Types.ObjectId(user_id) })
        ])


        await OTP.findOneAndUpdate({ _id: existingRecord._id }, { is_expired: true }, { new: true });

        return res.json({
            is_error: false,
            response_code: 200,
            count: count,
            data: data
        })
    } else {
        return apiResponse(res, true, '', ERROR_MSG[`OTP-MISMATCH-${lang}`], CLIENT_ERROR.badRequest, 0, [], req)
    }
}
/*
* Here we would probably call the DB to confirm the user exists
* Then validate and save in DB
* Create a JWT or a cookie
* Send an email to that address with the URL to approve account
* And finally let the user know their email is waiting for them at their inbox

*/
// get data
// patient signup user
exports.signup = async (req, res) => {
    let lang = req.headers["accept-language"] || 'en'
    // If no validation errors, get the req.body objects that were validated and are needed
    const { email, user_role, phone_number, device_token, device_type } = req.body;

    try {


        let existingPhoneUser
        if (phone_number && phone_number != null) {
            existingPhoneUser = await User.findOne(
                { "phone_number.nationalNumber": phone_number.nationalNumber },
                { _id: 1, is_completed: 1, email: 1, phone_number: 1, is_signup: 1, is_signup_otp_varify: 1, is_verified: 1 }
            );
        }
        let existingEmailUser = await User.findOne(
            { "email": email },
            { _id: 1, is_completed: 1, email: 1, phone_number: 1, is_signup: 1, is_signup_otp_varify: 1, is_verified: 1 }
        );
        let existingUser = (existingPhoneUser && existingPhoneUser != null) ? existingPhoneUser : existingEmailUser
        //fetch Role
        let role = await Role.findOne(
            { title: user_role },
            { _id: 1 }
        );
        if (existingUser && existingUser.is_signup == true && existingUser.is_signup_otp_varify == true) {
            if (existingPhoneUser && existingPhoneUser.phone_number != null) {
                return apiResponse(res, true, [], ERROR_MSG[`PHONE-ALREADY-EXIST-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);
            }
            else {
                return apiResponse(res, true, [], ERROR_MSG[`EMAIL-ALREADY-EXIST-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);
            }
        }
        // exitingUser profile but not completed
        if (existingUser && existingUser.is_signup == true && existingUser.is_signup_otp_varify == false) {
            let generatedOTP = await Math.floor(Math.random() * (9999 - 1000 + 1) + 1000);
            // await Math.floor(Math.random() * (9999 - 1000 + 1) + 1000);
            await MobileOtp(existingUser.phone_number.e164Number, `Dr. Hivey: Welcome! Your signup verification code is ${generatedOTP} Enter this code to complete your registration. If you did not request this, please ignore this message.`)
            let updatedData = {
                $set: { otp: generatedOTP },
            }
            let userData = await User.findOneAndUpdate({ _id: existingUser._id }, updatedData, { new: true })
            let otpObj = {
                user_id: userData._id,
                otp: generatedOTP,
                action: 'SIGNUP'
            }
            let newRecord = new OTP(_.pick(otpObj, ['user_id', 'otp', 'action']));
            newRecord.save()
                .then(async function (lookupData) {
                    let data = {
                        _id: userData._id,
                        phone: `******${userData.last_digit_phone}`,
                        email: userData.show_email
                    }

                    let user_id = userData._id
                    let fcmtoken = await Fcm.create({ user_id, device_token, device_type });
                    console.log(fcmtoken, "fcmtoken===");
                    return apiResponse(res, false, [], SUCCESS_MSG[`OTP-SEND-${lang}`], SUCCESS.OK, 0, data, req)
                })
                .catch(function (err) {
                    return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
                });
        }
        //save user 
        if (!existingUser) {
            req.body['is_signup_otp_varify'] = true;
            var newUser = new User(_.pick(req.body, ['title', 'first_name', 'middle_name', 'last_name', 'dob', 'phone_number', 'user_role', 'email', 'gender', 'device_data', 'password', 'social_security_number', 'branch_of_medicines', 'primary_specialty', 'additional_specialty', 'qualification', 'year_of_practice', 'additional_qualification', 'spoken_language', 'certificate', 'clinic_name', 'clinic_contact', 'clinic_open_time', 'clinic_close_time', 'street_address', 'location', 'primary_specialty_name', 'show_email', 'doctor_present', 'clinic_timing', 'is_fulltime', 'clinic_municipality', 'clinic_department', 'is_completed', 'hospital_name',]));
            newUser['email'] = req.body.email.toLowerCase()
            function maskEmail(email) {
                // Split the email address into local part and domain part
                var parts = email.split('@');

                // Replace characters in the local part except for the first two characters
                var maskedLocalPart = parts[0].substring(0, 2) + parts[0].substring(2).replace(/./g, '*');

                // Return the masked email address
                return maskedLocalPart + '@' + parts[1];
            }
            var maskedEmail = maskEmail(req.body.email.toLowerCase());
            newUser['show_email'] = maskedEmail
            if (user_role) {
                newUser['user_role'] = role['_id']
            }
            if (user_role == "patient") {
                newUser['user_account_status'] = 'APPROVED'
            }
            newUser['last_digit_phone'] = phone_number.e164Number.slice(-4)
            newUser['is_signup'] = true
            await newUser.save()
                .then(async function (user) {
                    const token = await userObject.generateToken(user.salt_key);//generate token
                    let generatedOTP = await Math.floor(Math.random() * (9999 - 1000 + 1) + 1000);
                    // await Math.floor(Math.random() * (9999 - 1000 + 1) + 1000);
                    await MobileOtp(user.phone_number.e164Number, `Welcome! Your signup verification code is ${generatedOTP} Enter this code to complete your registration. If you did not request this, please ignore this message.`)
                    let updatedData = {
                        $set: { account_verify_token: token, otp: generatedOTP },
                        $push: { auth_token: token },

                    }
                    let userData = await User.findOneAndUpdate({ _id: user._id }, updatedData, { new: true },)
                    let otpObj = {
                        user_id: userData._id,
                        otp: generatedOTP,
                        action: 'SIGNUP'
                    }
                    let newRecord = new OTP(_.pick(otpObj, ['user_id', 'otp', 'action']));
                    newRecord.save()
                        .then(function (lookupData) {

                        })
                        .catch(function (err) {
                            return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
                        });
                    let data = {
                        _id: userData._id,
                        phone: `******${userData.last_digit_phone}`,
                        email: userData.show_email
                    }

                    let user_id = userData._id.toString()
                    let fcmtoken = await Fcm.create({ user_id, device_token, device_type });
                    console.log(fcmtoken, "fcmtoken===");
                    return apiResponse(res, false, [], SUCCESS_MSG[`OTP-SEND-${lang}`], SUCCESS.OK, 0, data, req)
                })
        }
    } catch (error) {
        console.log(error);

        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }
}
exports.updateLanguage = async (req, res) => {
    let lang = req.headers["accept-language"] || 'en'
    const { userId } = req.body
    let condition = {}
    condition['_id'] = new mongoose.Types.ObjectId(userId);
    let record = await User.findOne(condition, { _id: 1 });
    if (record) {
        const updateUser = await User.findOneAndUpdate(condition, { $set: { selected_language: lang } }, { new: true })
        return apiResponse(res, false, [], '', SUCCESS.OK, 0, [updateUser], req);
    }
    return apiResponse(res, true, [], ERROR_MSG[`NO-RECORD-FOUND-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);

}




// signup otp varification
exports.signupOTPVerification = async (req, res) => {

    // If no validation errors, get the req.body objects that were validated and are needed
    let lang = req.headers["accept-language"] || 'en'
    try {
        const { user_id, otp, device_token, device_type } = req.body

        let userInfoData = await User.findOne({ _id: user_id }, { phone_number: 1 })

        let existingRecord = await OTP.findOne({ user_id: user_id, otp: otp }, { otp: 1, user_id: 1, is_expired: 1 }, { sort: { createdAt: -1 } })
        if (true) {

            // if (existingRecord && existingRecord.is_expired == true) {
            //     return apiResponse(res, true, [], ERROR_MSG[`OTP-EXPIRED-${lang}`], CLIENT_ERROR.badRequest, 0, [], req)
            // }

            await User.findOneAndUpdate({ _id: user_id }, { is_signup_otp_varify: true, is_signup: true, selected_language: lang }, { new: true })
            const [data, count] = await Promise.all([
                User.aggregate([
                    { $match: { _id: new mongoose.Types.ObjectId(user_id) } },
                    {
                        $lookup: {
                            from: "roles",
                            as: "userRole",
                            let: { userRole_id: "$user_role" },
                            pipeline: [
                                {
                                    $match: {
                                        $and: [
                                            {
                                                $expr: { $eq: ["$$userRole_id", "$_id"] },
                                            },
                                            // filteredQueryUsersTable
                                        ]
                                    },
                                },
                                { $project: { _id: 1, title: 1 } },

                            ],
                        },
                    },
                    { "$unwind": "$userRole" },
                    { $project: { _id: 1, first_name: 1, last_digit_phone: 1, last_name: 1, phone: 1, email: 1, user_role: "$userRole.title", salt_key: 1, hospital_name: 1,hospital_id:1 } },
                ]),
                await User.countDocuments({ _id: new mongoose.Types.ObjectId(user_id) })
            ])

            let fullName = `${data[0].first_name}`.charAt(0).toUpperCase() + `${data[0].first_name}`.slice(1) + " " + `${data[0].last_name}`.charAt(0).toUpperCase() + `${data[0].last_name}`.slice(1);
            if (data[0].user_role == 'doctor' || data[0].user_role == 'patient') {

                fullName = `${data[0].first_name}`.charAt(0).toUpperCase() + `${data[0].first_name}`.slice(1) + " " + `${data[0].last_name}`.charAt(0).toUpperCase() + `${data[0].last_name}`.slice(1);
            }
            else {
                fullName = `${data[0].hospital_name}`.charAt(0).toUpperCase() + `${data[0].hospital_name}`.slice(1);
            }
            const token = await userObject.generateToken(data[0].salt_key);//generate token

            let updatedData = {
                $set: { account_verify_token: token },
                $push: { auth_token: token }
            }
            await User.findOneAndUpdate({ _id: data[0]._id }, updatedData, { new: true })
            let link = `${process.env.WEB_ENDPOINT}/auth/email-verification/${data[0]._id}/${token}`
            if (lang === "fr") {
                await MobileOtp(userInfoData.phone_number.e164Number, `Salut ${fullName}, merci de vous être inscrit(e) sur Dr. Hivey ! 🎉 Votre compte a été créé avec succès.

Avec votre nouveau compte, vous pouvez :

Prendre des rendez-vous en ligne
Accéder à vos dossiers médicaux
Recevoir des mises à jour importantes sur votre santé
Trouver des médecins et hôpitaux à proximité
Nous sommes ravis de vous avoir parmi nous !
                                        `)
            } else if (lang === "ar") {
                await MobileOtp(userInfoData.phone_number.e164Number, `مرحبًا ${fullName}، شكرًا لتسجيلك في Dr. Hivey! 🎉 تم إنشاء حسابك بنجاح.

مع حسابك الجديد، يمكنك:

حجز المواعيد عبر الإنترنت
الوصول إلى سجلاتك الطبية
تلقي التحديثات الصحية الهامة
العثور على الأطباء والمستشفيات القريبة منك
نحن متحمسون لوجودك معنا!


                    `)
            } else {
                await MobileOtp(userInfoData.phone_number.e164Number, `Hi ${fullName}, thank you for registering with Dr. Hivey! 🎉 Your account has been successfully created.

With your new account, you can:

Schedule appointments online
Access your medical records
Receive important health updates
Find nearby doctors & hospitals
We're excited to have you with us!
                    `)
            }
            let templateData = (lang === "en") ? signUpTemplate({ fullName, link }) :
                (lang === "ar") ? signUpTemplate_ar({ fullName, link }) :
                    signUpTemplate_fr({ fullName, link });
            const mailOptions = {
                to: data[0].email,
                subject: templateData.subject,
                html: templateData.html
            };
            let isEmailSent = await sendEmail(mailOptions, res)
            let sentStatus = 'PENDING'
            if (isEmailSent) {
                sentStatus = 'SUCCESS'
            }
            let cronPostParams = {
                "user_id": data[0]._id,
                "email_to": data[0].email,
                "email_subject": templateData.subject,
                "email_content": templateData.html,
                "cron_email_type": "EMAIL_REGISTRATION",
                "cron_email_status": sentStatus
            }
            let saveEmail = new CronEmail(cronPostParams)
            saveEmail.save()

            // return res.json({
            //     is_error: false,
            //     response_code: 200,
            //     count: count,
            //     data: data,
            //     req
            // })

            // await OTP.findOneAndUpdate({ _id: existingRecord._id }, { is_expired: true }, { new: true });

            let fcmtoken = await Fcm.create({ user_id, device_token, device_type });
            console.log(fcmtoken);
            return res.json({
                is_error: false,
                response_code: 200,
                count: count,
                token: token,
                data: data
            })
        } else {
            return apiResponse(res, true, [], ERROR_MSG[`OTP-MISMATCH-${lang}`], CLIENT_ERROR.badRequest, 0, [], req)
        }
    } catch (error) {
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }
}




//  password reset 
exports.checkPasswordLinkExpire = async (req, res) => {

    // If no validation errors, get the req.body objects that were validated and are needed
    let lang = req.headers["accept-language"] || 'en'
    const { user_id, forgotToken } = req.body
    //checking unique email
    let existingUser = await User.findOne({ _id: user_id }, { _id: 1, password: 1, email: 1, reset_password_token: 1, salt_key: 1 })

    if (!existingUser) return apiResponse(res, true, [], ERROR_MSG[`ACCOUNT-NOT-EXIST-${lang}`], CLIENT_ERROR.badRequest, [])
    if (existingUser.reset_password_token.length <= 0) return apiResponse(res, true, [], ERROR_MSG[`LINK-EXPIRED-${lang}`], CLIENT_ERROR.badRequest, [])

    if (existingUser.reset_password_token != forgotToken) return apiResponse(res, true, [], ERROR_MSG[`INVALID-ACCOUNT-TOKEN-${lang}`], CLIENT_ERROR.badRequest, [])
    return apiResponse(res, true, [], '', SUCCESS.OK, 0, [existingUser], req)

}
// forgot password
exports.forgotPassword = async (req, res) => {
    let lang = req.headers["accept-language"] || 'en'
    try {
        const { user_id, phone_number, email, language } = req.body
        let data
        if (phone_number && phone_number != null) {
            data = await User.findOne({ "phone_number.nationalNumber": phone_number.nationalNumber })
        } else {
            data = await User.findOne({ email: email.toLowerCase() })
        }

        if (!data) return apiResponse(res, true, [], ERROR_MSG[`ACCOUNT-NOT-EXIST-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);
        let generatedOTP = await Math.floor(Math.random() * (9999 - 1000 + 1) + 1000);
        // await Math.floor(Math.random() * (9999 - 1000 + 1) + 1000);
        let infoUser = await User.findOne({email:email}, { _id: 1, selected_language: 1 })
        if (phone_number && phone_number != null) {
            if (infoUser.selected_language === 'fr') {

                await MobileOtp(phone_number.e164Number, `Dr. Hivey : Votre code de réinitialisation de mot de passe est ${generatedOTP}. Utilisez ce code pour réinitialiser votre mot de passe. Si vous n'avez pas demandé cela, veuillez ignorer ce message.`)
            }
            else if (infoUser.selected_language === 'ar') {
                await MobileOtp(phone_number.e164Number, `Dr. Hivey: رمز إعادة تعيين كلمة المرور الخاصة بك هو ${generatedOTP}. استخدم هذا الرمز لإعادة تعيين كلمة المرور الخاصة بك. إذا لم تطلب ذلك، يرجى تجاهل هذه الرسالة.`)
            }
            else {

                await MobileOtp(phone_number.e164Number, `Dr. Hivey: Your password reset code is ${generatedOTP}. Use this code to reset your password. If you did not request this, please ignore this message.`)
            }

            let otpObj = {
                user_id: data._id,
                otp: generatedOTP,
                action: 'Forgot password otp on phone'
            }
            let newRecord = new OTP(_.pick(otpObj, ['user_id', 'otp', 'action']));
            newRecord.save()
                .then(async function (lookupData) {
                    let dataShow = {
                        _id: data._id,
                        phone: `******${data.last_digit_phone}`,

                    }
                    await User.findOneAndUpdate({ _id: data._id }, { otp: generatedOTP })
                    return apiResponse(res, false, [], SUCCESS_MSG[`OTP-SEND-${lang}`], SUCCESS.OK, 0, dataShow, req)
                })
                .catch(function (err) {
                    return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
                });
        }
        else if (email && email != null) {
            let userDetails = await User.findOne({email:email}, { _id: 1, first_name: 1, last_name: 1, email: 1, dob: 1, selected_language: 1 })
            let userFullName = `${userDetails.first_name}`.charAt(0).toUpperCase() + `${userDetails.first_name}`.slice(1) + " " + `${userDetails.last_name}`.charAt(0).toUpperCase() + `${userDetails.last_name}`.slice(1);
            let templateData;

            if (userDetails.selected_language === 'fr') {
                // Use the French version of the template
                templateData = await forgetPasswordTemplate_fr({ userFullName, generatedOTP });
            }
            else if (userDetails.selected_language === 'ar') {
                templateData = await forgetPasswordTemplate_ar({ userFullName, generatedOTP });
            }
            else {
                // Use the default (English) version of the template
                templateData = await forgetPasswordTemplate({ userFullName, generatedOTP });
            }
            // let templateData = await forgetPasswordTemplate({ userFullName,generatedOTP })
            const mailOptions = {
                to: email,
                subject: templateData.subject,
                html: templateData.html
            };

            let isEmailSent = await sendEmail(mailOptions, res)
            let sentStatus = 'PENDING'
            if (isEmailSent) {
                sentStatus = 'SUCCESS'
            }

            let cronPostParams = {
                "user_id": data._id,
                "email_to": email,
                "email_subject": mailOptions.subject,
                "email_content": mailOptions.html,
                "cron_email_type": "EMAIL_FORGOT_PASSWORD_OTP",
                "cron_email_status": sentStatus
            }
            let saveEmail = new CronEmail(cronPostParams)
            saveEmail.save()
            let otpObj = {
                user_id: data._id,
                otp: generatedOTP,
                action: 'Resend otp on email'
            }

            let newRecord = new OTP(_.pick(otpObj, ['user_id', 'otp', 'action']));
            newRecord.save()
                .then(async function (lookupData) {
                    await User.findOneAndUpdate({ _id: data._id }, { otp: generatedOTP })
                    let dataShow = {
                        _id: data._id,
                        email: data.show_email
                    }

                    return apiResponse(res, false, [], SUCCESS_MSG[`FORGOT-PASSWORD-OTP-SEND-${lang}`], SUCCESS.OK, 0, dataShow, req)
                })
                .catch(function (err) {
                    return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
                });
        }

    } catch (error) {
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }
}

// category listing 
exports.categoryListing = async (req, res) => {
    try {
        var title_lang = req.params.lang || 'en'
        let lang = req.headers["accept-language"] || 'en'
        let languageTitle = 'title_' + title_lang
        let records = await Category.find({ is_deleted: false, is_active: true })
        records = records.map(record => {
            return {
                name: record[languageTitle],
                _id: record._id,
                image: record.image
            };
        });
        let count = await Category.countDocuments({ is_deleted: false, is_active: true })
        if (records) {
            return apiResponse(res, false, [], '', SUCCESS.OK, count, records, req)
        }
    } catch (error) {
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${title_lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }
}

// resend otp 
exports.resendOtp = async (req, res) => {
    let lang = req.headers["accept-language"] || 'en'
    // If no validation errors, get the req.body objects that were validated and are needed
    try {
        const { user_id, phone_number, email } = req.body;

        //expired all otp regarding user_id
        await OTP.updateMany({ user_id: new mongoose.Types.ObjectId(user_id), is_expired: false }, { is_expired: true }, { new: true });
        //end of expired all otp regarding user id

        let data = await User.findOne({ "_id": user_id }, { phone_number: 1, email: 1, _id: 1 })
        if (!data) return apiResponse(res, true, [], ERROR_MSG[`ACCOUNT-NOT-EXIST-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);
        let generatedOTP = await Math.floor(Math.random() * (9999 - 1000 + 1) + 1000);
        // await Math.floor(Math.random() * (9999 - 1000 + 1) + 1000);
        if (phone_number && phone_number != null) {
            await MobileOtp(phone_number.e164Number, `Dr. Hivey: Your verification code is ${generatedOTP}. Please enter this code to continue. If you did not request this, please ignore this message.`)
            let otpObj = {
                user_id: data._id,
                otp: generatedOTP,
                action: 'Resend otp on phone'
            }
            let newRecord = new OTP(_.pick(otpObj, ['user_id', 'otp', 'action']));
            newRecord.save()
                .then(async function (lookupData) {
                    let dataShow = {
                        _id: data._id,
                        phone: data.last_digit_phone
                    }
                    await User.findOneAndUpdate({ _id: data._id }, { otp: generatedOTP })
                    return apiResponse(res, false, [], SUCCESS_MSG[`OTP-SEND-${lang}`], SUCCESS.OK, 0, dataShow, req)
                })
                .catch(function (err) {
                    return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
                });
        }
        else if (email && email != null) {
            const mailOptions = {
                to: email,
                subject: "Resend one-time-password",
                html: `Your resend one-time-password is: ${generatedOTP}`
            };
            // await sendEmail(mailOptions);
            let isEmailSent = await sendEmail(mailOptions, res)
            let sentStatus = 'PENDING'
            if (isEmailSent) {
                sentStatus = 'SUCCESS'
            }
            let cronPostParams = {
                "user_id": data._id,
                "email_to": data.email,
                "email_subject": mailOptions.subject,
                "email_content": mailOptions.html,
                "cron_email_type": "EMAIL_RSEND_OTP",
                "cron_email_status": sentStatus
            }
            let saveEmail = new CronEmail(cronPostParams)
            saveEmail.save()
            let otpObj = {
                user_id: data._id,
                otp: generatedOTP,
                action: 'Resend otp on email'
            }
            let newRecord = new OTP(_.pick(otpObj, ['user_id', 'otp', 'action']));
            newRecord.save()
                .then(async function (lookupData) {
                    await User.findOneAndUpdate({ _id: data._id }, { otp: generatedOTP })
                    let dataShow = {
                        _id: data._id, email: data.email
                    }
                    return apiResponse(res, false, [], SUCCESS_MSG[`OTP-SEND-${lang}`], SUCCESS.OK, 0, dataShow, req)
                })
                .catch(function (err) {
                    return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
                });
        }

    } catch (error) {

        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }
}

/**
 * after forgot password reset password for the user
 * check user by the new token
 * update existing user password  
 * **/
exports.updatePassword = async (req, res) => {

    let lang = req.headers["accept-language"] || 'en'
    // If no validation errors, get the req.body objects that were validated and are needed
    const { password, user_id, forgotToken } = req.body
    //checking unique email

    let existingUser = await User.findOne({ _id: user_id }, { _id: 1, password: 1, email: 1, reset_password_token: 1, salt_key: 1 })

    if (!existingUser) return apiResponse(res, true, [], ERROR_MSG[`ACCOUNT-NOT-REGISTERD-${lang}`], CLIENT_ERROR.badRequest, [])


    if (existingUser.reset_password_token.length <= 0) return apiResponse(res, true, [], ERROR_MSG[`LINK-EXPIRED-${lang}`], CLIENT_ERROR.badRequest, [])

    if (existingUser.reset_password_token != forgotToken) return apiResponse(res, true, [], ERROR_MSG[`INVALID-ACCOUNT-TOKEN-${lang}`], CLIENT_ERROR.badRequest, [])

    if (existingUser.reset_password_token == forgotToken) {
        const encryptedPassword = await userObject.encryptPassword(existingUser, password);//encrypted password
        if (encryptedPassword == existingUser.password) {
            return apiResponse(res, true, [], ERROR_MSG[`USE-ANOTHER-PASSWORD-${lang}`], CLIENT_ERROR.badRequest, 0, [], req)
        }
        await User.findOneAndUpdate({ email: existingUser.email }, { $set: { password: encryptedPassword, updatedAt: new Date(), reset_password_token: '' } }, { new: true })
        return apiResponse(res, true, [], '', SUCCESS.OK, 0, { "id": existingUser._id }, req)
    }
}

exports.userInfo = async (req, res) => {
    const { id } = req.body
    let lang = req.headers["accept-language"] || 'en'
    let condition = {}
    condition['_id'] = mongoose.Types.ObjectId(id);

    //checking unique email
    let userInformation = await User.aggregate([

        { $match: condition },
        {
            $lookup: {
                from: 'roles',
                localField: "user_role",
                foreignField: "_id",
                as: 'user_role',
            },

        },
        { "$unwind": "$user_role" },
        {
            $lookup: {
                from: 'secret_questions',
                localField: "secret_question",
                foreignField: "_id",
                as: 'secret_question',
            },

        },
        { "$unwind": "$secret_question" },
    ]);

    if (!userInformation) return apiResponse(res, true, [], ERROR_MSG[`ACCOUNT-NOT-EXIST-${lang}`], CLIENT_ERROR.badRequest, 0, []);

    return apiResponse(res, false, [], '', SUCCESS.OK, 0, userInformation[0], req);
}


// user profile  info
exports.userProfileInformation = async (req, res) => {
    const { user_id } = req.body
    let lang = req.headers["accept-language"] || 'en'


    //checking unique email
    const [data, count] = await Promise.all([
        User.aggregate([
            { $match: { _id: new mongoose.Types.ObjectId(user_id) } },
            {
                $lookup: {
                    from: "roles",
                    as: "userRole",
                    let: { userRole_id: "$user_role" },
                    pipeline: [
                        {
                            $match: {
                                $and: [
                                    {
                                        $expr: { $eq: ["$$userRole_id", "$_id"] },
                                    },
                                    // filteredQueryUsersTable
                                ]
                            },
                        },
                        { $project: { _id: 1, title: 1 } },

                    ],
                },
            },
            { "$unwind": "$userRole" },
            {
                $project: {
                    _id: 1, first_name: 1, last_digit_phone: 1, last_name: 1, phone: 1, email: 1,
                    dob: 1, gender: 1, social_security_number: 1, phone_number: 1, branch_of_medicines: 1, primary_specialty: 1, additional_specialty: 1, qualification: 1, year_of_practice: 1, additional_qualification: 1, spoken_language: 1, certificate: 1, profile_pic: 1, street_address: 1, country: 1, city: 1, state: 1, zip_code: 1, clinic_name: 1, clinic_contact: 1, clinic_open_time: 1, clinic_close_time: 1, spoken_language_name: 1, location: 1, user_role: "$userRole.title", primary_specialty_name: 1, clinic_timing: 1, buffer_time: 1, is_fulltime: 1, is_deleted: 1, hospital_name: 1, street_address2: 1, is_auto_req_accept: 1 , platform_booking_status : 1,
                    hospital_id:1
                }
            },
        ]),
        await User.countDocuments({ _id: new mongoose.Types.ObjectId(user_id) })
    ])

    if (!data) return apiResponse(res, true, [], ERROR_MSG[`ACCOUNT-NOT-EXIST-${lang}`], CLIENT_ERROR.badRequest, 0, []);

    return apiResponse(res, false, [], '', SUCCESS.OK, count, data, req);
}

exports.changePassword = async (req, res) => {
    const { id, oldPassword, Password } = req.body
    let lang = req.headers["accept-language"] || 'en'
    //checking user
    let existingUser = await User.findOne(
        { _id: new mongoose.Types.ObjectId(id) },
        { _id: 1, email: 1, password: 1, salt_key: 1, createdAt: 1 }
    );


    if (!existingUser) return apiResponse(res, true, [], ERROR_MSG[`ACCOUNT-NOT-REGISTERD-${lang}`], CLIENT_ERROR.badRequest, [], req)

    const encryptedOldPassword = await userObject.encryptPassword(existingUser, oldPassword);//encrypted password

    if (encryptedOldPassword != existingUser.password) return apiResponse(res, true, [], ERROR_MSG[`OLD-PASSWORD-NOT-MATCHED-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);

    const encryptedPassword = await userObject.encryptPassword(existingUser, Password);//encrypted password

    if (encryptedPassword == existingUser.password) {
        return apiResponse(res, true, [], ERROR_MSG[`USE-ANOTHER-PASSWORD-${lang}`], CLIENT_ERROR.badRequest, 0, [], req)
    }
    await User.findOneAndUpdate({ email: existingUser.email }, { $set: { password: encryptedPassword, updatedAt: new Date() } }, { new: true })
    return apiResponse(res, true, [], '', SUCCESS.OK, 0, existingUser, req)
}

exports.changeSecretQuestion = async (req, res) => {
    const { id, secretQuestion, secretAnswer } = req.body
    let lang = req.headers["accept-language"] || 'en'
    //checking user
    let existingUser = await User.findOne(
        { _id: mongoose.Types.ObjectId(id) },
        { _id: 1, email: 1, secret_question: 1, secret_answer: 1, createdAt: 1 }
    );

    if (!existingUser) return apiResponse(res, true, [], ERROR_MSG[`ACCOUNT-NOT-REGISTERD-${lang}`], CLIENT_ERROR.badRequest, [])

    await User.findOneAndUpdate({ email: existingUser.email }, { $set: { secret_question: secretQuestion, secret_answer: secretAnswer, updatedAt: new Date() } }, { new: true })
    existingUser['salt_key'] = null;
    return apiResponse(res, true, [], '', SUCCESS.OK, 0, existingUser, req)
}
// account varify
exports.verify = async (req, res) => {
    try {
        const userId = req.params.user_id;


        //checking user exist or not
        let existingUser = await User.findOne(
            { _id: userId },
            { account_verify_token: 1, is_verified: 1 }
        );

        // if user not exists in db
        if (!existingUser) return apiResponse(res, true, [], ERROR_MSG['ACCOUNT-NOT-EXIST'], CLIENT_ERROR.badRequest, 0, []);

        // if link already used and no data into the table
        if (existingUser.account_verify_token.length <= 0 || req.params.token != existingUser.account_verify_token) {
            return apiResponse(res, true, [], ERROR_MSG['LINK-EXPIRED'], CLIENT_ERROR.badRequest, 0, []);
        }



        // check otp and remove data from temp and insert into user table
        if (req.params.token == existingUser.account_verify_token) {
            let user = await User.findOneAndUpdate({ _id: userId }, { $set: { is_verified: true, account_verify_token: '' } }, { new: true })
            return apiResponse(res, false, [], '', SUCCESS.OK, 0, [{ ok: true }])
        }
    } catch (err) {
        return apiResponse(res, true, [], ERROR_MSG['SYSTEM-ERROR'], SERVER_ERROR.internalServerError, 0, [])
    }

}


// list spoken language
exports.languageListing = async (req, res) => {
    let lang = req.headers["accept-language"] || 'en'
    try {
        let language = await Language.find({ is_deleted: false, is_active: true }, { title: 1 });
        let count = await Language.countDocuments({ is_deleted: false, is_active: true })
        return apiResponse(res, true, [], '', SUCCESS.OK, count, language, req)
    } catch (err) {
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }

}

// check user email or phone already exits or not 
exports.existingUser = async (req, res) => {
    let lang = req.headers["accept-language"] || 'en'
    try {
        let existingPhoneUser
        const { email, phone_number } = req.body;
        if (phone_number && phone_number != null) {
            existingPhoneUser = await User.findOne(
                { "phone_number.nationalNumber": phone_number.nationalNumber },
                { _id: 1, is_completed: 1, email: 1, phone_number: 1, is_signup: 1, is_signup_otp_varify: 1, is_verified: 1 }
            );
        }
        let existingEmailUser = await User.findOne(
            { "email": email },
            { _id: 1, is_completed: 1, email: 1, phone_number: 1, is_signup: 1, is_signup_otp_varify: 1, is_verified: 1 }
        );
        let existingUser = (existingPhoneUser && existingPhoneUser != null) ? existingPhoneUser : existingEmailUser


        if (existingPhoneUser && existingEmailUser == null) {
            return apiResponse(res, true, [], ERROR_MSG[`PHONE-ALREADY-EXIST-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);
        }
        if (existingEmailUser && existingPhoneUser == null) {
            return apiResponse(res, true, [], ERROR_MSG[`EMAIL-ALREADY-EXIST-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);
        }

        if (existingUser && existingUser.is_signup_otp_varify == false) return apiResponse(res, true, [], ERROR_MSG[`SIGNUP-OTP-NOT-VARIFY-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);

        // if (existingUser && existingUser.is_verified == false) return apiResponse(res, true, [], ERROR_MSG[`ACCOUNT-NOT-VERIFIED-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);

        if (existingUser && existingUser.is_signup == true && existingUser.is_signup_otp_varify == true) {
            if (existingPhoneUser && existingPhoneUser.phone_number != null) {
                return apiResponse(res, true, [], ERROR_MSG[`PHONE-ALREADY-EXIST-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);
            }
            else {
                return apiResponse(res, true, [], ERROR_MSG[`EMAIL-ALREADY-EXIST-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);
            }

        }


        return apiResponse(res, true, [], '', SUCCESS.OK, 0, [], req)
    } catch (err) {
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }

}


exports.contactUs = async (req, res) => {

    //save user 
    var newContact = new Contact(_.pick(req.body, ['first_name', 'email', 'subject', 'message', 'last_name', 'phone_number']));

    newContact.save()
        .then(async function (contact) {
            let link = `${process.env.WEB_ENDPOINT}`
            let fullName = contact.first_name;
            let templateData = contactUsTemplate({ fullName, link })
            const mailOptions = {
                to: contact.email,
                subject: templateData.subject,
                html: templateData.html
            };
            let isEmailSent = await sendEmail(mailOptions, res)
            let sentStatus = 'PENDING'
            if (isEmailSent) {
                sentStatus = 'SUCCESS'
            }
            let cronPostParams = {
                "user_id": contact._id,
                "email_to": contact.email,
                "email_subject": templateData.subject,
                "email_content": templateData.html,
                "cron_email_type": "CONTACT_US",
                "cron_email_status": sentStatus
            }
            let saveEmail = new CronEmail(cronPostParams)
            saveEmail.save()

            // let templateDataAdmin = contactUsTemplateAdmin({ name, email, subject, message })
            // const mailOptionsAdmin = {
            //     to: `${process.env.CONTACT_US_EMAIL}`,
            //     subject: templateDataAdmin.subject,
            //     html: templateDataAdmin.html
            // };
            // await sendEmail(mailOptionsAdmin, res)


            let userData = _.pick(contact, ['_id'])

            return apiResponse(res, false, [], '', SUCCESS.OK, 1, userData, req)
        })
        .catch(function (err) {
            return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR`], SERVER_ERROR.internalServerError, 0, [], req)
        });



}

exports.expiredOtpByUserId = async (req, res) => {
    let lang = req.headers["accept-language"] || 'en'
    try {
        const { user_id } = req.body;

        await OTP.updateMany({ user_id: new mongoose.Types.ObjectId(user_id), is_expired: false }, { is_expired: true }, { new: true });

        return apiResponse(res, false, [], '', SUCCESS.OK, 1, [], req)

    } catch (err) {
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }
}


// delete my account

exports.deleteMyAccount = async (req, res) => {
    let lang = req.headers["accept-language"] || 'en'
    try {
        const { user_id } = req.body;

        await User.findOneAndUpdate({ _id: new mongoose.Types.ObjectId(user_id) }, { is_deleted: true }, { new: true })
        return apiResponse(res, false, [], '', SUCCESS.OK, 1, [], req)

    } catch (err) {
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }
}



// signup otp varification
exports.getUserInfo = async (req, res) => {

    // If no validation errors, get the req.body objects that were validated and are needed
    let lang = req.headers["accept-language"] || 'en'
    try {
        const { id } = req.params
        let user_id = id;

        let userInfoData = await User.findOne({ _id: user_id }, { phone_number: 1 })

        await User.findOneAndUpdate({ _id: user_id }, { is_signup_otp_varify: true, is_signup: true, selected_language: lang }, { new: true })
        const [data, count] = await Promise.all([
            User.aggregate([
                { $match: { _id: new mongoose.Types.ObjectId(user_id) } },
                {
                    $lookup: {
                        from: "roles",
                        as: "userRole",
                        let: { userRole_id: "$user_role" },
                        pipeline: [
                            {
                                $match: {
                                    $and: [
                                        {
                                            $expr: { $eq: ["$$userRole_id", "$_id"] },
                                        },
                                        // filteredQueryUsersTable
                                    ]
                                },
                            },
                            { $project: { _id: 1, title: 1 } },

                        ],
                    },
                },
                { "$unwind": "$userRole" },
                {
                    $project: {
                        _id: 1, first_name: 1, last_digit_phone: 1, last_name: 1, phone: 1, email: 1, "is_completed": 1, "selected_language": 1,
                        "user_account_status": 1, user_role: "$userRole.title", salt_key: 1, hospital_name: 1,hospital_id:1
                    }
                },
            ]),
            await User.countDocuments({ _id: new mongoose.Types.ObjectId(user_id) })
        ])

        let fullName = `${data[0].first_name}`.charAt(0).toUpperCase() + `${data[0].first_name}`.slice(1);
        if (data[0].user_role == 'doctor' || data[0].user_role == 'patient') {

            fullName = `${data[0].first_name}`.charAt(0).toUpperCase() + `${data[0].first_name}`.slice(1) + " " + `${data[0].last_name}`.charAt(0).toUpperCase() + `${data[0].last_name}`.slice(1);
        }
        else {
            fullName = `${data[0].hospital_name}`.charAt(0).toUpperCase();
        }
        const token = await userObject.generateToken(data[0].salt_key);//generate token

        let updatedData = {
            $set: { account_verify_token: token },
            $push: { auth_token: token }
        }
        await User.findOneAndUpdate({ _id: data[0]._id }, updatedData, { new: true })


        return res.json({
            is_error: false,
            response_code: 200,
            count: count,
            token: token,
            data: data
        })

    } catch (error) {
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }
}

