import { Console } from "console";
import { Message } from "node-mailjet";
const _ = require('lodash');
require('dotenv').config({ path: __dirname + '../.env' })
const mongoose = require("mongoose");
const { User } = require('../../models/user');
const { CronEmail } = require('../../models/email')
const { Role } = require('../../models/role');
const { sendEmail } = require('../../core/utilities/emailService');
const { BookingAppointment } = require('../../models/booking');
const { BlockUser } = require('../../models/block-users');
const { Notification } = require('../../models/notification');
const { DoctorAvaliblitySlot } = require("../../models/doctor-avaliblity-slots")
const { apiResponse } = require("../../core/response/response")
const { Fcm } = require("../../models/fcm-tokens")
const { SUCCESS, REDIRECTION, CLIENT_ERROR, SERVER_ERROR } = require("../../core/response/statusCode")
const { ERROR_MSG, SUCCESS_MSG, DOCTOR_NOTIFY, PATIENT_NOTIFY } = require("../../core/response/messages")
const { addNotification } = require("../common/notification.controller")
const { sendPushNotification } = require("../../core/utilities/pushNotification");
const { MobileOtp } = require("../../core/utilities/mobileOtp");
const { dateFormat } = require('../../core/utilities/commonService');

const { newAppointmentEmailTemplate, newAppointmentEmailTemplate_fr, newAppointmentEmailTemplate_ar, patientRescheduleAppointmentTemplate, patientRescheduleAppointmentTemplate_fr, patientRescheduleAppointmentTemplate_ar, patientAppoinmentRejectedTemplate, patientAppoinmentRejectedTemplate_fr, patientAppoinmentRejectedTemplate_ar, RegisteredByAdmin, contactUsTemplate } = require('../../core/email-templates/email-web')

const { BookingHistory } = require("../../models/booking-histories");



exports.editPatientProfile = async (req, res) => {
    let lang = req.headers["accept-language"] || 'en'
    try {
        const { patient_id } = req.body;
        const details = await User.findById(req['user']._id).populate('user_role');
        if (!details) {
            return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
        }

        if (details.user_role.title != 'patient') {
            return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
        }


        let updateProfile = await User.findOneAndUpdate({ _id: req['user']._id }, { $set: req.body }, { new: true });
        return apiResponse(res, false, [], SUCCESS_MSG[`USER-UPDATED-${lang}`], SUCCESS.OK, 0, [], req)
    } catch (error) {
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }
}

