import { Console } from "console";
import { 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 { sendEmail } = require('../../core/utilities/emailService');
const { BookingAppointment } = require('../../models/booking')
const { BlockUser } = require('../../models/block-users');
const { DoctorAvaliblitySlot } = require("../../models/doctor-avaliblity-slots")
const { apiResponse } = require("../../core/response/response")
const { CronEmail } = require('../../models/email')
const { Notification } = require('../../models/notification')
const { Fcm } = require("../../models/fcm-tokens")
const { sendPushNotification } = require("../../core/utilities/pushNotification");
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 { MobileOtp } = require("../../core/utilities/mobileOtp");
const { Category } = require('../../models/admin/category');

const { newAppointmentEmailTemplate, newAppointmentEmailTemplate_fr, newAppointmentEmailTemplate_ar, doctorAppoinmentAcceptedTemplate, doctorAppoinmentRejectedTemplate_fr, doctorAppoinmentRejectedTemplate_ar, doctorRescheduledAppoinmentRejectedTemplate_ar, doctorRescheduledAppoinmentRejectedTemplate_fr, doctorAppoinmentAcceptedTemplate_fr, doctorRescheduledAppoinmentAcceptedTemplate_fr, doctorRescheduledAppoinmentAcceptedTemplate_ar, doctorAppoinmentAcceptedTemplate_ar, doctorAppoinmentRejectedTemplate, doctorRescheduleAppointmentTemplate, doctorRescheduleAppointmentTemplate_ar, doctorRescheduleAppointmentTemplate_fr, doctorRescheduledAppoinmentAcceptedTemplate, doctorRescheduledAppoinmentRejectedTemplate, RegisteredByAdmin } = require('../../core/email-templates/email-web')

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

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

        const details = await User.findById(doctor_id ? doctor_id : 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: doctor_id ? doctor_id : req['user']._id
        }, { $set: req.body }, { new: true })
        return apiResponse(res, false, [], SUCCESS_MSG[`USER-UPDATED-${lang}`], SUCCESS.OK, 0, { _id: doctor_id }, req)

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