// doctor listing
exports.doctorListing = async (req, res) => {
    let lang = req.headers["accept-language"] || 'en'
    try {
        const { user_id, otp, hospital_id } = req.body
        let filteredQuery = {}
        filteredQuery = { is_completed: true, is_deleted: false }
        let userRole = await Role.find({ $or: [{ title: 'doctor' }, { title: 'hospital' }] })
        filteredQuery['user_role'] = { $in: userRole.map(item => new mongoose.Types.ObjectId(item._id)) }

        const [data, count] = await Promise.all([
            User.aggregate([
                { $match: filteredQuery },
                {
                    $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, email: 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, clinic_name: 1, clinic_contact: 1, clinic_open_time: 1, clinic_close_time: 1, street_address: 1, location: 1, gender: 1, user_role: "$userRole.title" } },
            ]),
            await User.countDocuments(filteredQuery)
        ])

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

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



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

    const lang = req.headers["accept-language"] || 'en'

    // If no validation errors, get the req.body objects that were validated and are needed
    const { patient_id, hospital_doctor_id, slot, booking_date, booking_role_type, booking_speciality, status, reschedule_date, reschedule_slot, document_file, role_name, language, guardian_id, hospital_id, consultation_reason } = req.body;

    let booking_id = generateBookingId();
    req.body.booking_id = booking_id;

    let __date = new Date(booking_date);
    req['booking_date'] = (new Date(booking_date)).setHours(0, 0);
    let findExistsRecord = null;

    const doctorHospitalDetails = await User.findById(hospital_doctor_id).populate('user_role');

    try {


        let checkFullTimePartTime = await User.findOne({ _id: new mongoose.Types.ObjectId(hospital_doctor_id) });


        if (checkFullTimePartTime && checkFullTimePartTime.is_fulltime) {

            if (role_name == "doctor") {
                findExistsRecord = await BookingAppointment.findOne({
                    $or: [
                        {
                            booking_date: { $gte: __date, $lt: new Date(__date.getTime() + 24 * 60 * 60 * 1000) },
                            hospital_doctor_id: new mongoose.Types.ObjectId(hospital_doctor_id),
                            slot: slot,
                            reschedule_slot: null,
                            status: { $ne: 'REJECTED' }
                        },
                        {
                            reschedule_date: { $gte: __date, $lt: new Date(__date.getTime() + 24 * 60 * 60 * 1000) },
                            hospital_doctor_id: new mongoose.Types.ObjectId(hospital_doctor_id),
                            reschedule_slot: slot,
                            status: { $ne: 'REJECTED' }
                        }
                    ]
                });
            } else {
                //Hospital Case
                findExistsRecord = await BookingAppointment.findOne({
                    $or: [
                        {
                            booking_date: { $gte: __date, $lt: new Date(__date.getTime() + 24 * 60 * 60 * 1000) },
                            hospital_doctor_id: new mongoose.Types.ObjectId(hospital_doctor_id),
                            booking_speciality: new mongoose.Types.ObjectId(booking_speciality),
                            slot: slot,
                            reschedule_slot: null,
                            status: { $ne: 'REJECTED' }
                        },
                        {
                            reschedule_date: { $gte: __date, $lt: new Date(__date.getTime() + 24 * 60 * 60 * 1000) },
                            hospital_doctor_id: new mongoose.Types.ObjectId(hospital_doctor_id),
                            booking_speciality: new mongoose.Types.ObjectId(booking_speciality),
                            reschedule_slot: slot,
                            status: { $ne: 'REJECTED' }
                        }
                    ]
                });
            }
        }



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

    if (findExistsRecord) {
        console.log(doctorHospitalDetails.clinic_timing);
        return apiResponse(res, true, [], ERROR_MSG[`ALREADY-SLOTS-BOOKED-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);
    }

    let isBlockedByDoctor = await BlockUser.findOne({ patient_id: new mongoose.Types.ObjectId(patient_id), hospital_doctor_id: new mongoose.Types.ObjectId(hospital_doctor_id), is_blocked_user: true });

    if (isBlockedByDoctor) {
        return apiResponse(res, true, [], ERROR_MSG[`BLOCKED-BY-DOCTOR-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);
    }


    let doctor = await User.findOne({ _id: new mongoose.Types.ObjectId(req.body.hospital_doctor_id) });

    if (doctor.is_auto_req_accept) {
        // when auto accept req is ON  

        req.body['status'] = 'APPROVED';
        new BookingAppointment(_.pick(req.body, ['booking_id', 'patient_id', 'hospital_doctor_id', 'slot', 'booking_date', 'booking_role_type', 'booking_speciality', 'status', 'reschedule_date', 'reschedule_slot', 'document_file', 'guardian_id', 'consultation_reason'])).save()
            .then(async function (data) {

                //save data in booking history

                let saveHistoryDataCondition = {
                    booking_id: data._id,
                    patient_id: data.patient_id,
                    hospital_doctor_id: data.hospital_doctor_id,
                    action_by: role_name,
                    status: status,
                    guardian_id: guardian_id
                }

                let bookingModal = new BookingHistory(saveHistoryDataCondition);

                await bookingModal.save();

                //end of save data in booking history

                // email send to doctor
                let patient = await User.findOne({ _id: new mongoose.Types.ObjectId(data.patient_id) }, { _id: 1, first_name: 1, last_name: 1, email: 1, dob: 1 }).populate('guardian_id').exec();
                let doctor = await User.findOne({ _id: new mongoose.Types.ObjectId(data.hospital_doctor_id) }, { _id: 1, first_name: 1, last_name: 1, email: 1, dob: 1, clinic_name: 1, hospital_name: 1 });


                let patientFullName = `${patient.first_name}`.charAt(0).toUpperCase() + `${patient.first_name}`.slice(1) + " " + `${patient.last_name}`.charAt(0).toUpperCase() + `${patient.last_name}`.slice(1);

                let doctorFullName = `${doctor.first_name}`.charAt(0).toUpperCase() + `${doctor.first_name}`.slice(1) + " " + `${doctor.last_name}`.charAt(0).toUpperCase() + `${doctor.last_name}`.slice(1);


                let appointmentType = await Role.findOne({ _id: new mongoose.Types.ObjectId(data.booking_role_type) }, { title: 1 })
                let action = data



                let condition = {}
                condition['_id'] = new mongoose.Types.ObjectId(hospital_doctor_id);
                let record = await User.findOne(condition, { _id: 1, selected_language: 1, phone_number: 1 });

                const dateString = action.booking_date;
                const date = new Date(dateString);

                const formattedDate = `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`;
                let templateData;
                let doctorClinicName = doctor.hospital_name?.trim() ? doctor.hospital_name : doctor.clinic_name
                doctorFullName = doctorFullName ? doctorFullName : doctor.hospital_name
                if (record.selected_language === 'fr') {
                    templateData = await newAppointmentEmailTemplate_fr({ patientFullName, doctorFullName, action, doctorClinicName })

                    await MobileOtp(record.phone_number?.e164Number, `Nouveau rendez-vous ! Docteur ${doctorFullName}, vous avez un nouveau rendez-vous avec ${patientFullName} le ${formattedDate} à ${action.slot}.`)


                } else if (record.selected_language === 'ar') {
                    templateData = await newAppointmentEmailTemplate_ar({ patientFullName, doctorFullName, action, doctorClinicName })
                    await MobileOtp(record.phone_number?.e164Number, `موعد جديد! دكتور ${doctorFullName}، لديك موعد جديد مع ${patientFullName} في ${formattedDate} الساعة ${action.slot}.`)

                }
                else {
                    templateData = await newAppointmentEmailTemplate({ patientFullName, doctorFullName, action, doctorClinicName })
                    await MobileOtp(record.phone_number?.e164Number, `New Appointment! Dr. ${doctorFullName}, you have a new appointment with ${patientFullName} on ${formattedDate} at ${action.slot}.
`)

                }


                const mailOptions = {
                    to: doctor.email,
                    subject: templateData.subject,
                    html: templateData.html
                };
                let isEmailSent = await sendEmail(mailOptions, res)
                let sentStatus = 'PENDING'
                if (isEmailSent) {
                    sentStatus = 'SUCCESS'
                }
                let cronPostParams = {
                    "user_id": doctor._id,
                    "email_to": doctor.email,
                    "email_subject": templateData.subject,
                    "email_content": templateData.html,
                    "cron_email_type": "New Applointment",
                    "cron_email_status": sentStatus
                }
                let saveEmail = new CronEmail(cronPostParams)
                saveEmail.save()
                // send notification to doctor/hospital
                let schema = {
                    user_id: data.hospital_doctor_id,
                    notify_en: DOCTOR_NOTIFY[`NEW-BOOKING-en`],
                    notify_ar: DOCTOR_NOTIFY[`NEW-BOOKING-ar`],
                    notify_fr: DOCTOR_NOTIFY[`NEW-BOOKING-fr`]
                }
                const userTokenDetails = await Fcm.find({ user_id: data.hospital_doctor_id });
                userTokenDetails.length && userTokenDetails.forEach(async (token) => {
                    await sendPushNotification(token?.device_token, 'Doctome', schema?.[`notify_${lang}`], { booking_id: String(data._id), d_screen_url: String(`${action.status}`) });
                });

                await addNotification(schema, req, res)

                let patientEmail = null;
                if (guardian_id) {
                    patientEmail = patient.guardian_id.email
                }

                // patient
                let patientSchema = {
                    user_id: data.guardian_id ? data.guardian_id : data.patient_id,
                    notify_en: PATIENT_NOTIFY[`NEW-BOOKING-en`],
                    notify_ar: PATIENT_NOTIFY[`NEW-BOOKING-ar`],
                    notify_fr: PATIENT_NOTIFY[`NEW-BOOKING-fr`]
                }

                const patientTokenDetails = await Fcm.find({ user_id: data.guardian_id ? data.guardian_id : data.patient_id });
                patientTokenDetails.length && patientTokenDetails.forEach(async (token) => {
                    await sendPushNotification(token?.device_token, 'Doctome', patientSchema?.[`notify_${lang}`], { booking_id: String(data._id), d_screen_url: String(`${action.status}`) });
                });
                await addNotification(patientSchema, req, res)

                return apiResponse(res, false, [], SUCCESS_MSG[`APPOINTMENT-BOOKED-${lang}`], SUCCESS.OK, 0, [], req)
            })
            .catch(function (err) {
                return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
            });
    }
    else {
        // when auto accept req is OFF 
        console.log("---------- Booking apyload --------", req.body);
        new BookingAppointment(_.pick(req.body, ['booking_id', 'patient_id', 'hospital_doctor_id', 'slot', 'booking_date', 'booking_role_type', 'booking_speciality', 'status', 'reschedule_date', 'reschedule_slot', 'document_file', 'guardian_id', 'hospital_id', 'consultation_reason'])).save()
            .then(async function (data) {

                //save data in booking history

                let saveHistoryDataCondition = {
                    booking_id: data._id,
                    patient_id: data.patient_id,
                    hospital_doctor_id: data.hospital_id ? data.hospital_id : data.hospital_doctor_id,
                    action_by: role_name,
                    status: status,
                    guardian_id: guardian_id
                }

                let bookingModal = new BookingHistory(saveHistoryDataCondition);

                await bookingModal.save();

                //end of save data in booking history

                // email send to doctor
                let patient = await User.findOne({ _id: new mongoose.Types.ObjectId(data.patient_id) }, { _id: 1, first_name: 1, last_name: 1, email: 1, dob: 1 }).populate('guardian_id').exec();
                let doctor = await User.findOne({ _id: new mongoose.Types.ObjectId(data.hospital_doctor_id) }, { _id: 1, first_name: 1, last_name: 1, email: 1, dob: 1, clinic_name: 1, hospital_name: 1 }).populate('user_role');
                let employerDetails = await User.findOne({ _id: new mongoose.Types.ObjectId(data.hospital_id) }, { _id: 1, first_name: 1, last_name: 1, email: 1, dob: 1, clinic_name: 1, hospital_name: 1 }).populate('user_role');


                let doctorClinicName = doctor.hospital_name?.trim() ? doctor.hospital_name : doctor.clinic_name;
                if (employerDetails) {
                    doctorClinicName = employerDetails.hospital_name;
                }
                let patientFullName = `${patient.first_name}`.charAt(0).toUpperCase() + `${patient.first_name}`.slice(1) + " " + `${patient.last_name}`.charAt(0).toUpperCase() + `${patient.last_name}`.slice(1);
                let doctorFullName;
                if (doctor.user_role.title == 'doctor') {

                    doctorFullName = `${doctor.first_name}`.charAt(0).toUpperCase() + `${doctor.first_name}`.slice(1) + " " + `${doctor.last_name}`.charAt(0).toUpperCase() + `${doctor.last_name}`.slice(1);
                }
                else {
                    doctorFullName = doctor.hospital_name;
                }


                let appointmentType = await Role.findOne({ _id: new mongoose.Types.ObjectId(data.booking_role_type) }, { title: 1 })
                let action = data



                let condition = {}
                condition['_id'] = new mongoose.Types.ObjectId(hospital_doctor_id);
                let record = await User.findOne(condition, { _id: 1, selected_language: 1, phone_number: 1 });

                const dateString = action.booking_date;
                const date = new Date(dateString);

                const formattedDate = `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`;
                let templateData;
                doctorFullName = doctorFullName ? doctorFullName : doctor.hospital_name
                let user_role = doctor.hospital_name ? 'hospital' : 'doctor'
                if (record.selected_language === 'fr') {
                    templateData = await newAppointmentEmailTemplate_fr({ patientFullName, doctorFullName, action, doctorClinicName, user_role })

                    await MobileOtp(record.phone_number?.e164Number, `Nouvelle demande de rendez-vous ! Dr. ${doctorFullName}, vous avez un nouveau rendez-vous avec ${patientFullName} le ${formattedDate} à ${action.slot}.

`)


                } else if (record.selected_language === 'ar') {
                    templateData = await newAppointmentEmailTemplate_ar({ patientFullName, doctorFullName, action, doctorClinicName, user_role })
                    await MobileOtp(record.phone_number?.e164Number, `طلب موعد جديد! د. ${doctorFullName}، لديك موعد جديد مع ${patientFullName} في ${formattedDate} الساعة ${action.slot}.

`)

                }
                else {
                    templateData = await newAppointmentEmailTemplate({ patientFullName, doctorFullName, action, doctorClinicName, user_role })
                    await MobileOtp(record.phone_number?.e164Number, `New Appointment Request! Dr. ${doctorFullName}, you have a new appointment with ${patientFullName} on ${formattedDate} at ${action.slot}.
`)

                }


                const mailOptions = {
                    to: data.hospital_id ? employerDetails.email : doctor.email,
                    subject: templateData.subject,
                    html: templateData.html
                };
                let isEmailSent = await sendEmail(mailOptions, res)
                let sentStatus = 'PENDING'
                if (isEmailSent) {
                    sentStatus = 'SUCCESS'
                }
                let cronPostParams = {
                    "user_id": doctor._id,
                    "email_to": data.hospital_id ? employerDetails.email : doctor.email,
                    "email_subject": templateData.subject,
                    "email_content": templateData.html,
                    "cron_email_type": "New Applointment",
                    "cron_email_status": sentStatus
                }
                let saveEmail = new CronEmail(cronPostParams)
                saveEmail.save()
                // send notification to doctor/hospital
                let schema = {
                    user_id: data.hospital_id ? employerDetails._id : data.hospital_doctor_id,
                    notify_en: DOCTOR_NOTIFY[`NEW-BOOKING-en`],
                    notify_ar: DOCTOR_NOTIFY[`NEW-BOOKING-ar`],
                    notify_fr: DOCTOR_NOTIFY[`NEW-BOOKING-fr`]
                }
                const userTokenDetails = await Fcm.find({ user_id: data.hospital_id ? employerDetails._id : data.hospital_doctor_id, });
                userTokenDetails.length && userTokenDetails.forEach(async (token) => {
                    await sendPushNotification(token?.device_token, 'Doctome', schema?.notify_en, { booking_id: String(data._id), d_screen_url: String(`${action.status}`) });
                });
                await addNotification(schema, req, res)

                // patient
                let patientSchema = {
                    user_id: data.guardian_id ? data.guardian_id : data.patient_id,
                    notify_en: PATIENT_NOTIFY[`NEW-BOOKING-en`],
                    notify_ar: PATIENT_NOTIFY[`NEW-BOOKING-ar`],
                    notify_fr: PATIENT_NOTIFY[`NEW-BOOKING-fr`]
                }
                const patientTokenDetails = await Fcm.find({ user_id: data.guardian_id ? data.guardian_id : data.patient_id });
                patientTokenDetails.length && patientTokenDetails.forEach(async (token) => {
                    await sendPushNotification(token?.device_token, 'Doctome', patientSchema?.notify_en, { booking_id: String(data._id), d_screen_url: String(`${action.status}`) });
                });
                await addNotification(patientSchema, req, res);

                return apiResponse(res, false, [], SUCCESS_MSG[`APPOINTMENT-BOOKED-${lang}`], SUCCESS.OK, 0, [], req)
            })
            .catch(function (err) {
                console.error(err)
                return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
            });
    }


}

exports.getBookedAppointments = async (req, res) => {
    const lang = req.headers["accept-language"] || 'en';
    const { doctor_hospital_id, selected_date, speciality_id, role_name } = req.body;
    try {
        let __date = new Date(selected_date);
        let dateSlots = [];

        if (role_name == "doctor") {

            let conditionFind = {
                $or: [
                    { booking_date: { $gte: __date, $lt: new Date(__date.getTime() + 24 * 60 * 60 * 1000) }, hospital_doctor_id: new mongoose.Types.ObjectId(doctor_hospital_id), status: { $ne: 'REJECTED' } },

                    { reschedule_date: { $gte: __date, $lt: new Date(__date.getTime() + 24 * 60 * 60 * 1000) }, hospital_doctor_id: new mongoose.Types.ObjectId(doctor_hospital_id), status: { $ne: 'REJECTED' } }
                ]
            }
            dateSlots = await BookingAppointment.find(conditionFind);
        } else {
            //Hospital Case

            let conditionFind = {
                $or: [
                    { booking_date: { $gte: __date, $lt: new Date(__date.getTime() + 24 * 60 * 60 * 1000) }, hospital_doctor_id: new mongoose.Types.ObjectId(doctor_hospital_id), booking_speciality: new mongoose.Types.ObjectId(speciality_id), status: { $ne: 'REJECTED' } },

                    { reschedule_date: { $gte: __date, $lt: new Date(__date.getTime() + 24 * 60 * 60 * 1000) }, hospital_doctor_id: new mongoose.Types.ObjectId(doctor_hospital_id), booking_speciality: new mongoose.Types.ObjectId(speciality_id), status: { $ne: 'REJECTED' } }
                ]
            }

            dateSlots = await BookingAppointment.find(conditionFind);
        }


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

function generateBookingId() {
    const timestamp = Date.now().toString(36).toUpperCase();
    const bookingId = "DJ" + timestamp;
    return bookingId;
}

// appoinment listing
exports.appointmentListing = async (req, res) => {
    var title_lang = 'en';
    const lang = req.headers["accept-language"] || 'en';

    let startDate = new Date();
    let endDate = new Date(new Date().setDate(new Date().getDate() + 30));
    endDate.setUTCHours(23, 59, 59);


    try {
        const { patient_id, list_type } = req.body;

        let filteredQuery = {
            patient_id: new mongoose.Types.ObjectId(patient_id)
        }

        let filteredQueryWithRescheduled = {
            patient_id: new mongoose.Types.ObjectId(patient_id)
        }


        if (list_type == "All") {

            //Don't need to check status in all case
        } else if (list_type == "UPCOMING") {

            let start_date = new Date(new Date().setDate(new Date().getDate() + 1));;
            start_date.setUTCHours(0, 0, 0, 0);

            filteredQuery['$and'] = [
                { booking_date: { $gte: start_date, $lte: endDate } },
                { reschedule_date: null }
            ];
            console.log(start_date, endDate);
            filteredQuery['status'] = "APPROVED";

            filteredQueryWithRescheduled['reschedule_date'] = { $gte: start_date, $lte: endDate }
            filteredQueryWithRescheduled['status'] = "APPROVED";
        } else if (list_type == "TODAY") {

            const today = new Date(); // This gets the current date and time
            today.setUTCHours(0, 0, 0, 0); // Set time to the beginning of the day in UTC
            const tomorrow = new Date(today); // Clone the today date object
            tomorrow.setUTCDate(today.getUTCDate() + 1);

            filteredQuery['$and'] = [
                { booking_date: { $gte: today, $lte: endDate } },
                { reschedule_date: null }
            ];
            filteredQuery['status'] = "APPROVED";

            filteredQueryWithRescheduled['reschedule_date'] = { $gte: today, $lt: tomorrow }
            filteredQueryWithRescheduled['status'] = "APPROVED";
        } else if (list_type == "APPROVED") {
            filteredQuery['booking_date'] = { $gte: endDate }
            filteredQuery['status'] = "APPROVED";

            filteredQueryWithRescheduled['reschedule_date'] = { $gte: endDate }
            filteredQueryWithRescheduled['status'] = "APPROVED";
        } else {
            // PENDING | APPROVED | REJECTED | COMPLETED
            filteredQuery['status'] = list_type;
            filteredQueryWithRescheduled['status'] = list_type;
        }


        let matchCondition = {
            $or: [
                filteredQuery,
                filteredQueryWithRescheduled
            ]
        }



        let page, limit: number;
        page = req.query.page ? parseInt(req.query.page) - 1 : 0;
        limit = req.query.limit ? parseInt(req.query.limit) : 10;
        let skip = parseInt(page) * limit;

        const [data, count] = await Promise.all([
            BookingAppointment.aggregate([
                { $match: matchCondition },
                { $sort: { createdAt: -1 } },
                { $skip: skip },
                { $limit: limit },
                {
                    $lookup: {
                        from: "categories",
                        as: "booking_speciality",
                        let: { booking_speciality: "$booking_speciality" },
                        pipeline: [
                            {
                                $match: {
                                    $expr: { $eq: ["$$booking_speciality", "$_id"] },
                                }
                            },
                            {
                                $project: {
                                    _id: 1,
                                    title_en: 1,
                                    title_ar: 1,
                                    title_fr: 1,
                                    image: 1
                                }
                            }
                        ],
                    },

                },
                {
                    $unwind: {
                        path: '$booking_speciality',
                        preserveNullAndEmptyArrays: true,
                    },
                },
                {
                    $lookup: {
                        from: "users",
                        as: "doctor_hospital",
                        let: { hospital_doctor_id: "$hospital_doctor_id" },
                        pipeline: [
                            {
                                $match: {

                                    $expr: { $eq: ["$$hospital_doctor_id", "$_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" },
                            {
                                $lookup: {
                                    from: "categories",
                                    as: "selected_speciality",
                                    let: { primary_specialty: "$primary_specialty" },
                                    pipeline: [
                                        {
                                            $match: {
                                                //$expr: { $in: ["$_id", "$$primary_specialty"] }
                                                "$expr": {
                                                    "$cond": {
                                                        "if": { "$isArray": "$$primary_specialty" },
                                                        "then": { "$in": ["$_id", "$$primary_specialty"] },
                                                        "else": { "$eq": ["$primary_specialty", "$_id"] }
                                                    }
                                                }
                                            }
                                        },
                                        {
                                            $project: {
                                                _id: 1,
                                                title_ar: 1,
                                                title_en: 1,
                                                title_fr: 1,
                                                image: 1
                                            }
                                        }
                                    ],
                                },

                            },
                            {
                                $lookup: {
                                    from: "languages",
                                    as: "selected_language",
                                    let: { spoken_language: "$spoken_language" },
                                    pipeline: [
                                        {
                                            $match: {
                                                "$expr": {
                                                    "$cond": {
                                                        "if": { "$isArray": "$$spoken_language" },
                                                        "then": { "$in": ["$_id", "$$spoken_language"] },
                                                        "else": { "$eq": ["$spoken_language", "$_id"] }
                                                    }
                                                }
                                            }
                                        },
                                        {
                                            $project: {
                                                _id: 1,
                                                title: 1
                                            }
                                        }
                                    ],
                                },

                            },
                            {
                                $lookup: {
                                    from: "users",
                                    foreignField: "_id",
                                    localField: "hospital_id",
                                    as: "EmployerDetails",
                                },
                            },
                            { "$unwind": { path: "$EmployerDetails", preserveNullAndEmptyArrays: true } },

                            {
                                $project: {
                                    _id: 1,
                                    first_name: 1,
                                    last_name: 1,
                                    email: 1,

                                    qualification: 1,
                                    additional_qualification: 1,
                                    year_of_practice: 1, country: 1,
                                    state: 1,
                                    street_address: 1,
                                    zip_code: 1, branch_of_medicines: 1,
                                    selected_speciality: "$selected_speciality",
                                    selected_language: "$selected_language",
                                    user_role: "$userRole.title",
                                    clinic_name: 1,
                                    clinic_open_time: 1,
                                    clinic_close_time: 1,
                                    buffer_time: 1,
                                    is_fulltime: 1,
                                    profile_pic: 1,
                                    clinic_timing: 1,
                                    location: 1,
                                    street_address2: 1,
                                    platform_booking_status: 1,
                                    hospital_name: 1,
                                    EmployerDetails: 1
                                }
                            }
                        ]
                    }
                },

                {
                    $unwind: {
                        path: '$doctor_hospital',
                        preserveNullAndEmptyArrays: true,
                    },
                },


                { $project: { _id: 1, booking_id: 1, slot: 1, booking_date: 1, status: 1, createdAt: 1, rejected_reason: 1, doctor_hospital: "$doctor_hospital", document_file_from_doctor: 1, rejected_by: 1, booking_speciality: "$booking_speciality", reschedule_date: 1, reschedule_slot: 1, reschedule_by: 1, document_file: 1, daily_room_name: 1, daily_room_url: 1, daily_room_token: 1, daily_room_created_at: 1 } },



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



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


// patient appoinment action
exports.patientActionOnAppointment = async (req, res) => {
    var title_lang = 'en';
    const lang = req.headers["accept-language"] || 'en'

    try {
        const { booking_id, status, rejected_reason, rejected_by, language, reschedule_slot, reschedule_date } = req.body;
        let filteredQuery = {
            _id: new mongoose.Types.ObjectId(booking_id),
        }
        let action = await BookingAppointment.findOneAndUpdate(filteredQuery, { status: status, rejected_reason: rejected_reason, rejected_by: rejected_by, reschedule_date: reschedule_date, reschedule_slot: reschedule_slot }, { new: true })


        //save data in booking history

        let saveHistoryDataCondition = {
            booking_id: action._id,
            patient_id: action.patient_id,
            hospital_doctor_id: action.hospital_doctor_id,
            action_by: 'patient',
            status: status
        }

        let bookingModal = new BookingHistory(saveHistoryDataCondition);

        await bookingModal.save();

        //end of save data in booking history


        let patient = await User.findOne({ _id: new mongoose.Types.ObjectId(action.patient_id) }, { _id: 1, first_name: 1, last_name: 1, email: 1, dob: 1 })
        let doctor = await User.findOne({ _id: new mongoose.Types.ObjectId(action.hospital_doctor_id) }, { _id: 1, first_name: 1, last_name: 1, email: 1, dob: 1, hospital_name: 1, clinic_name: 1 }).populate("user_role");

        let doctorClinicName = doctor.hospital_name?.trim() ? doctor.hospital_name : doctor.clinic_name
        let patientFullName = `${patient.first_name}`.charAt(0).toUpperCase() + `${patient.first_name}`.slice(1) + " " + `${patient.last_name}`.charAt(0).toUpperCase() + `${patient.last_name}`.slice(1);
        let doctorFullName = `${doctor.first_name}`.charAt(0).toUpperCase() + `${doctor.first_name}`.slice(1) + " " + `${doctor.last_name}`.charAt(0).toUpperCase() + `${doctor.last_name}`.slice(1);
        if (doctor.user_role.title == 'hospital') {
            doctorFullName = `${doctor.hospital_name}`.charAt(0).toUpperCase() + `${doctor.hospital_name}`.slice(1)
        }
        // let appointmentType = await Role.findOne({ _id: new mongoose.Types.ObjectId(action.booking_role_type) }, { title: 1 })

        let fetchHospitalDoctorID = await BookingAppointment.findOne(filteredQuery, { hospital_doctor_id: 1 });
        let condition = {}
        condition['_id'] = new mongoose.Types.ObjectId(fetchHospitalDoctorID.hospital_doctor_id);

        let record = await User.findOne(condition, { _id: 1, selected_language: 1, phone_number: 1 });

        let appointmentDate;
        let appointmentSlot;
        if (action.reschedule_date != null) {

            const appointmentdateRe = new Date(action.reschedule_date);
            const formatappointmentdateRe = `${appointmentdateRe.getDate()}/${appointmentdateRe.getMonth() + 1}/${appointmentdateRe.getFullYear()}`;
            appointmentDate = formatappointmentdateRe;
            appointmentSlot = action.reschedule_slot;
        } else {

            const selecteddate = new Date(action.booking_date);
            const formattedselecteddate = `${selecteddate.getDate()}/${selecteddate.getMonth() + 1}/${selecteddate.getFullYear()}`;
            appointmentDate = formattedselecteddate;
            appointmentSlot = action.slot;
        }
        let templateData;
        if (record.selected_language === 'fr') {
            templateData = await patientAppoinmentRejectedTemplate_fr({ patientFullName, doctorFullName, action, doctorClinicName, user_role: doctor.user_role.title })
            await MobileOtp(record.phone_number.e164Number, `Cher Dr. ${doctorFullName},

Nous avons le regret de vous informer que votre rendez-vous avec ${patientFullName}, prévu pour le ${appointmentDate} à ${appointmentSlot}, a été annulé par le patient.

                                `)
        } else if (record.selected_language === 'ar') {
            templateData = await patientAppoinmentRejectedTemplate_ar({ patientFullName, doctorFullName, action, doctorClinicName, user_role: doctor.user_role.title })
            await MobileOtp(record.phone_number.e164Number, `عزيزي د. ${doctorFullName}،

نأسف لإبلاغك أنه قد تم إلغاء موعدك مع ${patientFullName}، والمحدد في ${appointmentDate} الساعة ${appointmentSlot} من قبل المريض.

                
                                                `)
        }
        else {
            templateData = await patientAppoinmentRejectedTemplate({ patientFullName, doctorFullName, action, doctorClinicName, user_role: doctor.user_role.title })
            await MobileOtp(record.phone_number.e164Number, `Dear Dr. ${doctorFullName},

We regret to inform you that your appointment with ${patientFullName} scheduled for ${appointmentDate} at ${appointmentSlot} has been cancelled by the patient.

                
                                                `)
        }

        const mailOptions = {
            to: doctor.email,
            subject: templateData.subject,
            html: templateData.html
        };
        let isEmailSent = await sendEmail(mailOptions, res)
        let sentStatus = 'PENDING'
        if (isEmailSent) {
            sentStatus = 'SUCCESS'
        }
        let cronPostParams = {
            "user_id": doctor._id,
            "email_to": doctor.email,
            "email_subject": templateData.subject,
            "email_content": templateData.html,
            "cron_email_type": "appoinment rejected by patient",
            "cron_email_status": sentStatus
        }
        let saveEmail = new CronEmail(cronPostParams)
        saveEmail.save()


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



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


// indivisual appointment listing

exports.patientAppointment = async (req, res) => {
    var title_lang = 'en';
    const lang = req.headers["accept-language"] || 'en'

    try {
        const { booking_id } = req.body;



        let filteredQuery = {
            _id: new mongoose.Types.ObjectId(booking_id),
        }

        const [data, count] = await Promise.all([
            BookingAppointment.aggregate([
                { $match: filteredQuery },
                {
                    $lookup: {
                        from: "categories",
                        as: "booking_speciality",
                        let: { booking_speciality: "$booking_speciality" },
                        pipeline: [
                            {
                                $match: {
                                    $expr: { $eq: ["$$booking_speciality", "$_id"] },
                                }
                            },
                            {
                                $project: {
                                    _id: 1,
                                    title_en: 1,
                                    title_ar: 1,
                                    title_fr: 1,
                                    image: 1
                                }
                            }
                        ],
                    },

                },
                {
                    $unwind: {
                        path: '$booking_speciality',
                        preserveNullAndEmptyArrays: true,
                    },
                },

                {
                    $lookup: {
                        from: "users",
                        as: "doctor_hospital",
                        let: { hospital_doctor_id: "$hospital_doctor_id" },
                        pipeline: [
                            {
                                $match: {

                                    $expr: { $eq: ["$$hospital_doctor_id", "$_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" },
                            {
                                $lookup: {
                                    from: "categories",
                                    as: "selected_speciality",
                                    let: { primary_specialty: "$primary_specialty" },
                                    pipeline: [
                                        {
                                            $match: {
                                                //$expr: { $in: ["$_id", "$$primary_specialty"] }
                                                "$expr": {
                                                    "$cond": {
                                                        "if": { "$isArray": "$$primary_specialty" },
                                                        "then": { "$in": ["$_id", "$$primary_specialty"] },
                                                        "else": { "$eq": ["$primary_specialty", "$_id"] }
                                                    }
                                                }
                                            }
                                        },
                                        {
                                            $project: {
                                                _id: 1,
                                                title_ar: 1,
                                                title_en: 1,
                                                title_fr: 1,
                                                image: 1
                                            }
                                        }
                                    ],
                                },

                            },
                            {
                                $lookup: {
                                    from: "languages",
                                    as: "selected_language",
                                    let: { spoken_language: "$spoken_language" },
                                    pipeline: [
                                        {
                                            $match: {
                                                "$expr": {
                                                    "$cond": {
                                                        "if": { "$isArray": "$$spoken_language" },
                                                        "then": { "$in": ["$_id", "$$spoken_language"] },
                                                        "else": { "$eq": ["$spoken_language", "$_id"] }
                                                    }
                                                }
                                            }
                                        },
                                        {
                                            $project: {
                                                _id: 1,
                                                title: 1
                                            }
                                        }
                                    ],
                                },

                            },

                            {
                                $project: {
                                    _id: 1,
                                    first_name: 1,
                                    last_name: 1,
                                    email: 1,
                                    qualification: 1,
                                    additional_qualification: 1,
                                    year_of_practice: 1, country: 1,
                                    state: 1,
                                    street_address: 1,
                                    street_address2: 1,
                                    zip_code: 1, branch_of_medicines: 1,
                                    selected_speciality: "$selected_speciality",
                                    selected_language: "$selected_language",
                                    user_role: "$userRole.title",
                                    clinic_name: 1,
                                    clinic_open_time: 1,
                                    clinic_close_time: 1,
                                    certificate: 1,
                                    clinic_timing: 1,
                                    profile_pic: 1,
                                    is_fulltime: 1,
                                    platform_booking_status: 1,
                                    hospital_name: 1

                                }
                            }
                        ]
                    }
                },

                {
                    $unwind: {
                        path: '$doctor_hospital',
                        preserveNullAndEmptyArrays: true,
                    },
                },

                { $project: { _id: 1, booking_id: 1, slot: 1, booking_date: 1, status: 1, createdAt: 1, rejected_reason: 1, doctor_hospital: "$doctor_hospital", document_file: 1, document_file_from_doctor: 1, booking_speciality: "$booking_speciality", reschedule_date: 1, reschedule_slot: 1, reschedule_by: 1 } },


                { $sort: { createdAt: -1 } },

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




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



exports.editPatientAppointment = async (req, res) => {
    let lang = req.headers["accept-language"] || 'en'
    try {
        const { id } = req.body
        let updateProfile = await BookingAppointment.findOneAndUpdate({ _id: id }, { $set: req.body }, { new: true })
        return apiResponse(res, false, [], SUCCESS_MSG[`USER-UPDATED-${lang}`], SUCCESS.OK, 0, [], req)
    } catch (error) {
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }
}



// notification
exports.notificationListing = async (req, res) => {
    const lang = req.headers["accept-language"] || 'en'
    try {
        const { user_id, is_read } = req.body
        var filteredQuery = {}
        let page, limit: number;



        page = req.query.page ? parseInt(req.query.page) - 1 : 0;
        limit = req.query.limit ? parseInt(req.query.limit) : 10;
        filteredQuery = {
            is_deleted: false,
            user_id: new mongoose.Types.ObjectId(user_id),
            is_read: (is_read == false || is_read == true) ? is_read : { $in: [true, false] }
        }

        const unreadDocs = {
            is_deleted: false,
            user_id: new mongoose.Types.ObjectId(user_id),
            is_read: false
        }
        const [data, totalCount, unreadCount] = await Promise.all([
            Notification.find(filteredQuery, { _id: 1, is_read: 1, notify_ar: 1, notify_en: 1, notify_fr: 1, createdAt: 1 }).sort({ createdAt: -1 }).skip(page * limit).limit(limit),
            Notification.countDocuments(filteredQuery),
            Notification.countDocuments(unreadDocs)
        ]);
        const count = {
            total: totalCount,
            unread: unreadCount
        };
        return apiResponse(res, false, [], '', SUCCESS.OK, count, data, req, unreadCount)
    } catch (error) {
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }
}
// delete notification
exports.deleteNotification = async (req, res) => {
    let lang = req.headers["accept-language"] || 'en'
    try {
        const { notify_id } = req.body
        let updateProfile = await Notification.deleteOne({ _id: new mongoose.Types.ObjectId(notify_id) })
        return apiResponse(res, false, [], '', SUCCESS.OK, 1, [], req)
    } catch (error) {
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }
}
//
exports.readNotification = async (req, res) => {
    let lang = req.headers["accept-language"] || 'en'
    try {
        const { notify_id } = req.body
        let updateProfile = await Notification.findOneAndUpdate({ _id: new mongoose.Types.ObjectId(notify_id) }, { is_read: true }, { new: true })
        return apiResponse(res, false, [], '', SUCCESS.OK, 1, [], req)
    } catch (error) {
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }
}


//rechudleAppoinment
exports.patientRescheduleAppointment = async (req, res) => {
    const lang = req.headers["accept-language"] || 'en'

    // If no validation errors, get the req.body objects that were validated and are needed
    const { id, hospital_doctor_id, status, reschedule_date, reschedule_slot, reschedule_by, booking_speciality, role_name, language, patient_id } = req.body;


    let updateCondition = {
        reschedule_date: reschedule_date,
        reschedule_slot: reschedule_slot,
        status: status,
        reschedule_by: reschedule_by,
        booking_speciality: booking_speciality
    };

    let __date = new Date(reschedule_date);
    let findExistsRecord = null;

    try {

        let checkFullTimePartTime = await User.findOne({ _id: new mongoose.Types.ObjectId(hospital_doctor_id) });

        if (checkFullTimePartTime && checkFullTimePartTime.is_fulltime) {
            if (role_name == "doctor") {
                findExistsRecord = await BookingAppointment.findOne({
                    $or: [
                        {
                            booking_date: { $gte: __date, $lt: new Date(__date.getTime() + 24 * 60 * 60 * 1000) },
                            hospital_doctor_id: new mongoose.Types.ObjectId(hospital_doctor_id),
                            slot: reschedule_slot,
                            reschedule_slot: null,
                            status: { $ne: 'REJECTED' }
                        },
                        {
                            reschedule_date: { $gte: __date, $lt: new Date(__date.getTime() + 24 * 60 * 60 * 1000) },
                            hospital_doctor_id: new mongoose.Types.ObjectId(hospital_doctor_id),
                            reschedule_slot: reschedule_slot,
                            status: { $ne: 'REJECTED' }
                        }
                    ]
                });
            } else {
                //Hospital Case
                findExistsRecord = await BookingAppointment.findOne({
                    $or: [
                        {
                            booking_date: { $gte: __date, $lt: new Date(__date.getTime() + 24 * 60 * 60 * 1000) },
                            hospital_doctor_id: new mongoose.Types.ObjectId(hospital_doctor_id),
                            booking_speciality: new mongoose.Types.ObjectId(booking_speciality),
                            slot: reschedule_slot,
                            reschedule_slot: null,
                            status: { $ne: 'REJECTED' }
                        },
                        {
                            reschedule_date: { $gte: __date, $lt: new Date(__date.getTime() + 24 * 60 * 60 * 1000) },
                            hospital_doctor_id: new mongoose.Types.ObjectId(hospital_doctor_id),
                            booking_speciality: new mongoose.Types.ObjectId(booking_speciality),
                            reschedule_slot: reschedule_slot,
                            status: { $ne: 'REJECTED' }
                        }
                    ]
                });
            }
        }




    } catch (err) {
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }
    let isBlockedByDoctor = await BlockUser.findOne({ patient_id: new mongoose.Types.ObjectId(patient_id), hospital_doctor_id: new mongoose.Types.ObjectId(hospital_doctor_id), is_blocked_user: true });

    if (isBlockedByDoctor) {
        return apiResponse(res, true, [], ERROR_MSG[`BLOCKED-BY-DOCTOR-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);
    }

    if (findExistsRecord) {
        return apiResponse(res, true, [], ERROR_MSG[`ALREADY-SLOTS-BOOKED-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);
    }







    try {
        const details = await User.findById(hospital_doctor_id);
        if (details.is_auto_req_accept) {
            updateCondition['status'] = 'APPROVED';
        }
        let action = await BookingAppointment.findOneAndUpdate({ _id: new mongoose.Types.ObjectId(id) }, { $set: updateCondition }, { new: true })
        let patient = await User.findOne({ _id: new mongoose.Types.ObjectId(action.patient_id) }, { _id: 1, first_name: 1, last_name: 1, email: 1, dob: 1 })
        let doctor = await User.findOne({ _id: new mongoose.Types.ObjectId(action.hospital_doctor_id) }, { _id: 1, first_name: 1, last_name: 1, email: 1, dob: 1, hospital_name: 1, clinic_name: 1 }).populate('user_role')



        let patientFullName = `${patient.first_name}`.charAt(0).toUpperCase() + `${patient.first_name}`.slice(1) + " " + `${patient.last_name}`.charAt(0).toUpperCase() + `${patient.last_name}`.slice(1);
        let doctorFullName = `${doctor.first_name}`.charAt(0).toUpperCase() + `${doctor.first_name}`.slice(1) + " " + `${doctor.last_name}`.charAt(0).toUpperCase() + `${doctor.last_name}`.slice(1);
        if (doctor.user_role.title == 'hospital') {
            doctorFullName = `${doctor.hospital_name}`.charAt(0).toUpperCase() + `${doctor.hospital_name}`.slice(1)
        }
        let user_role = doctor.user_role.title;
        let doctorClinicName = doctor.hospital_name?.trim() ? doctor.hospital_name : doctor.clinic_name
        let condition = {}
        condition['_id'] = new mongoose.Types.ObjectId(hospital_doctor_id);
        let record = await User.findOne(condition, { _id: 1, selected_language: 1, phone_number: 1 });
        const bookingdate = new Date(action.booking_date);

        const formattedBookingDate = `${bookingdate.getDate()}/${bookingdate.getMonth() + 1}/${bookingdate.getFullYear()}`;
        // rechedule fromatte date set 
        const dateStringRe = action.reschedule_date;
        const dateRe = new Date(dateStringRe);

        const rescheduleformattedDate = `${String(dateRe.getDate()).padStart(2, '0')}/${String(dateRe.getMonth() + 1).padStart(2, '0')}/${String(dateRe.getFullYear()).padStart(2, '0')}`;
        let templateData;
        if (details.is_auto_req_accept) {
            if (record.selected_language === 'fr') {
                templateData = await patientRescheduleAppointmentTemplate_fr({ patientFullName, doctorFullName, action, doctorClinicName, user_role })
                await MobileOtp(record.phone_number.e164Number, `Cher Dr. ${doctorFullName},
                    Un patient, ${patientFullName}, a reprogrammé son rendez-vous avec vous.
                    Rendez-vous initial:
                    Date : ${formattedBookingDate}
                    Heure : ${action.slot}
                    Rendez-vous reprogrammé préféré:
                    Date : ${rescheduleformattedDate}
                    Heure : ${action.reschedule_slot}
                    Type : ${doctorClinicName}
                    `)
            } else if (record.selected_language === 'ar') {
                templateData = await patientRescheduleAppointmentTemplate_ar({ patientFullName, doctorFullName, action, doctorClinicName, user_role })
                await MobileOtp(record.phone_number.e164Number, `عزيزي د. ${doctorFullName}،
                    لقد قام المريض ${patientFullName} بإعادة جدولة موعده معك.
                    الموعد الأصلي:
                    التاريخ: ${formattedBookingDate}
                    الوقت: ${action.slot}
                    الموعد الجديد المفضل:
                    التاريخ: ${rescheduleformattedDate}
                    الوقت: ${action.reschedule_slot}
                    النوع: ${doctorClinicName}
                                    `)
            }
            else {
                templateData = await patientRescheduleAppointmentTemplate({ patientFullName, doctorFullName, action, doctorClinicName, user_role })
                await MobileOtp(record.phone_number.e164Number, `Dear Dr. ${doctorFullName},
                    A patient, ${patientFullName}, has rescheduled their appointment with you.
                    Original Appointment:
                                    
                    Date: ${formattedBookingDate}
                    Time: ${action.slot}
                    Preferred Rescheduled Appointment:
                                    
                    Date: ${rescheduleformattedDate}
                    Time: ${action.reschedule_slot}
                    Type: ${doctorClinicName}
                                    `)
            }

        }
        else {
            if (record.selected_language === 'fr') {
                templateData = await patientRescheduleAppointmentTemplate_fr({ patientFullName, doctorFullName, action, doctorClinicName, user_role })
                await MobileOtp(record.phone_number.e164Number, `Cher Dr. ${doctorFullName},
                    Un patient, ${patientFullName}, a demandé à reprogrammer son rendez-vous avec vous.
                    Rendez-vous initial:
                    Date : ${formattedBookingDate}
                    Heure : ${action.slot}
                    Rendez-vous reprogrammé préféré:
                    Date : ${rescheduleformattedDate}
                    Heure : ${action.reschedule_slot}
                    Type : ${doctorClinicName}
                    `)
            } else if (record.selected_language === 'ar') {
                templateData = await patientRescheduleAppointmentTemplate_ar({ patientFullName, doctorFullName, action, doctorClinicName, user_role })
                await MobileOtp(record.phone_number.e164Number, `عزيزي د. ${doctorFullName}،
                    طلب المريض ${patientFullName} إعادة جدولة موعده معك.
                    الموعد الأصلي:
                    التاريخ: ${formattedBookingDate}
                    الوقت: ${action.slot}
                    الموعد الجديد المفضل:
                    التاريخ: ${rescheduleformattedDate}
                    الوقت: ${action.reschedule_slot}
                    النوع: ${doctorClinicName}
                                    `)
            }
            else {
                templateData = await patientRescheduleAppointmentTemplate({ patientFullName, doctorFullName, action, doctorClinicName, user_role })
                await MobileOtp(record.phone_number.e164Number, `Dear Dr. ${doctorFullName},
                    A patient, ${patientFullName}, has requested to reschedule their appointment with you.
                    Original Appointment:
                                    
                    Date: ${formattedBookingDate}
                    Time: ${action.slot}
                    Preferred Rescheduled Appointment:
                                    
                    Date: ${rescheduleformattedDate}
                    Time: ${action.reschedule_slot}
                    Type: ${doctorClinicName}
                                    `)
            }

        }


        const mailOptions = {
            to: doctor.email,
            subject: templateData.subject,
            html: templateData.html
        };
        let isEmailSent = await sendEmail(mailOptions, res)
        let sentStatus = 'PENDING'
        if (isEmailSent) {
            sentStatus = 'SUCCESS'
        }
        let cronPostParams = {
            "user_id": doctor._id,
            "email_to": doctor.email,
            "email_subject": templateData.subject,
            "email_content": templateData.html,
            "cron_email_type": "patient re-schedule appointment",
            "cron_email_status": sentStatus
        }
        let saveEmail = new CronEmail(cronPostParams)
        saveEmail.save()
        if (details.is_auto_req_accept) {
            let schema = {
                user_id: action.hospital_doctor_id,
                notify_en: DOCTOR_NOTIFY[`RE-SCHEDULE-AUTO-en`],
                notify_ar: DOCTOR_NOTIFY[`RE-SCHEDULE-AUTO-ar`],
                notify_fr: DOCTOR_NOTIFY[`RE-SCHEDULE-AUTO-fr`]
            }
            const userTokenDetails = await Fcm.find({ user_id: action.hospital_doctor_id });
            userTokenDetails.length && userTokenDetails.forEach(async (token) => {
                await sendPushNotification(token?.device_token, 'Doctome', schema?.[`notify_${lang}`], { booking_id: String(action._id), d_screen_url: String(`${action.status}`) });
            });

            await addNotification(schema, req, res);
        }
        else {

            let schema = {
                user_id: action.hospital_doctor_id,
                notify_en: DOCTOR_NOTIFY[`RE-SCHEDULE-REQ-en`],
                notify_ar: DOCTOR_NOTIFY[`RE-SCHEDULE-REQ-ar`],
                notify_fr: DOCTOR_NOTIFY[`RE-SCHEDULE-REQ-fr`]
            }
            const userTokenDetails = await Fcm.find({ user_id: action.hospital_doctor_id });
            userTokenDetails.length && userTokenDetails.forEach(async (token) => {
                await sendPushNotification(token?.device_token, 'Doctome', schema?.[`notify_${lang}`], { booking_id: String(action._id), d_screen_url: String(`${action.status}`) });
            });
            await addNotification(schema, req, res);
        }


        //save data in booking history

        let saveHistoryDataCondition = {
            booking_id: action._id,
            patient_id: action.patient_id,
            hospital_doctor_id: action.hospital_doctor_id,
            action_by: "patient",
            status: "RESCHEDULED"
        }

        let bookingModal = new BookingHistory(saveHistoryDataCondition);

        await bookingModal.save();

        //end of save data in booking history

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


exports.createPatientUser = async (req, res) => {
    try {
        let lang = req.headers["accept-language"] || 'en'
        // If no validation errors, get the req.body objects that were validated and are needed
        const { user_role, phone_number } = req.body;
        if (user_role != 'patient') {
            console.log(user_role)
            return apiResponse(res, true, [], ERROR_MSG[`SERVER-ERROR`], SERVER_ERROR.internalServerError, 0, [], req);
        }
        let role = await Role.findOne(
            { title: user_role },
            { _id: 1 }
        );
        //save user 
        req.body['is_signup_otp_varify'] = true;
        req.body['guardian_id'] = req['user']['_id'];
        var newUser = new User(_.pick(req.body, ['title', 'first_name', 'middle_name', 'last_name', 'dob', 'relationship','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', 'is_signup_otp_varify', 'guardian_id']));

        if (user_role) {
            newUser['user_role'] = role['_id']
        }
        // || user_role == 'doctor' || user_role == 'hospital'
        if (user_role == "patient") {
            newUser['user_account_status'] = 'APPROVED'
        }

        newUser['is_signup'] = true
        await newUser.save()
            .then(async function (user) {
                return apiResponse(res, false, [], SUCCESS_MSG[`User-created-${lang}`], SUCCESS.OK, 0, [], req);
            })

    }
    catch (error) {
        console.error(error);
        return apiResponse(res, true, [], ERROR_MSG[`SERVER-ERROR`], SERVER_ERROR.internalServerError, 0, [], req);
    }
}

exports.getListOfFamilyMembers = async (req, res) => {
    try {

        const { limit = 10, page = 1, id } = req.body;
        const fetchUserRole = await Role.findOne({ title: 'patient' });
        let filteredQuery = { user_role: new mongoose.Types.ObjectId(fetchUserRole._id) };

        if (id) {
            filteredQuery['guardian_id'] = new mongoose.Types.ObjectId(id);
        }
        else {
            filteredQuery['guardian_id'] = new mongoose.Types.ObjectId(req['user']['_id']);
        }
        let skip = (parseInt(page) - 1) * parseInt(limit);
        const [data, count] = await Promise.all([
            User.aggregate([
                {
                    $match: filteredQuery

                },
                { $sort: { createdAt: -1 } },
                { $skip: skip },
                { $limit: parseInt(limit) },
                {
                    $lookup:
                    {
                        from: 'users',
                        localField: 'guardian_id',
                        foreignField: '_id',
                        as: 'guardian_details'
                    }
                },
                {
                    $unwind: { path: "$guardian_details", preserveNullAndEmptyArrays: true }
                },
                {
                    $project:
                    {
                        first_name: 1,
                        last_name: 1,
                        gender: 1,
                        profile_pic: 1,
                        social_security_number: 1,
                        guardian_id: 1,
                        dob: 1,
                        is_account_active: 1,
                        createdAt: 1,
                        updatedAt: 1,
                        clinic_municipality: 1,
                        clinic_department: 1,
                        guardian_details:
                        {
                            first_name: 1,
                            last_name: 1,
                            email: 1,
                            phone_number: 1,
                            gender: 1,
                            profile_pic: 1
                        }
                    }
                }
            ]),
            User.countDocuments(filteredQuery)
        ]);
        return apiResponse(res, false, [], '', SUCCESS.OK, count, data, req);
    }
    catch (error) {
        console.error(error);
        return apiResponse(res, true, [], ERROR_MSG[`SERVER-ERROR`], SERVER_ERROR.internalServerError, 0, [], req);
    }
}

exports.getDetailsOfChild = async (req, res) => {
    try {
        const { id } = req.params;
        const fetchUserRole = await Role.findOne({ title: 'patient' });
        let filteredQuery = { user_role: new mongoose.Types.ObjectId(fetchUserRole._id), _id: new mongoose.Types.ObjectId(id) };
        const [data, count] = await Promise.all([
            User.aggregate([
                {
                    $match: filteredQuery

                },
                {
                    $lookup:
                    {
                        from: 'users',
                        localField: 'guardian_id',
                        foreignField: '_id',
                        as: 'guardian_details'
                    }
                },
                {
                    $unwind: { path: "$guardian_details", preserveNullAndEmptyArrays: true }
                },
                {
                    $project:
                    {
                        first_name: 1,
                        last_name: 1,
                        social_security_number: 1,
                        dob: 1,
                        gender: 1,
                        profile_pic: 1,
                        clinic_municipality: 1,
                        clinic_department: 1,
                        relationship: 1,
                        guardian_id: 1,
                        guardian_details:
                        {
                            first_name: 1,
                            last_name: 1,
                            email: 1,
                            phone_number: 1,
                            gender: 1,
                            profile_pic: 1
                        },
                        is_account_active: 1
                    }
                }
            ]),
            User.countDocuments(filteredQuery)
        ]);
        return apiResponse(res, false, [], '', SUCCESS.OK, count, data, req);
    }
    catch (error) {
        console.error(error);
        return apiResponse(res, true, [], ERROR_MSG[`SERVER-ERROR`], SERVER_ERROR.internalServerError, 0, [], req);
    }
}

exports.updateChildrenProfile = async (req, res) => {
    console.log(req.body);
    try {
        const { relationship, first_name, last_name, dob, is_account_active, social_security_number, childId } = req.body;
        await User.findByIdAndUpdate(
            { _id: childId },
            { relationship, first_name, last_name, dob, is_account_active, social_security_number },
            { new: true }
        );
        return apiResponse(res, false, [], '', SUCCESS.OK, 0, [], req);
    }
    catch (error) {
        console.error(error);
        return apiResponse(res, true, [], ERROR_MSG[`SERVER-ERROR`], SERVER_ERROR.internalServerError, 0, [], req);
    }
}