exports.editHospitalProfile = async (req, res) => {
    let lang = req.headers["accept-language"] || 'en'
    try {
        const { hospital_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 != 'hospital') {
            return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
        }
        await User.findOneAndUpdate({ _id: req['user']._id }, { $set: req.body }, { new: true });
        return apiResponse(res, false, [], SUCCESS_MSG[`USER-UPDATED-${lang}`], SUCCESS.OK, 0, { _id: hospital_id }, req)

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


exports.addUpdateAvaliblity = 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 { user_id, unavaliable_slots, selected_date, is_day_off } = req.body
    let dateSlots = await DoctorAvaliblitySlot.findOne({ 'selected_date': selected_date, user_id: new mongoose.Types.ObjectId(user_id) });

    if (dateSlots) {
        await DoctorAvaliblitySlot.findOneAndUpdate({ '_id': dateSlots._id }, { $set: { unavaliable_slots, is_day_off } }, { new: true })
        return apiResponse(res, false, [], SUCCESS_MSG[`AVALIBLITY-UPDATED-${lang}`], SUCCESS.OK, 0, [], req)
    } else {
        new DoctorAvaliblitySlot(_.pick(req.body, ['user_id', 'unavaliable_slots', 'selected_date', 'is_day_off'])).save()
            .then(async function (data) {
                return apiResponse(res, false, [], SUCCESS_MSG[`AVALIBLITY-UPDATED-${lang}`], SUCCESS.OK, 0, [], req)
            })
            .catch(function (err) {
                return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
            });
    }

}

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

        const doctorDetails = await User.findById(user_id);

        if (doctorDetails.is_fulltime) {
            let dateSlots = await DoctorAvaliblitySlot.findOne({ selected_date: selected_date, user_id: user_id }, { unavaliable_slots: 1, is_day_off: 1, selected_date: 1, user_id: 1 });
            return apiResponse(res, false, [], '', SUCCESS.OK, 0, dateSlots, req)
        }

        let dateSlots = await DoctorAvaliblitySlot.findOne({ selected_date: selected_date, user_id: user_id }, { unavaliable_slots: 1, is_day_off: 1, selected_date: 1, user_id: 1 });

        let find_slots = [];
        doctorDetails.clinic_timing.length && doctorDetails.clinic_timing.forEach((res: any) => {
            find_slots.push(`${formatTimeForSlot(res.start_time)} - ${formatTimeForSlot(res.end_time)}`);
        });

        let rangeStartDate = new Date(selected_date);
        rangeStartDate.setUTCHours(0, 0, 0);

        let rangeEndDate = new Date(selected_date);
        rangeEndDate.setHours(23, 59, 59);


        let conditionFind = {
            hospital_doctor_id: user_id,
            slot: { $in: find_slots },
            $or: [
                {
                    $and: [
                        {
                            booking_date: { $gte: rangeStartDate, $lte: rangeEndDate },
                            reschedule_date: null
                        }
                    ]
                },
                {
                    reschedule_date: { $gte: rangeStartDate, $lte: rangeEndDate }
                }
            ],
            status: "APPROVED"
        }


        const result = await BookingAppointment.find(conditionFind);

        let arr = [];

        doctorDetails.clinic_timing.length && doctorDetails.clinic_timing.forEach((res: any) => {
            let totalCount = 0;

            result.length && result.forEach((elem: any) => {
                if (elem.slot == `${formatTimeForSlot(res.start_time)} - ${formatTimeForSlot(res.end_time)}`) {
                    totalCount++;
                }

                if (elem.reschedule_slot == `${formatTimeForSlot(res.start_time)} - ${formatTimeForSlot(res.end_time)}`) {
                    totalCount++;
                }
            })

            if (totalCount >= res.limit) {
                arr.push(`${formatTimeForSlot(res.start_time)} - ${formatTimeForSlot(res.end_time)}`);
            }

        });

        if (arr.length && dateSlots) {
            arr.forEach((slot: any) => {
                if (!dateSlots.unavaliable_slots.includes(slot)) {
                    dateSlots.unavaliable_slots.push(slot);
                }
            })
        }
        else if (arr.length) {
            let obj = { unavaliable_slots: [], is_day_off: true, selected_date: selected_date, user_id: user_id };
            arr.forEach((slot: any) => {
                obj.unavaliable_slots.push(slot);
            })
            return apiResponse(res, false, [], '', SUCCESS.OK, 0, obj, req)
        }

        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 formatTimeForSlot(time : any )
// {
//     const time24 = time; // e.g., "13 : 00"
//     const [hourStr, minute] = time24.split(':');
//     let hour = parseInt(hourStr.trim());
//     const period = hour >= 12 ? 'PM' : 'AM';
//     const formattedHour = ((hour % 12) || 12).toString().padStart(2, '0');
//     const formattedTime = `${formattedHour}:${minute.trim()} ${period}`;
//     return formattedTime;
// }

function formatTimeForSlot(time: any) {
    const time24 = time; // e.g., "13 : 00"
    const [hourStr, minute] = time24.split(':');
    let hour = parseInt(hourStr.trim());
    // const period = hour >= 12 ? 'PM' : 'AM';
    const formattedHour = hour.toString().padStart(2, '0');
    const formattedTime = `${formattedHour}:${minute.trim()}`;
    return formattedTime;
}

exports.doctorHospitalListing = async (req, res) => {
    var title_lang = 'en';


    try {
        const { category_id, selected_gender, language_multiple_ids, list_type, selected_date, selected_slot_time, patient_id, latitude, longitude, search, hospital_id, experience } = req.body;

        let time_slot = null;
        if (selected_slot_time) {
            const [time, modifier] = selected_slot_time.split(' ');
            let [hours, minutes] = time.split(':').map(Number);

            if (modifier === 'PM' && hours < 12) hours += 12;
            if (modifier === 'AM' && hours === 12) hours = 0;

            time_slot = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
        }

        let findBlockDoctors = await BlockUser.find({ patient_id: patient_id, is_blocked_user: true });

        let notInDoctorHospitalIds = [];
        findBlockDoctors.map(async (k) => {
            await notInDoctorHospitalIds.push(k.hospital_doctor_id);
        })

        let conditionFetchRole: any = { is_account_active: true }
        if (list_type == "All") {
            conditionFetchRole = {
                $or: [
                    {
                        title: "doctor"
                    },
                    {
                        title: "hospital"
                    }
                ]
            }
        }
        else if (list_type == "All" && hospital_id) {
            conditionFetchRole = {
                $or: [
                    {
                        title: "doctor"
                    }
                ],
                _id: new mongoose.Types.ObjectId(hospital_id)
            }
        }
        else {
            conditionFetchRole = {
                title: list_type
            }
        }
        const fetchUserRole = await Role.find(conditionFetchRole);
        if (fetchUserRole && fetchUserRole.length > 0) {
            var filteredQuery = { is_deleted: false }
            let page, limit: number;
            page = req.query.page ? parseInt(req.query.page) - 1 : 0;
            limit = req.query.limit ? parseInt(req.query.limit) : 10;
            if (category_id && category_id != "All") {
                filteredQuery['primary_specialty'] = {
                    $in: [new mongoose.Types.ObjectId(category_id)]
                }
            }

            let ids_user_role = [];
            fetchUserRole.map(async (p) => {
                await ids_user_role.push(new mongoose.Types.ObjectId(p._id));
            })


            filteredQuery['user_role'] = {
                $in: ids_user_role
            };

            filteredQuery['user_account_status'] = "APPROVED";
            filteredQuery['is_account_active'] = true;
            if (list_type == "All" && hospital_id) {
                delete filteredQuery['is_account_active'];
            }

            if (latitude && longitude) {
                let KM = 10;
                filteredQuery['location'] = {
                    $geoWithin: {
                        $centerSphere: [
                            [longitude, latitude], // Replace with actual coordinates
                            KM / 6378.1 // Radius in radians (300 km / Earth's radius in km)
                        ]
                    }
                }
            }

            if (language_multiple_ids && language_multiple_ids.length > 0) {
                const objectIdLanguageIds = language_multiple_ids.map(id => new mongoose.Types.ObjectId(id));
                filteredQuery['spoken_language'] = { $in: objectIdLanguageIds };
            }

            if (selected_gender) {
                filteredQuery['gender'] = selected_gender;
            }

            if (experience) {
                filteredQuery['year_of_practice'] = { $gte: experience };
            }


            // FOR DATA ACCORDING TO DATE & SLOTS
            let unavailabilitySlotsData = [];
            let bookedDoctorIds = [];
            if (selected_date && selected_slot_time) {

                unavailabilitySlotsData = await DoctorAvaliblitySlot.aggregate([
                    {
                        $match: {
                            selected_date: selected_date,
                            unavaliable_slots: {
                                $in: [time_slot]
                            }
                        }
                    },
                    {
                        $lookup: {
                            from: "users",
                            as: "doctorHospital",
                            let: { user_id: "$user_id" },
                            pipeline: [
                                {
                                    $match: {

                                        $expr: {
                                            $and: [
                                                {
                                                    $eq: ["$$user_id", "$_id"]
                                                },
                                                {
                                                    is_fulltime: true
                                                }
                                            ]

                                        },
                                    }
                                },
                            ],
                        },
                    },
                    {
                        $unwind: {
                            path: '$doctorHospital'
                        },
                    },

                    {
                        $project: {
                            user_id: 1,
                            unavaliable_slots: 1,
                        }
                    }
                ]);
                const bookedAppointments = await BookingAppointment.find({
                    $or: [
                        {
                            reschedule_date: selected_date,
                            reschedule_slot: selected_slot_time,
                            status: 'APPROVED'
                        },
                        {
                            booking_date: selected_date,
                            slot: selected_slot_time,
                            status: 'APPROVED',
                            reschedule_date: { $exists: false }
                        }
                    ]
                });
                bookedAppointments.map((booking) => {
                    bookedDoctorIds.push(booking.hospital_doctor_id);
                });
            }

            let removeUserIds = [];

            unavailabilitySlotsData.map(async (k: any) => {
                await removeUserIds.push(k.user_id);
            });
            let mergerArrayIDS = [...removeUserIds, ...notInDoctorHospitalIds, ...bookedDoctorIds];


            if (mergerArrayIDS && mergerArrayIDS.length > 0) {
                filteredQuery['_id'] = {
                    $nin: mergerArrayIDS
                }
            }

            if (hospital_id) {
                filteredQuery['hospital_id'] = new mongoose.Types.ObjectId(hospital_id);
            }
            if (search != '' && search != undefined) {
                let ids = await Category.find(
                    { $or: [{ title_en: { $regex: search, $options: 'i' } }, { title_fr: { $regex: search, $options: 'i' } }, { title_ar: { $regex: search, $options: 'i' } }] }, { _id: 1 }
                );
                ids = ids.map(obj => obj._id);

                filteredQuery['$or'] = [
                    { first_name: { $regex: search, $options: 'i' } },
                    { last_name: { $regex: search, $options: 'i' } },
                    { middle_name: { $regex: search, $options: 'i' } },
                    { hospital_name: { $regex: search, $options: 'i' } },
                    {
                        $expr: {
                            $regexMatch: {
                                input: { $concat: ["$first_name", " ", "$last_name"] },
                                regex: search,
                                options: "i"
                            }
                        }
                    },
                    {
                        $expr: {
                            $regexMatch: {
                                input: { $concat: ["$first_name", " ", "$middle_name", " ", "$last_name"] },
                                regex: search,
                                options: "i"
                            }
                        }
                    },
                    {
                        '$or': [
                            { 'clinic_municipality.commune_en': { $regex: search, $options: 'i' } },
                            { 'clinic_municipality.commune_fr': { $regex: search, $options: 'i' } },
                            { 'clinic_municipality.commune_ar': { $regex: search, $options: 'i' } }
                        ]
                    },
                    {
                        '$or': [
                            { 'clinic_department.wilaya_en': { $regex: search, $options: 'i' } },
                            { 'clinic_department.wilaya_fr': { $regex: search, $options: 'i' } },
                            { 'clinic_department.wilaya_ar': { $regex: search, $options: 'i' } }
                        ]
                    },
                    { primary_specialty: { $in: ids } }

                ];
            }

            filteredQuery['$and'] = [
                { _id: { $ne: new mongoose.Types.ObjectId(patient_id) } }
            ];

            // END OF DATA ACCORDING TO DATE & SLOTS
            let skip = parseInt(page) * limit;
            const [data, count] = await Promise.all([
                User.aggregate([
                    { $match: filteredQuery },
                    { $sort: { createdAt: -1 } },
                    { $skip: skip },
                    { $limit: limit },
                    {
                        $lookup: {
                            from: "roles",
                            as: "role_of_user",
                            let: { user_role: "$user_role" },
                            pipeline: [
                                {
                                    $match: {

                                        $expr: { $eq: ["$$user_role", "$_id"] },
                                    }
                                },
                            ],
                        },
                    },
                    {
                        $unwind: {
                            path: '$role_of_user',
                            preserveNullAndEmptyArrays: true,
                        },
                    },
                    {
                        $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',
                            localField: 'hospital_id',
                            foreignField: '_id',
                            as: "employer_details"
                        }
                    },
                    { $unwind: { path: "$employer_details", preserveNullAndEmptyArrays: true } },
                    {
                        $project:
                        {
                            salt_key: 0,
                            password: 0,
                            auth_token: 0,
                            email: 0,
                            otp: 0
                        }
                    }
                ]),
                User.countDocuments(filteredQuery)
            ]);
            return apiResponse(res, false, [], '', SUCCESS.OK, count, data, req)
        } else {
            return apiResponse(res, false, [], '', SUCCESS.OK, 0, [], req)
        }


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



// patient appointment listing

exports.appointmentListing = async (req, res) => {
    console.log("req.bodyss", req.body);
    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 { hospital_doctor_id, list_type, patient_name, start_date: bodyStartDate, end_date: bodyEndDate } = req.body;
        const patientNameFilter = {};
        if (patient_name) {
            const nameParts = patient_name.split(' ');

            if (nameParts.length > 1) {
                const firstName = nameParts[0];
                const lastName = nameParts[1];

                // Create regular expressions for both first and last name
                patientNameFilter['first_name'] = new RegExp(firstName, 'i');
                patientNameFilter['last_name'] = new RegExp(lastName, 'i');
            } else {
                // If only one part is provided, apply it to both first_name and last_name
                patientNameFilter['$or'] = [
                    { first_name: new RegExp(patient_name, 'i') },
                    { last_name: new RegExp(patient_name, 'i') }
                ];
            }
        }
        // Split the patient_name into parts

        // Now you can use 'patientSearch' object as intended     
        let filteredQuery = {
            hospital_doctor_id: new mongoose.Types.ObjectId(hospital_doctor_id)
        }

        let filteredQueryWithRescheduled = {
            hospital_doctor_id: new mongoose.Types.ObjectId(hospital_doctor_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()));;
            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['status'] = "APPROVED";

            filteredQuery['$and'] = [
                { booking_date: { $gte: today, $lt: tomorrow } },
                { reschedule_date: null }
            ];

            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;
        }


        // If custom date range provided, normalize and apply per list_type requirement
        // Requirements:
        //  PENDING   -> filter by createdAt
        //  UPCOMING  -> filter by booking_date (original) & reschedule_date (rescheduled)
        //  COMPLETED -> filter by booking_date only
        //  REJECTED  -> filter by rejected_date
        if (bodyStartDate && bodyEndDate) {
            try {
                const rangeStartDate = new Date(bodyStartDate);
                const rangeEndDate = new Date(bodyEndDate);
                rangeStartDate.setUTCHours(0, 0, 0, 0);
                rangeEndDate.setUTCHours(23, 59, 59, 999);

                switch (list_type) {
                    case 'PENDING':
                        // Remove any previous date $and conditions for consistency
                        delete filteredQuery['$and'];
                        filteredQuery['createdAt'] = { $gte: rangeStartDate, $lte: rangeEndDate };
                        // Mirror condition so OR does not broaden result unexpectedly
                        filteredQueryWithRescheduled['createdAt'] = { $gte: rangeStartDate, $lte: rangeEndDate };
                        break;
                    case 'UPCOMING':
                        filteredQuery['$and'] = [
                            { booking_date: { $gte: rangeStartDate, $lte: rangeEndDate } },
                            { reschedule_date: null }
                        ];
                        filteredQueryWithRescheduled['reschedule_date'] = { $gte: rangeStartDate, $lte: rangeEndDate };
                        break;
                    case 'COMPLETED':
                        // Only booking_date matters; neutralize reschedule branch with impossible match
                        delete filteredQuery['$and'];
                        filteredQuery['booking_date'] = { $gte: rangeStartDate, $lte: rangeEndDate };
                        // Use an always-false condition for second branch to avoid broad OR
                        filteredQueryWithRescheduled['_id'] = new mongoose.Types.ObjectId('000000000000000000000000');
                        break;
                    case 'REJECTED':
                        delete filteredQuery['$and'];
                        filteredQuery['booking_date'] = { $gte: rangeStartDate, $lte: rangeEndDate };
                        filteredQueryWithRescheduled['booking_date'] = { $gte: rangeStartDate, $lte: rangeEndDate };
                        break;
                    default:
                        // Fallback to original generic logic (booking & reschedule date windows)
                        filteredQuery['$and'] = [
                            { booking_date: { $gte: rangeStartDate, $lte: rangeEndDate } },
                            { reschedule_date: null }
                        ];
                        filteredQueryWithRescheduled['reschedule_date'] = { $gte: rangeStartDate, $lte: rangeEndDate };
                }
                console.log('custom date range applied', list_type, rangeStartDate, rangeEndDate);
            } catch (e) {
                console.log('Invalid custom date range supplied', e);
            }
        }

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

        console.log(JSON.stringify(matchCondition))

        // let patientNameFilter = {
        //     ...filter_patient_name
        // }


        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 patientRole = await Role.findOne({ title: "patient" });
        const patientRoleId = patientRole ? patientRole._id : null;

        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: "patient",
                        let: { patient_id: "$patient_id" },
                        pipeline: [
                            {
                                $match: {
                                    $and: [
                                        {
                                            $expr: { $eq: ["$$patient_id", "$_id"] }
                                        },
                                        {
                                            user_role: patientRoleId
                                        },
                                        patientNameFilter
                                    ]


                                }
                            },
                            { $project: { _id: 1, first_name: 1, last_name: 1, email: 1, profile_pic: 1, gender: 1, phone_number: 1, dob: 1, user_role: 1 } },
                        ]
                    }
                },
                {
                    $unwind: {
                        path: '$patient',
                        preserveNullAndEmptyArrays: true,
                    },
                },
                {
                    $match: {
                        patient: { $ne: null }
                    }
                },
                {
                    $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,
                                    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,
                                    consultation_reason: 1,
                                    is_fulltime: 1,
                                    clinic_timing: 1,
                                    platform_booking_status: 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", patient: "$patient", rejected_by: 1, booking_speciality: "$booking_speciality", reschedule_date: 1, reschedule_slot: 1, reschedule_by: 1, daily_room_name: 1, daily_room_url: 1, daily_room_token: 1, daily_room_created_at: 1 } },


            ]),
            BookingAppointment.aggregate([
                { $match: matchCondition },
                {
                    $lookup: {
                        from: "users",
                        as: "patient",
                        let: { patient_id: "$patient_id" },
                        pipeline: [
                            {
                                $match: {
                                    $and: [
                                        {
                                            $expr: { $eq: ["$$patient_id", "$_id"] }
                                        },
                                        {
                                            user_role: patientRoleId
                                        },
                                        patientNameFilter
                                    ]
                                }
                            },
                            { $project: { _id: 1 } },
                        ]
                    }
                },
                {
                    $unwind: {
                        path: '$patient',
                        preserveNullAndEmptyArrays: false, // Only count where patient exists
                    },
                },
                {
                    $count: "total"
                }
            ]).then(result => result.length > 0 ? result[0].total : 0)
        ]);
        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)
    }
}

// appointment status counts (summary)
// Returns counts for: pending, today, upcoming (next 30 days excluding today), approved (after 30 days), completed, rejected, total
// Mirrors the business logic used in appointmentListing for date windows.

/**
 * appointmentListingCounts with booking date range filter
 * Accepts optional bookingStartDate and bookingEndDate in req.body
 */

/**
 * Enhanced counts (mirrors date logic from appointmentListing)
 * - TODAY: status APPROVED and (reschedule_date || booking_date) is today
 * - UPCOMING: status APPROVED and effective date in next 30 days (excluding today)
 * - APPROVED: status APPROVED and effective date beyond 30–day window
 * - PENDING / COMPLETED / REJECTED: raw status counts
 * - Custom range (start_date,end_date) applies per-field logic like in appointmentListing:
 *      PENDING   -> createdAt in range
 *      UPCOMING / TODAY / APPROVED buckets derive from effective date (reschedule_date || booking_date) intersecting range
 *      COMPLETED -> booking_date in range
 *      REJECTED  -> booking_date in range
 */
exports.appointmentListingCounts = async (req, res) => {
    console.log("req.body count", req.body);
    const lang = req.headers["accept-language"] || 'en';
    try {
        console.log("success")
        const { hospital_doctor_id, start_date: bodyStartDate, end_date: bodyEndDate } = req.body;
        if (!hospital_doctor_id) {
            return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`] || 'Missing hospital_doctor_id', 400, 0, [], req);
        }

        const doctorId = new mongoose.Types.ObjectId(hospital_doctor_id);

        // Base relative windows
        const todayStart = new Date();
        todayStart.setUTCHours(0, 0, 0, 0);
        const tomorrowStart = new Date(todayStart);
        tomorrowStart.setUTCDate(todayStart.getUTCDate() + 1);

        const upcomingEnd = new Date(todayStart);
        upcomingEnd.setUTCDate(todayStart.getUTCDate() + 30);
        upcomingEnd.setUTCHours(23, 59, 59, 999);

        // Custom range (optional)
        let rangeStart: Date | null = null;
        let rangeEnd: Date | null = null;
        console.log("1")
        if (bodyStartDate && bodyEndDate) {
            try {
                rangeStart = new Date(bodyStartDate);
                rangeEnd = new Date(bodyEndDate);
                rangeStart.setUTCHours(0, 0, 0, 0);
                rangeEnd.setUTCHours(23, 59, 59, 999);
            } catch (e) {
                console.log('Invalid custom date range supplied for counts', e);
            }
        }


        console.log("2");
        // Build $group accumulator expressions
        // Effective date = reschedule_date (if not null) else booking_date
        const effectiveDate = { $ifNull: ["$reschedule_date", "$booking_date"] };

        // Helper to AND an array (filters out nulls)
        const andAll = (arr) => ({
            $and: arr.filter(Boolean)
        });

        // Range filters per status when custom range provided
        const inRangeCreatedAt = rangeStart ? { $gte: ["$createdAt", rangeStart] } : null;
        const inRangeCreatedAtLe = rangeEnd ? { $lte: ["$createdAt", rangeEnd] } : null;

        const inRangeBooking = rangeStart ? { $gte: ["$booking_date", rangeStart] } : null;
        const inRangeBookingLe = rangeEnd ? { $lte: ["$booking_date", rangeEnd] } : null;

        const inRangeEffective = rangeStart ? { $gte: [effectiveDate, rangeStart] } : null;
        const inRangeEffectiveLe = rangeEnd ? { $lte: [effectiveDate, rangeEnd] } : null;

        // COUNT CONDITIONS
        const pendingCond = andAll([
            { $eq: ["$status", "PENDING"] },
            rangeStart ? inRangeCreatedAt : null,
            rangeEnd ? inRangeCreatedAtLe : null
        ]);

        const completedCond = andAll([
            { $eq: ["$status", "COMPLETED"] },
            rangeStart ? inRangeBooking : null,
            rangeEnd ? inRangeBookingLe : null
        ]);

        const rejectedCond = andAll([
            { $eq: ["$status", "REJECTED"] },
            rangeStart ? inRangeBooking : null,
            rangeEnd ? inRangeBookingLe : null
        ]);

        // TODAY (subset of APPROVED by effective date)
        const todayCond = andAll([
            { $eq: ["$status", "APPROVED"] },
            { $gte: [effectiveDate, todayStart] },
            { $lt: [effectiveDate, tomorrowStart] },
            rangeStart ? inRangeEffective : null,
            rangeEnd ? inRangeEffectiveLe : null
        ]);

        // UPCOMING (next 30 days excluding today)
        const upcomingCond = andAll([
            { $eq: ["$status", "APPROVED"] },
            { $gte: [effectiveDate, todayStart] },
            { $lte: [effectiveDate, upcomingEnd] },
            rangeStart ? inRangeEffective : null,
            rangeEnd ? inRangeEffectiveLe : null
        ]);

        // APPROVED beyond 30–day window
        const approvedBeyondCond = andAll([
            { $eq: ["$status", "APPROVED"] },
            { $gt: [effectiveDate, upcomingEnd] },
            rangeStart ? inRangeEffective : null,
            rangeEnd ? inRangeEffectiveLe : null
        ]);

        console.log("upcomingCond",upcomingCond);
        // When custom range is present we still keep segmentation; counts will only reflect rows falling inside respective per-status filters.

        const pipeline = [
            { $match: { hospital_doctor_id: doctorId } },
            {
                $group: {
                    _id: null,
                    pending: { $sum: { $cond: [pendingCond, 1, 0] } },
                    today: { $sum: { $cond: [todayCond, 1, 0] } },
                    upcoming: { $sum: { $cond: [upcomingCond, 1, 0] } },
                    approved: { $sum: { $cond: [approvedBeyondCond, 1, 0] } },
                    completed: { $sum: { $cond: [completedCond, 1, 0] } },
                    rejected: { $sum: { $cond: [rejectedCond, 1, 0] } },
                    // total counts only those rows that match ANY of our status buckets (mirrors applied filters)
                    total: {
                        $sum: {
                            $cond: [
                                {
                                    $or: [
                                        pendingCond,
                                        todayCond,
                                        upcomingCond,
                                        approvedBeyondCond,
                                        completedCond,
                                        rejectedCond
                                    ]
                                },
                                1,
                                0
                            ]
                        }
                    }
                }
            }
        ];

        const agg = await BookingAppointment.aggregate(pipeline);
        const raw = agg.length ? agg[0] : {};

        const responseCounts = {
            pending: raw.pending || 0,
            today: raw.today || 0,
            upcoming: raw.upcoming || 0,
            approved: raw.approved || 0,
            completed: raw.completed || 0,
            rejected: raw.rejected || 0,
            total: raw.total || 0
        };

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

exports.appointmentListingCountsss = async (req, res) => {
    const lang = req.headers["accept-language"] || 'en';
    try {
        const { hospital_doctor_id, start_date: bodyStartDate, end_date: bodyEndDate } = req.body;
        if (!hospital_doctor_id) {
            return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`] || 'Missing hospital_doctor_id', 400, 0, [], req)
        }

        // Base date windows used for relative buckets (today, upcoming, approved-beyond)
        const todayStart = new Date();
        todayStart.setUTCHours(0, 0, 0, 0);
        const tomorrowStart = new Date(todayStart);
        tomorrowStart.setUTCDate(todayStart.getUTCDate() + 1);
        const upcomingEnd = new Date();
        upcomingEnd.setUTCDate(upcomingEnd.getUTCDate() + 30);
        upcomingEnd.setUTCHours(23, 59, 59, 999);

        const hospitalDoctorObjectId = new mongoose.Types.ObjectId(hospital_doctor_id);

        // If a custom date range is supplied we must constrain each status bucket by its relevant field:
        //  PENDING   -> createdAt within range
        //  COMPLETED -> booking_date within range
        //  REJECTED  -> updated_at within range

        let customMatch = null;
        if (bodyStartDate && bodyEndDate) {
            try {
                const rangeStartDate = new Date(bodyStartDate);
                const rangeEndDate = new Date(bodyEndDate);
                rangeStartDate.setUTCHours(0, 0, 0, 0);
                rangeEndDate.setUTCHours(23, 59, 59, 999);

                customMatch = {
                    $or: [
                        { $and: [{ status: 'PENDING' }, { createdAt: { $gte: rangeStartDate, $lte: rangeEndDate } }] },
                        { $and: [{ status: 'COMPLETED' }, { booking_date: { $gte: rangeStartDate, $lte: rangeEndDate } }] },
                        { $and: [{ status: 'REJECTED' }, { updated_at: { $gte: rangeStartDate, $lte: rangeEndDate } }] },
                        {
                            $and: [{ status: 'APPROVED' }, {
                                $or: [
                                    { $and: [{ $ne: ["$reschedule_date", null] }, { reschedule_date: { $gte: rangeStartDate, $lte: rangeEndDate } }] },
                                    { $and: [{ $eq: ["$reschedule_date", null] }, { booking_date: { $gte: rangeStartDate, $lte: rangeEndDate } }] }
                                ]
                            }]
                        }
                    ]
                }
            } catch (e) {
                console.log('Invalid custom date range for counts', e);
            }
        }

        const pipeline = [
            { $match: customMatch ? { $and: [{ hospital_doctor_id: hospitalDoctorObjectId }, customMatch] } : { hospital_doctor_id: hospitalDoctorObjectId } },
            {
                $group: {
                    _id: null,
                    pending: { $sum: { $cond: [{ $eq: ["$status", "PENDING"] }, 1, 0] } },
                    completed: { $sum: { $cond: [{ $eq: ["$status", "COMPLETED"] }, 1, 0] } },
                    rejected: { $sum: { $cond: [{ $eq: ["$status", "REJECTED"] }, 1, 0] } },
                    upcoming: { $sum: { $cond: [{ $eq: ["$status", "APPROVED"] }, 1, 0] } },
                    total: { $sum: 1 }
                }
            }
        ];

        const result = await BookingAppointment.aggregate(pipeline);
        const counts = result.length ? result[0] : { pending: 0, today: 0, upcoming: 0, approved: 0, completed: 0, rejected: 0, total: 0 };
        const responseCounts = {
            pending: counts.pending || 0,
            upcoming: counts.upcoming || 0,
            completed: counts.completed || 0,
            rejected: counts.rejected || 0,
            total: counts.total || 0
        };
        return apiResponse(res, false, [], '', SUCCESS.OK, 0, responseCounts, req)
    } catch (error) {
        console.log(error);
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }
}

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

    try {
        const { hospital_doctor_id } = req.body;

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

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

        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['booking_date'] = { $gte: today, $lt: tomorrow }
        filteredQuery['status'] = "APPROVED";

        filteredQueryWithRescheduled['reschedule_date'] = { $gte: today, $lt: tomorrow }
        filteredQueryWithRescheduled['status'] = "APPROVED";
        let matchCondition = {
            $or: [
                filteredQuery,
                filteredQueryWithRescheduled
            ]
        }
        const [data] = await Promise.all([
            BookingAppointment.aggregate([
                { $match: matchCondition },

                { $sort: { createdAt: -1 } },
                {
                    $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: "patient",
                        let: { patient_id: "$patient_id" },
                        pipeline: [
                            {
                                $match: {
                                    $and: [
                                        {
                                            $expr: { $eq: ["$$patient_id", "$_id"] }
                                        }
                                    ]


                                }
                            },
                            { $project: { _id: 1, first_name: 1, last_name: 1, email: 1, profile_pic: 1, gender: 1, phone_number: 1, dob: 1, social_security_number: 1 } },
                        ]
                    }
                },
                {
                    $unwind: {
                        path: '$patient',
                        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,
                                    city: 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,
                                    is_fulltime: 1,
                                    clinic_timing: 1,
                                    additional_specialty: 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", patient: "$patient", rejected_by: 1, booking_speciality: "$booking_speciality", reschedule_date: 1, reschedule_slot: 1, reschedule_by: 1 } },


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



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

// // doctor aciton on patient appointment 
exports.doctorActionOnAppointment = async (req, res) => {
    var title_lang = 'en';
    const lang = req.headers["accept-language"] || 'en'

    try {
        const { booking_id, status, reschedule_slot, reschedule_date, rejected_reason, rejected_by, language } = req.body;
        let flag: any = await isLimitReachedForSlot(booking_id, status, reschedule_slot, reschedule_date);
        if (!flag && status == 'APPROVED') {
            return apiResponse(res, true, [], ERROR_MSG[`Slot-limit-reached-${lang}`], 400, 0, [], req);
        }
        let endDate = new Date(new Date().setDate(new Date().getDate() + 30));
        endDate.setUTCHours(23, 59, 59);
        let filteredQuery = {
            _id: new mongoose.Types.ObjectId(booking_id),
        }
        let action = await BookingAppointment.findOneAndUpdate(filteredQuery, { status: status, reschedule_date: reschedule_date, reschedule_slot: reschedule_slot, rejected_reason: rejected_reason, rejected_by: rejected_by, }, { new: true })

        console.log("---------- after action on booking --------", action);

        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, user_role: 1, hospital_name: 1, clinic_name: 1 })
        let doctorClinicName = doctor.hospital_name?.trim() ? doctor.hospital_name : doctor.clinic_name

        let roleFindOfDoctorHospital = await Role.findOne({ _id: new mongoose.Types.ObjectId(doctor.user_role) }, { _id: 1, title: 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);

        if (roleFindOfDoctorHospital.title == 'doctor') {
            doctorFullName = doctorFullName
        }
        else {
            doctorFullName = `${doctor.hospital_name}`.charAt(0).toUpperCase() + `${doctor.hospital_name}`.slice(1);
        }
        console.log(action.booking_role_type);
        // let appointmentType = await Role.findOne({ _id: doctor.user_role }, { title: 1 })

        // let condition = {}
        // condition['_id'] = new mongoose.Types.ObjectId(hospital_doctor_id);
        // let record = await User.findOne(condition, { _id:1,selected_language:1});
        let fetchPatientID = await BookingAppointment.findOne(filteredQuery, { patient_id: 1 });
        let condition = {}
        condition['_id'] = new mongoose.Types.ObjectId(fetchPatientID.patient_id);
        const dateString = action.booking_date;
        const date = new Date(dateString);

        const formattedDate = `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`;
        let record = await User.findOne(condition, { _id: 1, selected_language: 1, phone_number: 1 });
        let booking_date = new Date(action.booking_date) // make sure it's a Date object

        let start_date = new Date();
        start_date.setDate(start_date.getDate() + 1); // tomorrow
        start_date.setUTCHours(0, 0, 0, 0); // set to midnight UTC

        const today = new Date();
        today.setUTCHours(0, 0, 0, 0);

        const tomorrow = new Date(today);
        tomorrow.setUTCDate(today.getUTCDate() + 1);




        if (action && action.status == 'APPROVED' && action.reschedule_date == null) {
            let reschedule_date = new Date(action.reschedule_date)
            if ((booking_date >= today && booking_date < tomorrow) || (reschedule_date >= today && reschedule_date < tomorrow
            )
            ) {
                action.status = "TODAY";
            } else if ((booking_date >= start_date && booking_date <= endDate) || (reschedule_date >= start_date && reschedule_date <= endDate)) {
                action.status = "UPCOMING";
            }
            let templateData;
            if (record.selected_language === 'fr') {
                templateData = await doctorAppoinmentAcceptedTemplate_fr({ patientFullName, user_role: roleFindOfDoctorHospital.title, doctorFullName, action, doctorClinicName })
                await MobileOtp(record.phone_number.e164Number, `Salut ${patientFullName}, votre rendez-vous avec le Dr ${doctorFullName} a été confirmé !

                    Date : ${formattedDate}
                    Heure : ${action.slot}
                    Type : ${doctorClinicName}
                    `)

            } else if (record.selected_language === 'ar') {
                templateData = await doctorAppoinmentAcceptedTemplate_ar({ patientFullName, user_role: roleFindOfDoctorHospital.title, doctorFullName, action, doctorClinicName })
                await MobileOtp(record.phone_number.e164Number, `مرحبًا ${patientFullName}، تم تأكيد موعدك مع الدكتور ${doctorFullName}!

                    التاريخ: ${formattedDate}
                    الوقت: ${action.slot}
                    النوع: ${doctorClinicName}
                    `)

            }
            else {
                templateData = await doctorAppoinmentAcceptedTemplate({ patientFullName, user_role: roleFindOfDoctorHospital.title, doctorFullName, action, doctorClinicName })
                await MobileOtp(record.phone_number.e164Number, `Hi ${patientFullName}, your appointment with Dr. ${doctorFullName} has been confirmed!

                    Date: ${formattedDate}
                    Time: ${action.slot}
                    Type: ${doctorClinicName}
                    `)

            }

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

            let schema = {
                user_id: patient._id,
                notify_en: DOCTOR_NOTIFY[`APPROVED-BOOKING-en`],
                notify_ar: DOCTOR_NOTIFY[`APPROVED-BOOKING-ar`],
                notify_fr: DOCTOR_NOTIFY[`APPROVED-BOOKING-fr`]
            }
            const userTokenDetails = await Fcm.find({ user_id: patient._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)

        }
        if (action && action.status == 'APPROVED' && action.reschedule_date !== null) {
            let reschedule_date = new Date(action.reschedule_date)
            if ((reschedule_date >= today && reschedule_date < tomorrow)) {
                action.status = "TODAY";
            } else if ((reschedule_date >= today && reschedule_date <= endDate)) {
                action.status = "UPCOMING";
            }
            const reschduledate = new Date(action.reschedule_date);

            const formattedRescheduleDate = `${reschduledate.getDate()}/${reschduledate.getMonth() + 1}/${reschduledate.getFullYear()}`;
            let templateData;
            if (record.selected_language === 'fr') {
                templateData = await doctorRescheduledAppoinmentAcceptedTemplate_fr({ patientFullName, user_role: roleFindOfDoctorHospital.title, doctorFullName, action, doctorClinicName })
                await MobileOtp(record.phone_number.e164Number, `Bonjour ${patientFullName},
                    Nous avons le plaisir de vous informer que votre rendez-vous avec
                    Dr. ${doctorFullName} a été rééchelonné avec succès.
                    Détails du nouveau rendez-vous :
                    SUCCESSSUCCESS
                    Médecin : Dr. ${doctorFullName}
                    Date : ${formattedRescheduleDate}
                    Heure : ${action.reschedule_slot}
                    Type de rendez-vous : ${doctorClinicName}
                                        `)
            } else if (record.selected_language === 'ar') {
                templateData = await doctorRescheduledAppoinmentAcceptedTemplate_ar({ patientFullName, user_role: roleFindOfDoctorHospital.title, doctorFullName, action, doctorClinicName })
                await MobileOtp(record.phone_number.e164Number, `مرحباً ${patientFullName}،
                    نود إبلاغك أنه تم إعادة جدولة موعدك مع
                    د. ${doctorFullName} بنجاح.
                    تفاصيل الموعد الجديد:

                    الطبيب: د. ${doctorFullName}
                    التاريخ: ${formattedRescheduleDate}
                    الوقت: ${action.reschedule_slot}
                    نوع الموعد: ${doctorClinicName}
                                        `)
            }
            else {
                templateData = await doctorRescheduledAppoinmentAcceptedTemplate({ patientFullName, user_role: roleFindOfDoctorHospital.title, doctorFullName, action, doctorClinicName })
                await MobileOtp(record.phone_number.e164Number, `Hello ${patientFullName},
                    We are pleased to inform you that your appointment with
                    Dr. ${doctorFullName} has been successfully rescheduled.
                    New appointment details:

                    Doctor: Dr. ${doctorFullName}
                    Date: ${formattedRescheduleDate}
                    Time: ${action.reschedule_slot}
                    Appointment Type: ${doctorClinicName}
                                        `)
            }
            const mailOptions = {
                to: patient.email,
                subject: templateData.subject,
                html: templateData.html
            };
            let isEmailSent = await sendEmail(mailOptions, res)
            let sentStatus = 'PENDING'
            if (isEmailSent) {
                sentStatus = 'SUCCESS'
            }
            let cronPostParams = {
                "user_id": patient._id,
                "email_to": patient.email,
                "email_subject": templateData.subject,
                "email_content": templateData.html,
                "cron_email_type": "appoinment approved",
                "cron_email_status": sentStatus
            }
            let saveEmail = new CronEmail(cronPostParams)
            saveEmail.save()

            let schema = {
                user_id: doctor._id,
                notify_en: DOCTOR_NOTIFY[`APPROVED-RESCHEDULED-REQ-en`],
                notify_ar: DOCTOR_NOTIFY[`APPROVED-RESCHEDULED-REQ-ar`],
                notify_fr: DOCTOR_NOTIFY[`APPROVED-RESCHEDULED-REQ-fr`]
            }
            const dorTokenDetails = await Fcm.find({ user_id: doctor._id });
            dorTokenDetails.length && dorTokenDetails.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);
            console.log(patient, " --------------- here the patient ---------")

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

        }


        if (action && action.status == 'REJECTED' && action.reschedule_date == null) {
            let templateData;
            if (record.selected_language === 'fr') {
                templateData = await doctorAppoinmentRejectedTemplate_fr({ patientFullName, doctorFullName, action, doctorClinicName, user_role: roleFindOfDoctorHospital.title })
                await MobileOtp(record.phone_number.e164Number, `Salut ${patientFullName}, nous avons le regret de vous informer que votre demande de rendez-vous avec le Dr. ${doctorFullName} a été rejetée.
Raison du rejet : ${action.rejected_reason || "Le médecin est hors de la ville"}

Date : ${formattedDate}
Heure : ${action.slot}
Type : ${doctorClinicName}
                                        `)
            } else if (record.selected_language === 'ar') {
                templateData = await doctorAppoinmentRejectedTemplate_ar({ patientFullName, doctorFullName, action, doctorClinicName, user_role: roleFindOfDoctorHospital.title })
                await MobileOtp(record.phone_number.e164Number, `مرحبًا ${patientFullName}، نأسف لإبلاغك بأن طلبك للحصول على موعد مع الدكتور ${doctorFullName} قد تم رفضه.
سبب الرفض : ${action.rejected_reason || "الدكتور خارج المدينة"}

التاريخ: ${formattedDate}
الوقت: ${action.slot}
النوع: ${doctorClinicName}
                                        `)
            }
            else {
                templateData = await doctorAppoinmentRejectedTemplate({ patientFullName, doctorFullName, action, doctorClinicName, user_role: roleFindOfDoctorHospital.title })
                await MobileOtp(record.phone_number.e164Number, `Hi ${patientFullName}, we regret to inform you that your appointment request with Dr. ${doctorFullName} has been rejected.
Reason for Rejection: ${action.rejected_reason || "Doctor is out of town"}

Date: ${formattedDate}
Time: ${action.slot}
Type: ${doctorClinicName}

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

            let schema = {
                user_id: patient._id,
                notify_en: PATIENT_NOTIFY[`REJECTED-BOOKING-en`],
                notify_ar: PATIENT_NOTIFY[`REJECTED-BOOKING-ar`],
                notify_fr: PATIENT_NOTIFY[`REJECTED-BOOKING-fr`]
            }
            const patTokenDetails = await Fcm.find({ user_id: patient._id });
            patTokenDetails.length && patTokenDetails.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)
        }
        if (action && action.status == 'REJECTED' && action.reschedule_date !== null) {
            const reschduleRejectdate = new Date(action.reschedule_date);

            const formattedRescheduleRejectDate = `${reschduleRejectdate.getDate()}/${reschduleRejectdate.getMonth() + 1}/${reschduleRejectdate.getFullYear()}`;
            let templateData;
            if (record.selected_language === 'fr') {
                templateData = await doctorRescheduledAppoinmentRejectedTemplate_fr({ patientFullName, doctorFullName, action, doctorClinicName, user_role: roleFindOfDoctorHospital.title })
                await MobileOtp(record.phone_number.e164Number, `Bonjour ${patientFullName},
                        Nous avons le regret de vous informer que votre demande de reprogrammation de votre rendez-vous avec
                        Dr. ${doctorFullName} a été rejetée.
                        Raison du rejet : ${action.rejected_reason ? action.rejected_reason : "Le médecin est hors de la ville"}.

                        Détails du rendez-vous :

                        Médecin : Dr. ${doctorFullName}
                        Date : ${formattedRescheduleRejectDate}
                        Heure : ${action.reschedule_slot}
                        Type de rendez-vous : ${doctorClinicName}
                                                            `)
            } else if (record.selected_language === 'ar') {
                templateData = await doctorRescheduledAppoinmentRejectedTemplate_ar({ patientFullName, doctorFullName, action, doctorClinicName, user_role: roleFindOfDoctorHospital.title })
                await MobileOtp(record.phone_number.e164Number, `مرحباً ${patientFullName}،
                        نأسف لإبلاغك أنه تم رفض طلبك لإعادة جدولة موعدك مع
                        د. ${doctorFullName}.
                        سبب الرفض: ${action.rejected_reason ? action.rejected_reason : "الطبيب خارج المدينة"}.

                        تفاصيل الموعد:

                        الطبيب: د. ${doctorFullName}
                        التاريخ: ${formattedRescheduleRejectDate}
                        الوقت: ${action.reschedule_slot}
                        نوع الموعد: ${doctorClinicName}

                                                            `)
            }
            else {
                templateData = await doctorRescheduledAppoinmentRejectedTemplate({ patientFullName, doctorFullName, action, doctorClinicName, user_role: roleFindOfDoctorHospital.title })
                await MobileOtp(record.phone_number.e164Number, `Hello ${patientFullName},
                    We regret to inform you that your request to reschedule your appointment with
                    Dr. ${doctorFullName} has been rejected.
                    Reason for rejection: ${action.rejected_reason ? action.rejected_reason : "Doctor is out of town"}.

                    Appointment Details:

                    Doctor: Dr. ${doctorFullName}
                    Date: ${formattedRescheduleRejectDate}
                    Time: ${action.reschedule_slot}
                    Appointment Type: ${doctorClinicName}
                                                            `)
            }
            const mailOptions = {
                to: patient.email,
                subject: templateData.subject,
                html: templateData.html
            };
            let isEmailSent = await sendEmail(mailOptions, res)
            let sentStatus = 'PENDING'
            if (isEmailSent) {
                sentStatus = 'SUCCESS'
            }
            let cronPostParams = {
                "user_id": patient._id,
                "email_to": patient.email,
                "email_subject": templateData.subject,
                "email_content": templateData.html,
                "cron_email_type": "appoinment rejected",
                "cron_email_status": sentStatus
            }
            let saveEmail = new CronEmail(cronPostParams)
            saveEmail.save()

            let schema = {
                user_id: patient._id,
                notify_en: PATIENT_NOTIFY[`REJECTED-BOOKING-en`],
                notify_ar: PATIENT_NOTIFY[`REJECTED-BOOKING-ar`],
                notify_fr: PATIENT_NOTIFY[`REJECTED-BOOKING-fr`]
            }
            const patTokenDetails = await Fcm.find({ user_id: patient._id });
            patTokenDetails.length && patTokenDetails.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: roleFindOfDoctorHospital.title,
            status: status
        }

        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) {
        console.log(error);
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }
}


// notification listing

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,           // Total number of notifications based on the query
            unread: unreadCount          // Number of unread notifications
        };

        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)
    }
}
// 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)
    }
}

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

    try {
        const { booking_id } = req.body;

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

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

        const [data, count] = await Promise.all([
            BookingAppointment.aggregate([
                { $match: filteredQuery },
                {
                    $lookup: {
                        from: "users",
                        as: "patient",
                        let: { patient_id: "$patient_id" },
                        pipeline: [
                            {
                                $match: {

                                    $expr: { $eq: ["$$patient_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
                                            }
                                        }
                                    ],
                                },

                            },
                            { $project: { _id: 1, first_name: 1, last_name: 1, email: 1, profile_pic: 1, gender: 1, phone_number: 1, dob: 1, selected_speciality: 1, qualification: 1, additional_qualification: 1, year_of_practice: 1, city: 1, state: 1, zip_code: 1, street_address: 1, clinic_name: 1, user_role: "$userRole.title" } },
                        ]
                    }
                },
                {
                    $unwind: {
                        path: '$patient',
                        preserveNullAndEmptyArrays: true,
                    },
                },
                {
                    $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,
                                    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,
                                    certificate: 1,
                                    clinic_timing: 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, patient: "$patient", document_file_from_doctor: 1, rejected_by: 1, booking_speciality: 1, reschedule_date: 1, reschedule_slot: 1, reschedule_by: 1, consultation_reason: 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.editDoctorHospitalAppointment = 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)
    }
}



//rechudleAppoinment
exports.doctorRescheduleAppointment = 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, booking_id, hospital_doctor_id, status, reschedule_date, reschedule_slot, reschedule_by, booking_speciality, role_name, language } = req.body;

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

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

    console.log(updateCondition);

    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) {
        console.log(err)
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }



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


    try {
        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, user_role: 1, clinic_name: 1, hospital_name: 1 })


        let roleFindOfDoctorHospital = await Role.findOne({ _id: new mongoose.Types.ObjectId(doctor.user_role) }, { _id: 1, title: 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);

        if (roleFindOfDoctorHospital.title == 'doctor') {
            doctorFullName = doctorFullName
        }
        else {
            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 doctorClinicName = doctor.hospital_name?.trim() ? doctor.hospital_name : doctor.clinic_name
        let fetchPatientid = await BookingAppointment.findOne({ _id: new mongoose.Types.ObjectId(id) }, { patient_id: 1 });
        let condition = {}
        condition['_id'] = new mongoose.Types.ObjectId(fetchPatientid.patient_id);


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

        const dateReschduled = new Date(action.reschedule_date);

        const formatteddateReschduled = `${dateReschduled.getDate()}/${dateReschduled.getMonth() + 1}/${dateReschduled.getFullYear()}`;
        let templateData;
        if (record.selected_language === 'fr') {
            templateData = await doctorRescheduleAppointmentTemplate_fr({ patientFullName, doctorFullName, user_role: roleFindOfDoctorHospital.title, action, reschedule_slot, doctorClinicName })
            await MobileOtp(record.phone_number.e164Number, `Bonjour ${patientFullName},

                Votre rendez-vous avec Dr. ${doctorFullName} a été reprogrammé avec succès.

                Détails du rendez-vous mis à jour :
                - Médecin : Dr. ${doctorFullName}
                - Date : ${formatteddateReschduled}
                - Heure : ${reschedule_slot}
                - Type de rendez-vous : ${doctorClinicName}

                Merci pour votre compréhension et coopération.

                                    `)

        } else if (record.selected_language === 'ar') {
            templateData = await doctorRescheduleAppointmentTemplate_ar({ patientFullName, doctorFullName, user_role: roleFindOfDoctorHospital.title, action, reschedule_slot, doctorClinicName })
            await MobileOtp(record.phone_number.e164Number, `مرحباً ${patientFullName}،

                تم إعادة جدولة موعدك مع د. ${doctorFullName} بنجاح.

                تفاصيل الموعد المُعدل:
                - الطبيب: د. ${doctorFullName}
                - التاريخ: ${formatteddateReschduled}
                - الوقت: ${reschedule_slot}
                - نوع الموعد: ${doctorClinicName}

                شكراً لتفهمك وتعاونك.

                                    `)
        }
        else {
            templateData = await doctorRescheduleAppointmentTemplate({ patientFullName, doctorFullName, user_role: roleFindOfDoctorHospital.title, action, reschedule_slot, doctorClinicName })
            await MobileOtp(record.phone_number.e164Number, `Hello ${patientFullName},

                Your appointment with Dr. ${doctorFullName} has been successfully rescheduled.

                Updated Appointment Details:
                - Doctor: Dr. ${doctorFullName}
                - Date: ${formatteddateReschduled}
                - Time: ${reschedule_slot}
                - Appointment Type: ${doctorClinicName}

                Thank you for your understanding and cooperation.

                                    `)
        }

        const mailOptions = {
            to: patient.email,
            subject: templateData.subject,
            html: templateData.html
        };
        let isEmailSent = await sendEmail(mailOptions, res)
        let sentStatus = 'PENDING'
        if (isEmailSent) {
            sentStatus = 'SUCCESS'
        }
        let cronPostParams = {
            "user_id": patient._id,
            "email_to": patient.email,
            "email_subject": templateData.subject,
            "email_content": templateData.html,
            "cron_email_type": "appoinment rejected",
            "cron_email_status": sentStatus
        }
        let saveEmail = new CronEmail(cronPostParams)
        saveEmail.save()
        let schema = {
            user_id: action.hospital_doctor_id,
            notify_en: DOCTOR_NOTIFY[`RESCEDULE-BOOKING-en`],
            notify_ar: DOCTOR_NOTIFY[`RESCEDULE-BOOKING-ar`],
            notify_fr: DOCTOR_NOTIFY[`RESCEDULE-BOOKING-fr`]
        }
        const dorTokenDetails = await Fcm.find({ user_id: action.hospital_doctor_id });
        dorTokenDetails.length && dorTokenDetails.forEach(async (token) => {
            await sendPushNotification(token?.device_token, 'Dr. Hivey', schema?.[`notify_${lang}`], { booking_id: String(action._id), d_screen_url: String(`${action.status}`) });
            let endDate = new Date(new Date().setDate(new Date().getDate() + 30));
            endDate.setUTCHours(23, 59, 59);
            let booking_date = new Date(action.booking_date) // make sure it's a Date object

            let start_date = new Date();
            start_date.setDate(start_date.getDate() + 1); // tomorrow
            start_date.setUTCHours(0, 0, 0, 0); // set to midnight UTC

            const today = new Date();
            today.setUTCHours(0, 0, 0, 0);

            const tomorrow = new Date(today);
            tomorrow.setUTCDate(today.getUTCDate() + 1);
            let reschedule_date = new Date(action.reschedule_date)
            if ((reschedule_date >= today && reschedule_date < tomorrow
            )
            ) {
                action.status = "TODAY";
            } else if ((reschedule_date >= start_date && reschedule_date <= endDate)) {
                action.status = "UPCOMING";
            }
            const dorTokenDetails = await Fcm.find({ user_id: action.hospital_doctor_id });
            dorTokenDetails.length && dorTokenDetails.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)

            // patient
            let schema1 = {
                user_id: patient._id,
                notify_en: PATIENT_NOTIFY[`RESCEDULE-BOOKING-en`],
                notify_ar: PATIENT_NOTIFY[`RESCEDULE-BOOKING-ar`],
                notify_fr: PATIENT_NOTIFY[`RESCEDULE-BOOKING-fr`]
            }
            const patTokenDetails = await Fcm.find({ user_id: patient._id });
            patTokenDetails.length && patTokenDetails.forEach(async (token) => {
                await sendPushNotification(token?.device_token, 'Dr. Hivey', schema1?.[`notify_${lang}`], { booking_id: String(action._id), d_screen_url: String(`${action.status}`) });
            });
            await addNotification(schema1, 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: roleFindOfDoctorHospital.title,
                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) {
        console.log(error)
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }
}

// today approved appointment count
exports.approvedAppointmentCount = async (req, res) => {
    let lang = req.headers["accept-language"] || 'en'
    try {
        const currentDate = new Date();
        const startOfDay = new Date(currentDate.setUTCHours(0, 0, 0, 0));
        const endOfDay = new Date(currentDate.setUTCHours(23, 59, 59, 999));


        let filteredQuery = {}
        let filteredQueryWithRescheduled = {}
        let 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
        let tomorrow = new Date(today); // Clone the today date object
        tomorrow.setUTCDate(today.getUTCDate() + 1);
        console.log(today, tomorrow);

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

        filteredQueryWithRescheduled['reschedule_date'] = { $gte: today, $lt: tomorrow }
        filteredQueryWithRescheduled['status'] = "APPROVED";
        console.log(filteredQuery, filteredQueryWithRescheduled);
        let count = await BookingAppointment.countDocuments({

            $or: [
                filteredQuery,
                filteredQueryWithRescheduled
            ],
            hospital_doctor_id: new mongoose.Types.ObjectId(req.body.hospital_doctor_id),
        })
        return apiResponse(res, false, [], '', SUCCESS.OK, count, [], req)
    } catch (error) {
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }
}

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

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

    try {
        const { hospital_doctor_id } = req.body
        var filteredQuery = {}
        let page, limit: number;

        filteredQuery['user_account_status'] = "APPROVED";
        filteredQuery['is_account_active'] = true;
        filteredQuery['is_deleted'] = false;

        page = req.query.page ? parseInt(req.query.page) - 1 : 0;
        limit = req.query.limit ? parseInt(req.query.limit) : 10;

        const patientIds = await BookingAppointment.distinct('patient_id', {
            hospital_doctor_id: new mongoose.Types.ObjectId(hospital_doctor_id)
        });


        if (patientIds && patientIds.length > 0) {
            filteredQuery['_id'] = {
                $in: patientIds
            }
        } else {
            return apiResponse(res, false, [], '', SUCCESS.OK, 0, [], req)
        }
        let skip = parseInt(page) * limit;
        const pipeline = [
            { $match: filteredQuery },
            { $sort: { createdAt: -1 } },
            { $skip: skip },
            { $limit: limit },
            {
                $lookup: {
                    from: "block-users",
                    as: "blockUser",
                    let: { p_id: "$_id", hos_doc_id: new mongoose.Types.ObjectId(hospital_doctor_id) },
                    pipeline: [
                        {
                            $match: {
                                $and: [
                                    { $expr: { $eq: ["$$p_id", "$patient_id"] } },
                                    { $expr: { $eq: ["$$hos_doc_id", "$hospital_doctor_id"] } }
                                ]
                            }
                        },
                        { $project: { _id: 1, is_blocked_user: 1, } }
                    ],
                },
            },

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

            { $project: { _id: 1, first_name: 1, last_name: 1, dob: 1, phone_number: 1, gender: 1, profile_pic: 1, is_blocked_user: "$blockUser.is_blocked_user" } }
        ];

        const [data, count] = await Promise.all([
            User.aggregate(pipeline),
            User.countDocuments(filteredQuery)
        ]);

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

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

    try {
        const { hospital_doctor_id, patient_id, is_blocked_user } = req.body;

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

        if (findExistsRecord) {
            //update condition
            await BlockUser.findOneAndUpdate({ _id: new mongoose.Types.ObjectId(findExistsRecord._id) }, { $set: { is_blocked_user: is_blocked_user } }, { new: true });

            return apiResponse(res, false, [], SUCCESS_MSG[`USER-UPDATED-${lang}`], SUCCESS.OK, 0, findExistsRecord, req)

        } else {
            //save condition
            new BlockUser(_.pick(req.body, ['hospital_doctor_id', 'patient_id', 'is_blocked_user'])).save()
                .then(async function (data) {
                    return apiResponse(res, false, [], SUCCESS_MSG[`USER-UPDATED-${lang}`], SUCCESS.OK, 0, [], 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)
    }
}

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

    const { patient_id, hospital_doctor_id } = req.body;
    var title_lang = 'en';
    const lang = req.headers["accept-language"] || 'en';

    try {
        var filteredQuery = {
            _id: new mongoose.Types.ObjectId(patient_id)
        }
        const pipeline = [
            { $match: filteredQuery },
            {
                $lookup: {
                    from: "block-users",
                    as: "blockUser",
                    let: { p_id: "$_id", hos_doc_id: new mongoose.Types.ObjectId(hospital_doctor_id) },
                    pipeline: [
                        {
                            $match: {
                                $and: [
                                    { $expr: { $eq: ["$$p_id", "$hospital_doctor_id"] } },
                                    { $expr: { $eq: ["$$hos_doc_id", "$patient_id"] } }
                                ]
                            }
                        },
                        { $project: { _id: 1, is_blocked_user: 1, } }
                    ],
                },
            },

            {
                $unwind: {
                    path: '$blockUser',
                    preserveNullAndEmptyArrays: true,
                },
            },
            {
                $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
                            }
                        }
                    ],
                },

            },
            { $project: { _id: 1, first_name: 1, last_name: 1, dob: 1, phone_number: 1, gender: 1, profile_pic: 1, is_blocked_user: "$blockUser.is_blocked_user", selected_speciality: "$selected_speciality", qualification: 1, additional_qualification: 1, year_of_practice: 1 } }
        ];

        const data = await User.aggregate(pipeline).then(results => results[0] || null);
        const count = await User.countDocuments(filteredQuery);
        return apiResponse(res, false, [], '', SUCCESS.OK, count, data, req)
    } catch (error) {
        return apiResponse(res, true, [], ERROR_MSG[`SYSTEM-ERROR-${title_lang}`], SERVER_ERROR.internalServerError, 0, [], req)
    }

}


exports.appointmentHistoryForPatient = async (req, res) => {
    const { patient_id, hospital_doctor_id, booking_id } = req.body;
    var title_lang = 'en';
    const lang = req.headers["accept-language"] || 'en';

    try {
        var filteredQuery = {
            booking_id: new mongoose.Types.ObjectId(booking_id),
        };
        let page, limit;
        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 pipeline = [
            { $match: filteredQuery },
            { $sort: { updatedAt: -1 } },
            { $skip: skip },
            { $limit: limit },
            {
                $lookup: {
                    from: "bookings",
                    as: "bookingDetails",
                    let: { bok_id: "$booking_id" },
                    pipeline: [
                        {
                            $match: {
                                $expr: { $eq: ["$$bok_id", "$_id"] },
                            },
                        },
                        {
                            $project: {
                                _id: 1,
                                patient_id: 1,
                                hospital_doctor_id: 1,
                                slot: 1,
                                booking_date: 1,
                                reschedule_date: 1,
                                reschedule_slot: 1,
                            },
                        },
                    ],
                },
            },
            { $unwind: { path: "$bookingDetails" } },
        ];

        const [data, count] = await Promise.all([
            BookingHistory.aggregate(pipeline),
            BookingHistory.countDocuments(filteredQuery),
        ]);

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



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

    try {
        var filteredQuery = {
            patient_id: new mongoose.Types.ObjectId(patient_id),
            hospital_doctor_id: new mongoose.Types.ObjectId(hospital_doctor_id),
        };

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

        const pipeline = [
            { $match: filteredQuery },

            // Group by booking_id to ensure uniqueness
            {
                $group: {
                    _id: "$booking_id",  // Group by unique booking_id
                    patient_id: { $first: "$patient_id" },  // Retain first occurrence of patient_id
                    hospital_doctor_id: { $first: "$hospital_doctor_id" },  // Retain first occurrence of hospital_doctor_id
                    status: { $last: "$status" },  // Take the most recent status
                    updatedAt: { $max: "$updatedAt" },  // Get the most recent updatedAt for each booking_id
                },
            },

            // Sort by the most recent updatedAt to get the latest status
            { $sort: { updatedAt: -1 } },

            // Lookup to fetch detailed booking info
            {
                $lookup: {
                    from: "bookings",  // Lookup from the bookings collection
                    as: "bookingDetails",
                    let: { bok_id: "$_id" },
                    pipeline: [
                        {
                            $match: {
                                $expr: { $eq: ["$$bok_id", "$_id"] },  // Match booking_id with the group's booking_id
                            },
                        },
                        {
                            $project: {
                                _id: 1,
                                patient_id: 1,
                                hospital_doctor_id: 1,
                                slot: 1,
                                booking_date: 1,
                                reschedule_date: 1,
                                reschedule_slot: 1,
                            },
                        },
                    ],
                },
            },

            { $unwind: { path: "$bookingDetails" } },  // Unwind the bookingDetails array to merge them into the main object

            { $skip: skip },  // Pagination - skip records
            { $limit: limit },  // Pagination - limit to the specified number of records
        ];

        // Separate pipeline for counting unique bookings without pagination
        const countPipeline = [
            { $match: filteredQuery },

            // Group by booking_id to ensure uniqueness
            {
                $group: {
                    _id: "$booking_id",  // Group by unique booking_id
                },
            },

            // Sort by the most recent updatedAt for each unique booking
            { $sort: { updatedAt: -1 } },
        ];

        const [data, countResult] = await Promise.all([
            BookingHistory.aggregate(pipeline),
            BookingHistory.aggregate(countPipeline),
        ]);

        const count = countResult.length;  // Count the number of unique bookings

        return apiResponse(res, false, [], "", SUCCESS.OK, count, data, req);
    } catch (error) {
        return apiResponse(
            res,
            true,
            [],
            ERROR_MSG[`SYSTEM-ERROR-${title_lang}`],
            SERVER_ERROR.internalServerError,
            0,
            [],
            req
        );
    }


};


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

    try {
        // Get the logged-in doctor's ID from the request
        const hospital_doctor_id = req.user._id;

        // Create a pipeline to fetch unique patients who have bookings with this doctor
        const pipeline = [
            {
                $match: {
                    patient_id: new mongoose.Types.ObjectId(hospital_doctor_id),
                }
            },
            // Group by patient_id to get unique patients
            {
                $group: {
                    _id: "$patient_id",
                    patient_id: { $first: "$patient_id" },
                    hospital_doctor_id: { $first: "$hospital_doctor_id" },
                    updatedAt: { $max: "$updatedAt" },
                }
            },
            // Sort by the most recent updatedAt
            { $sort: { updatedAt: -1 } },
            // Lookup to fetch patient details
            {
                $lookup: {
                    from: "users",
                    localField: "hospital_doctor_id",
                    foreignField: "_id",
                    as: "patientDetails",
                    pipeline: [
                        {
                            $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
                                        }
                                    }
                                ],
                            },

                        }
                    ]
                }
            },

            // Unwind the patientDetails array
            { $unwind: { path: "$patientDetails" } },
            // Project only the fields we need
            {
                $project: {
                    _id: 1,
                    patient_id: 1,
                    "patientDetails._id": 1,
                    "patientDetails.first_name": 1,
                    "patientDetails.last_name": 1,
                    "patientDetails.email": 1,
                    "patientDetails.phone_number": 1,
                    "patientDetails.profile_image": 1,
                    "patientDetails.year_of_practice": 1,
                    "patientDetails.qualification": 1,
                    "patientDetails.additional_qualification": 1,
                    "patientDetails.selected_speciality": "$patientDetails.selected_speciality",
                }
            }
        ];

        const data = await BookingAppointment.aggregate(pipeline);
        const count = data.length;

        return apiResponse(res, false, [], "", SUCCESS.OK, count, data, req);
    } catch (error) {
        console.error("Error in getUniquePatientsByDoctor:", error);
        return apiResponse(
            res,
            true,
            [],
            ERROR_MSG[`SYSTEM-ERROR-${title_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 { email, 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 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, [], "Phone number already exist !", CLIENT_ERROR.badRequest, 0, existingUser, req);
            }
            else {
                return apiResponse(res, true, [], 'Email address already exist', CLIENT_ERROR.badRequest, 0, existingUser, req);
            }
        }
        // exitingUser profile but not completed
        if (existingUser && existingUser.is_signup == true && existingUser.is_signup_otp_varify == false) {

            return apiResponse(res, true, [], 'Email address already exist', CLIENT_ERROR.badRequest, 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', 'is_signup_otp_varify']));
            newUser['email'] = req.body.email.toLowerCase();
            let templateData = await RegisteredByAdmin(newUser);
            const mailOptions = {
                to: newUser.email,
                subject: templateData.subject,
                html: templateData.html
            };
            let isEmailSent = await sendEmail(mailOptions, res)
            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']
            }
            // || user_role == 'doctor' || user_role == 'hospital'
            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) {
                    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.getAllPatientList = async (req, res) => {
    try {
        var title_lang = 'en';
        const lang = req.headers["accept-language"] || 'en';
        const { hospital_doctor_id, search } = req.body
        var filteredQuery = {}
        let page, limit: number;

        filteredQuery['user_account_status'] = "APPROVED";
        filteredQuery['is_account_active'] = true;
        filteredQuery['is_deleted'] = false;
        const filteredNameQuery = {};

        if (search != '' && search != null && search != undefined) {
            filteredNameQuery['$or'] = [{
                $expr: {
                    $regexMatch: {
                        input: { $concat: ["$first_name", " ", "$last_name"] }, // Concatenating with a space
                        regex: search,
                        options: "i"
                    }
                }
            }]
        }

        let pipeline: any;


        if (search != '' || search != null || search != undefined || !search) {
            page = req.query.page ? parseInt(req.query.page) - 1 : 0;
            limit = req.query.limit ? parseInt(req.query.limit) : 10;

            let skip = parseInt(page) * limit;
            pipeline = [
                {
                    $lookup:
                    {
                        from: 'roles',
                        localField: 'user_role',
                        foreignField: '_id',
                        as: 'role'
                    }
                },
                { $unwind: { path: "$role" } },
                {
                    $match:
                    {
                        "role.title": "patient"
                    }
                },
                { $match: filteredQuery },
                { $match: filteredNameQuery },
                { $sort: { createdAt: -1 } },
                { $skip: skip },
                { $limit: limit },

                {
                    $lookup: {
                        from: "block-users",
                        as: "blockUser",
                        let: { p_id: "$_id", hos_doc_id: new mongoose.Types.ObjectId(hospital_doctor_id) },
                        pipeline: [
                            {
                                $match: {
                                    $and: [
                                        { $expr: { $eq: ["$$p_id", "$patient_id"] } },
                                        { $expr: { $eq: ["$$hos_doc_id", "$hospital_doctor_id"] } }
                                    ]
                                }
                            },
                            { $project: { _id: 1, is_blocked_user: 1, } }
                        ],
                    },
                },

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

                { $project: { _id: 1, first_name: 1, last_name: 1, dob: 1, phone_number: 1, gender: 1, profile_pic: 1, is_blocked_user: "$blockUser.is_blocked_user" } }
            ];
        }
        else {
            pipeline = [
                {
                    $lookup:
                    {
                        from: 'roles',
                        localField: 'user_role',
                        foreignField: '_id',
                        as: 'role'
                    }
                },
                { $unwind: { path: "$role" } },
                {
                    $match:
                    {
                        "role.title": "patient"
                    }
                },
                { $match: filteredQuery },
                { $match: filteredNameQuery },
                { $sort: { createdAt: -1 } },
                {
                    $lookup: {
                        from: "block-users",
                        as: "blockUser",
                        let: { p_id: "$_id", hos_doc_id: new mongoose.Types.ObjectId(hospital_doctor_id) },
                        pipeline: [
                            {
                                $match: {
                                    $and: [
                                        { $expr: { $eq: ["$$p_id", "$patient_id"] } },
                                        { $expr: { $eq: ["$$hos_doc_id", "$hospital_doctor_id"] } }
                                    ]
                                }
                            },
                            { $project: { _id: 1, is_blocked_user: 1, } }
                        ],
                    },
                },

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

                { $project: { _id: 1, first_name: 1, last_name: 1, dob: 1, phone_number: 1, gender: 1, profile_pic: 1, is_blocked_user: "$blockUser.is_blocked_user" } }
            ];
        }

        const [data, count] = await Promise.all([
            User.aggregate(pipeline),
            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.bookAppointmentForPatient = async (req, res) => {
    const lang = req.headers["accept-language"] || 'en'
    try {

        // 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 } = req.body;

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

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

        const doctorHospitalDetails = await User.findById(hospital_doctor_id).populate('user_role');
        req['booking_role_type'] = doctorHospitalDetails?.user_role?._id.toString();
        console.log("----------- Booking role type ----------", req.booking_role_type)
        req['booking_speciality'] = doctorHospitalDetails.primary_specialty[0];
        req['document_file'] = [];
        req['reschedule_date'] = null;
        req['reschedule_slot'] = null;
        req['booking_date'] = (new Date(req.booking_date)).setHours(0, 0);
        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) });



        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'])).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
                }

                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 })
                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, hospital_name: 1, clinic_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 appointmentType = doctorHospitalDetails?.user_role?.title
                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;
                let user_role = doctor.hospital_name ? 'hospital' : 'doctor';
                console.log(patientFullName, doctorFullName, action, doctorClinicName, user_role)
                if (record.selected_language === 'fr') {
                    templateData = await newAppointmentEmailTemplate_fr({ patientFullName, doctorFullName, action, doctorClinicName, user_role })

                    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, 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! 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 Appointment",
                    "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 dorTokenDetails = await Fcm.find({ user_id: data.hospital_doctor_id });
                dorTokenDetails.length && dorTokenDetails.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)

                // patient
                let patientSchema = {
                    user_id: data.patient_id,
                    notify_en: PATIENT_NOTIFY[`DOCTOR-SCHEDULED-en`],
                    notify_ar: PATIENT_NOTIFY[`DOCTOR-SCHEDULED-ar`],
                    notify_fr: PATIENT_NOTIFY[`DOCTOR-SCHEDULED-fr`]
                }
                const patTokenDetails = await Fcm.find({ user_id: data.patient_id });
                patTokenDetails.length && patTokenDetails.forEach(async (token) => {
                    await sendPushNotification(token?.device_token, 'Doctome', patientSchema?.[`notify_${lang}`], { booking_id: String(action._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.log(err);
                throw new Error(err)
            });



    }
    catch (error) {
        console.log(error)
        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;
}

exports.doctorDetailsById = async (req, res) => {
    try {
        const { id } = req.params;
        const details = await User.findById(id).populate('primary_specialty').populate('spoken_language').populate('user_role');
        return apiResponse(res, false, [], '', SUCCESS.OK, 0, details, req);
    }
    catch (error) {
        console.error(error);
        return apiResponse(res, true, [], ERROR_MSG[`SERVER-ERROR`], SERVER_ERROR.internalServerError, 0, [], req);
    }
}

async function isLimitReachedForSlot(booking_id: any, status: any, reschedule_slot: any, reschedule_date: any) {
    try {
        const bookingDetails = await BookingAppointment.findById(booking_id);
        const doctorDetails = await User.findById(bookingDetails.hospital_doctor_id);
        console.log(bookingDetails.booking_date, "------------- doctor details -----------")
        if (doctorDetails.is_fulltime) {
            return true;
        }
        let find_slots = [];
        doctorDetails.clinic_timing.length && doctorDetails.clinic_timing.forEach((res: any) => {
            find_slots.push(`${formatTimeForSlot(res.start_time)} - ${formatTimeForSlot(res.end_time)}`);
        });
        let selected_date = bookingDetails.booking_date;

        // console.log("----------- find slots --------", find_slots)
        let rangeStartDate = new Date(selected_date);
        rangeStartDate.setUTCHours(0, 0, 0);

        let rangeEndDate = new Date(selected_date);
        rangeEndDate.setHours(23, 59, 59);


        let conditionFind = {
            hospital_doctor_id: doctorDetails._id,
            slot: { $in: find_slots },
            $or: [
                {
                    $and: [
                        {
                            booking_date: { $gte: rangeStartDate, $lte: rangeEndDate },
                            reschedule_date: null
                        }
                    ]
                },
                {
                    reschedule_date: { $gte: rangeStartDate, $lte: rangeEndDate }
                }
            ],
            status: "APPROVED"
        }


        const result = await BookingAppointment.find(conditionFind);

        let arr = [];
        let flag = true;

        doctorDetails.clinic_timing.length && doctorDetails.clinic_timing.forEach((res: any) => {
            let totalCount = 0;

            result.length && result.forEach((elem: any) => {
                if (bookingDetails.slot == `${formatTimeForSlot(res.start_time)} - ${formatTimeForSlot(res.end_time)}`) {
                    totalCount++;
                }

                if (elem.reschedule_slot == `${formatTimeForSlot(res.start_time)} - ${formatTimeForSlot(res.end_time)}`) {
                    totalCount++;
                }
            })

            if (totalCount >= res.limit) {
                flag = false
            }

        });

        return flag;
    }
    catch (error) {
        throw new Error(error);
    }
}

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

    const lang = req.headers["accept-language"] || 'en';
    try {
        const { status, id } = req.body;
        const details = await User.findOne({ _id: id, is_deleted: false });
        if (!details) {
            return apiResponse(res, true, [], ERROR_MSG[`ACCOUNT-NOT-EXIST-${lang}`], CLIENT_ERROR.badRequest, 0, [], req);
        }

        details['is_account_active'] = status;
        details.save();
        return apiResponse(res, false, [], '', SUCCESS.OK, 0, details, req);

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


exports.hospitalDashboardAppointmentListing = 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 { hospital_doctor_id, list_type, patient_name } = req.body;
        const patientNameFilter = {};
        if (patient_name) {
            const nameParts = patient_name.split(' ');

            if (nameParts.length > 1) {
                const firstName = nameParts[0];
                const lastName = nameParts[1];

                // Create regular expressions for both first and last name
                patientNameFilter['first_name'] = new RegExp(firstName, 'i');
                patientNameFilter['last_name'] = new RegExp(lastName, 'i');
            } else {
                // If only one part is provided, apply it to both first_name and last_name
                patientNameFilter['$or'] = [
                    { first_name: new RegExp(patient_name, 'i') },
                    { last_name: new RegExp(patient_name, 'i') }
                ];
            }
        }
        // Split the patient_name into parts

        // Now you can use 'patientSearch' object as intended
        let filteredQuery = {};
        let filteredQueryWithRescheduled = {};
        if (!hospital_doctor_id) {
            filteredQuery = {
                hospital_doctor_id: new mongoose.Types.ObjectId(hospital_doctor_id)
            }

            filteredQueryWithRescheduled = {
                hospital_doctor_id: new mongoose.Types.ObjectId(hospital_doctor_id)
            }
        }
        else {
            const doctorsList = await User.findOne({ hospital_id: req.user.id }, { _id: 1 });
            let list = doctorsList.map((obj) => { return new mongoose.Types.ObjectId(obj._id) });
            filteredQuery = {
                hospital_doctor_id: { $in: list }
            }

            filteredQueryWithRescheduled = {
                hospital_doctor_id: { $in: list }
            }
        }


        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['status'] = "APPROVED";

            filteredQuery['$and'] = [
                { booking_date: { $gte: today, $lt: tomorrow } },
                { reschedule_date: null }
            ];

            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
            ]
        }

        console.log(JSON.stringify(matchCondition))

        // let patientNameFilter = {
        //     ...filter_patient_name
        // }


        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: "patient",
                        let: { patient_id: "$patient_id" },
                        pipeline: [
                            {
                                $match: {
                                    $and: [
                                        {
                                            $expr: { $eq: ["$$patient_id", "$_id"] }
                                        },
                                        patientNameFilter
                                    ]


                                }
                            },
                            { $project: { _id: 1, first_name: 1, last_name: 1, email: 1, profile_pic: 1, gender: 1, phone_number: 1, dob: 1 } },
                        ]
                    }
                },
                {
                    $unwind: {
                        path: '$patient',
                        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,
                                    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,
                                    is_fulltime: 1,
                                    clinic_timing: 1,
                                    platform_booking_status: 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", patient: "$patient", rejected_by: 1, booking_speciality: "$booking_speciality", reschedule_date: 1, reschedule_slot: 1, reschedule_by: 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)
    }
}

exports.listOfHospitalEmployees = async (req, res) => {
    var title_lang = 'en';
    const lang = req.headers["accept-language"] || 'en';
    try {
        console.log(req.user.id)
        const role = await Role.findOne({ title: "doctor" });
        const list = await User.find({ hospital_id: req.user._id, is_deleted: false, user_role: role._id }, { _id: 1, first_name: 1, last_name: 1, email: 1, is_Account_active: 1 });
        return apiResponse(res, false, [], '', SUCCESS.OK, list.length, list, req);

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


exports.doctorsAppointmentListing = 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 { hospital_doctor_id, list_type, patient_name } = req.body;
        const patientNameFilter = {};
        if (patient_name) {
            const nameParts = patient_name.split(' ');

            if (nameParts.length > 1) {
                const firstName = nameParts[0];
                const lastName = nameParts[1];

                // Create regular expressions for both first and last name
                patientNameFilter['first_name'] = new RegExp(firstName, 'i');
                patientNameFilter['last_name'] = new RegExp(lastName, 'i');
            } else {
                // If only one part is provided, apply it to both first_name and last_name
                patientNameFilter['$or'] = [
                    { first_name: new RegExp(patient_name, 'i') },
                    { last_name: new RegExp(patient_name, 'i') }
                ];
            }
        }
        // Split the patient_name into parts

        // Now you can use 'patientSearch' object as intended
        let filteredQuery = {
            hospital_doctor_id: new mongoose.Types.ObjectId(hospital_doctor_id)
        }

        let filteredQueryWithRescheduled = {
            hospital_doctor_id: new mongoose.Types.ObjectId(hospital_doctor_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);

            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['status'] = "APPROVED";

            filteredQuery['$and'] = [
                { booking_date: { $gte: today, $lt: tomorrow } },
                { reschedule_date: null }
            ];

            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
            ]
        }

        //console.log(matchCondition)

        // let patientNameFilter = {
        //     ...filter_patient_name
        // }


        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 doctorRole = await Role.findOne({ title: "doctor" });
        const doctorRoleId = doctorRole ? doctorRole._id : null;

        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: "patient",
                        let: { patient_id: "$patient_id" },
                        pipeline: [
                            {
                                $match: {
                                    $and: [
                                        {
                                            $expr: { $eq: ["$$patient_id", "$_id"] }
                                        },
                                        {
                                            user_role: doctorRoleId
                                        },
                                        patientNameFilter
                                    ]
                                }
                            },
                            {
                                $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
                                            }
                                        }
                                    ],
                                },

                            },
                            { $project: { _id: 1, first_name: 1, last_name: 1, email: 1, profile_pic: 1, gender: 1, phone_number: 1, dob: 1, user_role: 1, selected_speciality: 1, qualification: 1, additional_qualification: 1, year_of_practice: 1 } },
                        ]
                    }
                },
                {
                    $unwind: {
                        path: '$patient',
                        preserveNullAndEmptyArrays: true,
                    },
                },
                {
                    $match: {
                        patient: { $ne: null }
                    }
                },
                {
                    $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,
                                    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,
                                    clinic_timing: 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", patient: "$patient", rejected_by: 1, booking_speciality: "$booking_speciality", reschedule_date: 1, reschedule_slot: 1, reschedule_by: 1, consultation_reason: 1 } },


            ]),
            BookingAppointment.aggregate([
                { $match: matchCondition },
                {
                    $lookup: {
                        from: "users",
                        as: "patient",
                        let: { patient_id: "$patient_id" },
                        pipeline: [
                            {
                                $match: {
                                    $and: [
                                        {
                                            $expr: { $eq: ["$$patient_id", "$_id"] }
                                        },
                                        {
                                            user_role: doctorRoleId
                                        },
                                        patientNameFilter
                                    ]
                                }
                            },
                            { $project: { _id: 1 } },
                        ]
                    }
                },
                {
                    $unwind: {
                        path: '$patient',
                        preserveNullAndEmptyArrays: false, // Only count where patient exists
                    },
                },
                {
                    $count: "total"
                }
            ]).then(result => result.length > 0 ? result[0].total : 0)
        ]);
        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)
    }
}
