HEX
Server: nginx/1.24.0
System: Linux DGT-WORDPRESS-VM-SERVER 6.14.0-1014-azure #14~24.04.1-Ubuntu SMP Fri Oct 3 20:52:11 UTC 2025 x86_64
User: ubuntu (1000)
PHP: 8.4.12
Disabled: NONE
Upload Files
File: /mnt/data/doccure-wp/wp-content/plugins/doccure/chat/class-chat-system.php
<?php

use Dompdf\Css\Style;   
if (!class_exists('ChatSystem')) {
    /**
     * One to One Chat System
     * 
     * @package doccure
     */
    class ChatSystem
    {
        
        /**
         * DB Variable
         * 
         * @var [string]
         */
        protected static $wpdb;
        /**
         * Initialize Singleton
         *
         * @var [void]
         */
        private static $_instance = null;

        /**
         * Call this method to get singleton
         *
         * @return ChatSystem Instance
         */
        public static function instance()
        {
            if (self::$_instance === null) {
                self::$_instance = new ChatSystem();
            }
            return self::$_instance;
        }

        /**
         * PRIVATE CONSTRUCTOR
         */
        private function __construct()
        {
            global $wpdb;
            self::$wpdb = $wpdb;
            add_action('after_setup_theme', array(__CLASS__, 'createChatTable'));
            add_action('fetch_users_threads', array(__CLASS__, 'fetchUserThreads'), 11, 1);
            add_action('wp_ajax_fetchUserConversation', array(__CLASS__, 'fetchUserConversation'));
            add_action('wp_ajax_nopriv_fetchUserConversation', array(__CLASS__, 'fetchUserConversation'));
            add_action('wp_ajax_sendUserMessage', array(__CLASS__, 'sendUserMessage'));
            add_action('wp_ajax_nopriv_sendUserMessage', array(__CLASS__, 'sendUserMessage'));
            add_action('wp_ajax_getIntervalChatHistoryData', array(__CLASS__, 'getIntervalChatHistoryData'));
            add_action('wp_ajax_nopriv_getIntervalChatHistoryData', array(__CLASS__, 'getIntervalChatHistoryData'));
            add_filter('get_user_info', array(__CLASS__, 'getUserInfoData'), 10, 3);
			add_action('fetch_single_users_threads', array(__CLASS__, 'fetchSingleUserThreads'), 11, 2);
			add_action('doccure_chat_count', array(__CLASS__, 'countUnreadMessages'),11,2);
			add_filter('doccure_chat_count', array(__CLASS__, 'countUnreadMessages'),11,2);
			
        }

        /**
         * Create Chat Table
         *
         * @return void
         */
        public static function createChatTable()
        {
            global $wpdb;
            $private_chat = $wpdb->prefix . "private_chat";
            
            if ($wpdb->get_var("SHOW TABLES LIKE '$private_chat'") != $private_chat) {
                $charset_collate = $wpdb->get_charset_collate();
                $sql = "CREATE TABLE $private_chat (
                    id int(11) NOT NULL AUTO_INCREMENT,
                    sender_id int(11) NOT NULL,
                    receiver_id int(11) NOT NULL,
                    chat_message text NOT NULL,
                    status int(11) NOT NULL DEFAULT 1,
                    timestamp int(11) NOT NULL,
                    time_gmt datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
                    PRIMARY KEY (id)
                ) $charset_collate;";

                require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
                dbDelta($sql);
            }
        }

        /**
         * Get current user's role
         */
        public static function getCurrentUserRole($userId = '') {
            $user = get_userdata($userId);
            if (!empty($user)) {
                $roles = $user->roles;
                if (in_array('doctors', $roles)) {
                    return 'doctor';
                } elseif (in_array('doctors_staff', $roles)) {
                    return 'doctors_staff';
                } elseif (in_array('staff', $roles)) {
                    return 'staff';
                } elseif (in_array('regular_users', $roles)) {
                    return 'patient';
                }
            }
            return 'user';
        }

        /**
         * Check if staff can chat with a specific user
         */
        public static function canStaffChatWithUser($staffId, $targetUserId) {
            $staffParentId = get_user_meta($staffId, 'parent_id', true);
            $targetUserParentId = get_user_meta($targetUserId, 'parent_id', true);
            
            // Get user roles
            $staffRole = self::getCurrentUserRole($staffId);
            $targetUserRole = self::getCurrentUserRole($targetUserId);
            
            // Staff can always chat with their parent doctor
            if ($targetUserId == $staffParentId) {
                return true;
            }
            
            // Staff can chat with doctors_staff and staff created by the same doctor
            if (in_array($targetUserRole, array('doctors_staff', 'staff')) && $targetUserParentId == $staffParentId) {
                return true;
            }
            
            return false;
        }

        /**
         * Check if doctor can chat with a specific user
         */
        public static function canDoctorChatWithUser($doctorId, $targetUserId) {
            $targetUserRole = self::getCurrentUserRole($targetUserId);
            $targetUserParentId = get_user_meta($targetUserId, 'parent_id', true);
            
            // Doctors can chat with ALL patients (regular_users) regardless of parent_id
            if ($targetUserRole === 'patient') {
                return true;
            }
            
            // Doctors can chat with doctors_staff and staff they created
            if (in_array($targetUserRole, array('doctors_staff', 'staff'))) {
                return $targetUserParentId == $doctorId;
            }
            
            return false;
        }

        /**
         * Check if doctors_staff can chat with a specific user
         */
        public static function canDoctorsStaffChatWithUser($doctorsStaffId, $targetUserId) {
            $doctorsStaffParentId = get_user_meta($doctorsStaffId, 'parent_id', true);
            $targetUserParentId = get_user_meta($targetUserId, 'parent_id', true);
            
            // Get user roles
            $doctorsStaffRole = self::getCurrentUserRole($doctorsStaffId);
            $targetUserRole = self::getCurrentUserRole($targetUserId);
            
            // Doctors_staff can always chat with their parent doctor
            if ($targetUserId == $doctorsStaffParentId) {
                return true;
            }
            
            // Doctors_staff can chat with other doctors_staff and staff created by the same doctor
            if (in_array($targetUserRole, array('doctors_staff', 'staff')) && $targetUserParentId == $doctorsStaffParentId) {
                return true;
            }
            
            // NEW: Doctors_staff can chat with ALL patients
            if ($targetUserRole === 'patient') {
                return true;
            }
            
            return false;
        }

        /**
         * Check if patient can chat with a specific user
         */
        public static function canPatientChatWithUser($patientId, $targetUserId) {
            $targetUserRole = self::getCurrentUserRole($targetUserId);
            $targetUserParentId = get_user_meta($targetUserId, 'parent_id', true);
            
            // Patients can chat with doctors and doctors_staff
            if (in_array($targetUserRole, array('doctor', 'doctors_staff'))) {
                return true;
            }
            
            return false;
        }

        /**
         * Validate if users can chat before sending message
         */
        public static function validateChatPermission($senderId, $receiverId) {
            $senderRole = self::getCurrentUserRole($senderId);
            $receiverRole = self::getCurrentUserRole($receiverId);
            
            switch($senderRole) {
                case 'doctor':
                    return self::canDoctorChatWithUser($senderId, $receiverId);
                    
                case 'staff':
                    return self::canStaffChatWithUser($senderId, $receiverId);
                    
                case 'doctors_staff':
                    return self::canDoctorsStaffChatWithUser($senderId, $receiverId);
                    
                case 'patient':
                    return self::canPatientChatWithUser($senderId, $receiverId);
                    
                default:
                    return false;
            }
        }

        /**
         * Get All Users for Chat by Role with restrictions based on current user role
         */
        public static function getAllUsersForChat($userId = '', $role = '') {
            global $wpdb;
            
            $userTable = $wpdb->prefix . 'users';
            $usermetaTable = $wpdb->prefix . 'usermeta';
            $privateChat = $wpdb->prefix . 'private_chat';
            
            // Get current user's role
            $current_user_role = self::getCurrentUserRole($userId);
            
            // Base query to get all potential users
            $query = "SELECT 
                        u.ID as user_id, 
                        u.display_name, 
                        u.user_email,
                        u.user_registered,
                        pc.id as last_message_id,
                        pc.chat_message as last_message,
                        pc.status as last_message_status,
                        pc.time_gmt as last_message_time,
                        pc.sender_id,
                        pc.receiver_id,
                        CASE 
                            WHEN pc.id IS NOT NULL THEN 1 
                            ELSE 0 
                        END as has_chat_history
                     FROM $userTable u
                     LEFT JOIN $privateChat pc ON pc.id = (
                         SELECT MAX(id) FROM $privateChat 
                         WHERE (sender_id = u.ID AND receiver_id = $userId) 
                            OR (sender_id = $userId AND receiver_id = u.ID)
                     )
                     WHERE u.ID != $userId";
            
            // Add role-based restrictions
            switch($current_user_role) {
                case 'doctor':
                    // Doctors can see ALL patients, and doctors_staff/staff they created
                    $query .= " AND (
                        u.ID IN (
                            SELECT user_id FROM $usermetaTable 
                            WHERE meta_key = 'parent_id' AND meta_value = $userId
                            AND user_id IN (
                                SELECT user_id FROM $usermetaTable 
                                WHERE meta_key = 'wp_capabilities' 
                                AND (meta_value LIKE '%\"doctors_staff\"%' OR meta_value LIKE '%\"staff\"%')
                            )
                        )
                        OR 
                        u.ID IN (
                            SELECT user_id FROM $usermetaTable 
                            WHERE meta_key = 'wp_capabilities' 
                            AND meta_value LIKE '%\"regular_users\"%'
                        )
                    )";
                    break;
                    
                case 'staff':
                    $parentId = get_user_meta($userId, 'parent_id', true);
                    if (empty($parentId)) {
                        // If no parent_id, staff can't chat with anyone
                        $query .= " AND 1=0";
                    } else {
                        // Staff can see their parent doctor, doctors_staff, and other staff from same doctor
                        $query .= " AND (
                            u.ID = $parentId 
                            OR u.ID IN (
                                SELECT user_id FROM $usermetaTable 
                                WHERE meta_key = 'parent_id' AND meta_value = $parentId
                                AND user_id IN (
                                    SELECT user_id FROM $usermetaTable 
                                    WHERE meta_key = 'wp_capabilities' 
                                    AND (meta_value LIKE '%\"doctors_staff\"%' OR meta_value LIKE '%\"staff\"%')
                                )
                            )
                        )";
                    }
                    break;
                    
                case 'doctors_staff':
                    $parentId = get_user_meta($userId, 'parent_id', true);
                    if (empty($parentId)) {
                        // If no parent_id, doctors_staff can't chat with anyone
                        $query .= " AND 1=0";
                    } else {
                        // UPDATED: Doctors_staff can see their parent doctor, other doctors_staff, staff from same doctor, AND ALL patients
                        $query .= " AND (
                            u.ID = $parentId 
                            OR u.ID IN (
                                SELECT user_id FROM $usermetaTable 
                                WHERE meta_key = 'parent_id' AND meta_value = $parentId
                                AND user_id IN (
                                    SELECT user_id FROM $usermetaTable 
                                    WHERE meta_key = 'wp_capabilities' 
                                    AND (meta_value LIKE '%\"doctors_staff\"%' OR meta_value LIKE '%\"staff\"%')
                                )
                            )
                            OR u.ID IN (
                                SELECT user_id FROM $usermetaTable 
                                WHERE meta_key = 'wp_capabilities' 
                                AND meta_value LIKE '%\"regular_users\"%'
                            )
                        )";
                    }
                    break;
                    
                case 'patient':
                    // Patients can see doctors and doctors_staff
                    $query .= " AND u.ID IN (
                        SELECT user_id FROM $usermetaTable 
                        WHERE meta_key = 'wp_capabilities' 
                        AND (meta_value LIKE '%\"doctors\"%' OR meta_value LIKE '%\"doctors_staff\"%')
                    )";
                    break;
            }

            // Add role filter if specified
            if (!empty($role)) {
                switch($role) {
                    case 'doctor':
                        // Doctor filter includes both doctors and doctors_staff for all users
                        $query .= " AND u.ID IN (
                            SELECT user_id FROM $usermetaTable 
                            WHERE meta_key = 'wp_capabilities' 
                            AND (meta_value LIKE '%\"doctors\"%' OR meta_value LIKE '%\"doctors_staff\"%')
                        )";
                        break;
                    case 'staff':
                        $query .= " AND u.ID IN (
                            SELECT user_id FROM $usermetaTable 
                            WHERE meta_key = 'wp_capabilities' 
                            AND meta_value LIKE '%\"staff\"%'
                        )";
                        break;
                    case 'patient':
                        $query .= " AND u.ID IN (
                            SELECT user_id FROM $usermetaTable 
                            WHERE meta_key = 'wp_capabilities' 
                            AND meta_value LIKE '%\"regular_users\"%'
                        )";
                        break;
                }
            }
            
            $query .= " ORDER BY has_chat_history DESC, pc.time_gmt DESC, u.display_name ASC";
            
            return $wpdb->get_results($query, ARRAY_A);
        }

        /**
         * Get User Role for Display
         */
        public static function getUserRole($user_id) {
            $user = get_userdata($user_id);
            if (!empty($user)) {
                $roles = $user->roles;
                if (in_array('doctors', $roles)) {
                    return 'doctor';
                } elseif (in_array('doctors_staff', $roles)) {
                    return 'doctors_staff';
                } elseif (in_array('staff', $roles)) {
                    return 'staff';
                } elseif (in_array('regular_users', $roles)) {
                    return 'patient';
                }
            }
            return 'user';
        }

        /**
         * Get available filter buttons based on user role
         */
        public static function getAvailableFilters($userId = '') {
            $current_user_role = self::getCurrentUserRole($userId);
            $available_filters = array();
            
            switch($current_user_role) {
                case 'doctor':
                    // Doctors can see all filters for users they created + all patients
                    $available_filters = array('doctor', 'staff', 'patient');
                    break;
                case 'staff':
                    // Staff can see doctor (combined doctors + doctors_staff) and staff filters
                    $available_filters = array('doctor', 'staff');
                    break;
                case 'doctors_staff':
                    // Doctors_staff can see doctor (combined), staff and patient filters
                    $available_filters = array('doctor', 'staff', 'patient');
                    break;
                case 'patient':
                    // Patients can see only doctor (combined doctors + doctors_staff) filter
                    $available_filters = array('doctor');
                    break;
                default:
                    $available_filters = array('doctor', 'staff', 'patient');
                    break;
            }
            
            return $available_filters;
        }

        /**
         * Get Chat Users List Threads
         *
         * @return array
         */
        public static function getUsersThreadListData(
            $userId = '',
            $receiverID = '',
            $type = 'list',
            $data = array(),
            $msgID = '',
			$offset = '',
            $role = '' // Added role parameter
        ) {
            $privateChat = self::$wpdb->prefix . 'private_chat';
            $userTable = self::$wpdb->prefix . 'users';
            $fetchResults = array();
			
            switch ($type) {
            case "list":
                // Use the new method to get users by role
                $fetchResults = self::getAllUsersForChat($userId, $role);
                break;
            case "fetch_thread":
                $fetchResults = self::$wpdb->get_results(
                    "SELECT * FROM $privateChat
                    WHERE 
                        ($privateChat.sender_id = $userId 
                    AND 
                        $privateChat.receiver_id = $receiverID) 
                    OR 
                        ($privateChat.sender_id = $receiverID 
                    AND 
                        $privateChat.receiver_id = $userId) 
                    ", ARRAY_A
                );
                break;
		case "fetch_thread_last_items":
    $total = 10;
    $limit = $offset * $total;
    
    // Improved query to properly load older messages with proper ordering
    $fetchResults = self::$wpdb->get_results(
        "SELECT * FROM $privateChat 
        WHERE 
            (sender_id = $userId AND receiver_id = $receiverID) 
            OR 
            (sender_id = $receiverID AND receiver_id = $userId) 
        ORDER BY id DESC 
        LIMIT $limit, $total",
        ARRAY_A
    );
    
    // Reverse the array to maintain chronological order
    $fetchResults = array_reverse($fetchResults);
    break;
            case "fetch_interval_thread":
                $fetchResults = self::$wpdb->get_results(
                    "SELECT * FROM $privateChat
                    WHERE ($privateChat.sender_id = $userId 
                        AND $privateChat.receiver_id = $receiverID)
                    OR ($privateChat.sender_id = $receiverID 
                        AND $privateChat.receiver_id = $userId)
                    ORDER BY $privateChat.id ASC
                    ", ARRAY_A
                );
                break;
            case "set_thread_status":
                self::$wpdb->update(
                    $privateChat,
                    array("status" => intval(0)),
                    array(
                        "sender_id" => stripslashes_deep($receiverID),
                        "receiver_id" => stripslashes_deep($userId),
                        "status" => intval(1)
                    )
                );
                break;
            case "insert_msg":
                
                self::$wpdb->insert($privateChat, $data);
                return self::$wpdb->insert_id;
                break;
            case "fetch_recent_thread":
                $fetchResults = self::$wpdb->get_row(
                    "SELECT * FROM
                    $privateChat
                    WHERE $privateChat.id = $msgID", ARRAY_A
                );
                break;
            case "count_unread_msgs":
                $fetchResults = self::$wpdb->get_var(
                    "SELECT count(*) AS unread FROM $privateChat where $privateChat.receiver_id = $userId and status = 1"
                );
                break;
			 case "count_unread_msgs_by_user":
                $fetchResults = self::$wpdb->get_var(
                    "SELECT count(*) AS unread FROM $privateChat 
                    WHERE $privateChat.sender_id =  $receiverID
                    AND $privateChat.receiver_id = $userId
                    AND $privateChat.status = 1"
                );
                break;
            case "delete_thread_msg":
                self::$wpdb->delete($privateChat, $data);
                break;
            }
            
            return $fetchResults;
        }
		
        /**
         * Fetch User Threads - Modified with updated permissions
         *
         * @param string $userId
         * @return void
         */
        public static function fetchUserThreads($userId = '')
        {
            ob_start();
            // Get available filters based on user role
            $available_filters = self::getAvailableFilters($userId);
            $current_user_role = self::getCurrentUserRole($userId);
            
            // Load users based on role restrictions
            $allUsers = self::getAllUsersForChat($userId, '');
            $chat_active_user   = isset($_GET['id']) ? $_GET['id'] : '';
            
            // Set default filter to the first available one
            $current_filter = !empty($available_filters[0]) ? $available_filters[0] : '';
            ?>
            <ul>
               <li>							
    <!-- Search Box - Always show for all users -->
    <div class="dc-chat-filter-buttons">
        <div class="dc-formtheme dc-formsearch">
            <fieldset>
                <div class="form-group">
                    <input type="text" autocomplete="off" name="fullname" class="form-control dc-filter-users" placeholder="<?php esc_html_e('Search Users', 'doccure_core'); ?>">
                    <a href="javascript:;" class="dc-searchgbtn"><i class="fa fa-search"></i></a>
                </div>
            </fieldset>
        </div>
        
        <!-- Filter Buttons - Only show if multiple filters available -->
        <?php if (count($available_filters) > 1): ?>
        <div class="dc-filter-buttons-group">
            <?php 
            // Show available filter buttons
            foreach($available_filters as $filter): 
                $active_class = $current_filter === $filter ? 'active' : '';
                $display_name = '';
                switch($filter) {
                    case 'doctor': 
                        $display_name = esc_html__('Doctors', 'doccure_core');
                        break;
                    case 'staff': 
                        $display_name = esc_html__('Staff', 'doccure_core'); 
                        break;
                    case 'patient': 
                        $display_name = esc_html__('Patients', 'doccure_core'); 
                        break;
                }
            ?>
            <button type="button" class="dc-filter-btn <?php echo esc_attr($active_class); ?>" data-filter="<?php echo esc_attr($filter); ?>">
                <i class=""></i>
                <?php echo $display_name; ?>
            </button>
            <?php endforeach; ?>
        </div>
        <?php endif; ?>
    </div>
    
    <div class="dc-verticalscrollbar dc-dashboardscrollbar lore" id="chat-users-list">
        <?php
            if ( !empty( $allUsers ) ) { 
                foreach ( $allUsers as $user ) {
                    
                    $user_id = $user['user_id'];
                    $unreadNotifyClass  = '';

                    // Check for unread messages
                    $unread_count = self::getUsersThreadListData($userId, $user_id, 'count_unread_msgs_by_user');
                    if ($unread_count > 0) {
                        $unreadNotifyClass = 'dc-dotnotification';
                    }

                    $userAvatar = self::getUserInfoData('avatar', $user_id, array('width' => 100, 'height' => 100));
                    $userName   = self::getUserInfoData('username', $user_id, array());
                    $userUrl    = self::getUserInfoData('url', $user_id, array());
                    $userRole   = self::getUserRole($user_id);
                    
                    // Get last message if exists
                    $last_message = !empty($user['last_message']) ? $user['last_message'] : __('No messages yet', 'doccure_core');
                    $last_message_id = !empty($user['last_message_id']) ? $user['last_message_id'] : 0;
                    
                    // For all users, group doctors and doctors_staff under 'doctor' filter
                    $filter_role = $userRole;
                    if ($userRole === 'doctors_staff') {
                        $filter_role = 'doctor';
                    }
                    // For staff and patients, also group doctors and doctors_staff under 'doctor' filter
                    if (in_array($current_user_role, array('staff', 'patient')) && $userRole === 'doctor') {
                        $filter_role = 'doctor';
                    }
                    ?>
                    <div class="dc-ad dc-load-chat <?php echo esc_attr($unreadNotifyClass); ?> user-role-<?php echo esc_attr($userRole); ?> filter-role-<?php echo esc_attr($filter_role); ?>" 
                         id="load-user-chat-<?php echo intval($user_id); ?>" 
                         data-userid="<?php echo intval($user_id); ?>" 
                         data-currentid="<?php echo intval($userId); ?>" 
                         data-msgid="<?php echo intval($last_message_id); ?>" 
                         data-img="<?php echo esc_url($userAvatar); ?>" 
                         data-name="<?php echo esc_attr($userName); ?>" 
                         data-url="<?php echo esc_url($userUrl); ?>"
                         data-role="<?php echo esc_attr($userRole); ?>">
                        <figure>
                            <img src="<?php echo esc_url($userAvatar); ?>" alt="<?php echo esc_attr($userName); ?>">
                            <?php echo do_action('doccure_print_user_status',$user_id);?>
                        </figure>
                        <div class="dc-adcontent">
                            <h3>
                                <?php echo esc_attr($userName); ?>
                                <span>
                                    <?php 
                                    switch($userRole) {
                                        case 'doctor': esc_html_e('(Doctor)', 'doccure_core'); break;
                                        case 'staff': esc_html_e('(Staff)', 'doccure_core'); break;
                                        case 'doctors_staff': esc_html_e('(Doctor Staff)', 'doccure_core'); break;
                                        case 'patient': esc_html_e('(Patient)', 'doccure_core'); break;
                                        default: esc_html_e('(User)', 'doccure_core'); break;
                                    }
                                    ?>
                                </span>
                            </h3>
                            <span class="list-last-message">
                                <?php 
                                if (!empty($user['last_message'])) {
                                    echo wp_trim_words($user['last_message'], 10);
                                } else {
                                    echo '<em>' . esc_html__('Start a conversation', 'doccure_core') . '</em>';
                                }
                                ?>
                            </span>
                        </div>
                        <em class="dcunread-count"><?php echo intval($unread_count); ?></em>
                    </div>	
                <?php 
                }
            } else {
                $no_users_message = '';
                switch($current_user_role) {
                    case 'doctor':
                        $no_users_message = esc_html__('No users available to chat with.', 'doccure_core');
                        break;
                    case 'staff':
                        $no_users_message = esc_html__('No users available to chat with.', 'doccure_core');
                        break;
                    case 'doctors_staff':
                        $no_users_message = esc_html__('No users available to chat with.', 'doccure_core');
                        break;
                    case 'patient':
                        $no_users_message = esc_html__('No doctors available to chat with.', 'doccure_core');
                        break;
                    default:
                        $no_users_message = esc_html__('No users found to chat with.', 'doccure_core');
                        break;
                }
                echo '<p class="dc-no-users">' . $no_users_message . '</p>';
            }
        ?>
    </div>
</li>
                <li>
                    <div class="dc-chatarea load-dc-chat-message">
                        <div class="dc-chatarea dc-chatarea-empty">
                            <figure class="dc-chatemptyimg">
                                <img src="<?php echo esc_url(get_template_directory_uri() . '/assets/images/message-img.png'); ?>" alt="<?php esc_attr_e('No Message Selected', 'doccure_core'); ?>">
                                <figcaption>
                                    <h3><?php esc_html_e('No message selected to display', 'doccure_core'); ?></h3>
                                </figcaption>
                            </figure>
                        </div>
                    </div>
                </li>
            </ul>

            <script type="text/javascript">
            jQuery(document).ready(function($) {
                <?php if (count($available_filters) > 1): ?>
                // Filter button click handler (only when multiple filters available)
                $('.dc-filter-btn').on('click', function() {
                    var filter = $(this).data('filter');
                    
                    // Remove active class from all buttons
                    $('.dc-filter-btn').removeClass('active');
                    // Add active class to clicked button
                    $(this).addClass('active');
                    
                    // Hide all users first
                    $('.dc-load-chat').hide();
                    // Show only users with the selected role
                    $('.filter-role-' + filter).show();
                    
                    // Update no users message
                    updateNoUsersMessage();
                });
                
                // Function to update no users message
                function updateNoUsersMessage() {
                    var visibleUsers = $('.dc-load-chat:visible').length;
                    if (visibleUsers === 0) {
                        if ($('.dc-no-users').length === 0) {
                            $('#chat-users-list').append('<p class="dc-no-users"><?php echo esc_js(__('No users found for this filter.', 'doccure_core')); ?></p>');
                        }
                    } else {
                        $('.dc-no-users').remove();
                    }
                }
                
                // Initialize filter state - show only users for the active filter
                $('.dc-filter-btn.active').trigger('click');
                <?php else: ?>
                // For users with only one filter option, show all available users
                $('.dc-load-chat').show();
                <?php endif; ?>
            });
            </script>
            <?php
            if(!empty($chat_active_user)){
                $script = "
                jQuery(window).on('load', function() {
                        jQuery('#load-user-chat-".esc_js($chat_active_user)."').trigger('click'); 
                    }); 
                    
                    ";
                wp_add_inline_script( 'doccure-dashboard', $script, 'before' );
            }
            echo ob_get_clean();
        }
        
		/**
         * Fetch Single User Threads
         *
         * @param string $userId
         * @return void
         */
        public static function fetchSingleUserThreads($userId = '',$recived_id = '') {
            ob_start();
			
            $usersThreadUserList 	= self::getUsersThreadListData( $userId, $recived_id, 'fetch_thread', array(), '');
			if ( !empty( $usersThreadUserList ) ) { 
				foreach ( $usersThreadUserList as $userVal ) { 
					$unreadNotifyClass  = 'dc-offerermessage';
					$chat_user_id 		= '';
					if ( $recived_id === intval($userVal['sender_id']) ) {
						$unreadNotifyClass = 'dc-memessage dc-readmessage';
					} 

					$chat_user_id = intval($userVal['sender_id']);

					$message_date	= !empty($userVal['time_gmt']) ?  date(get_option('date_format'), strtotime($userVal['time_gmt'])) : '';

					$userAvatar = self::getUserInfoData('avatar', $chat_user_id, array('width' => 100, 'height' => 100));
					$userName 	= self::getUserInfoData('username', $chat_user_id, array());
					$userUrl 	= self::getUserInfoData('url', $chat_user_id, array());
					$count 		= self::getUsersThreadListData($chat_user_id,$userId,'count_unread_msgs_by_user');
					$unread		= !empty( $count ) ? $count : 0;
					?>
					<div class="<?php echo esc_attr( $unreadNotifyClass );?>">
						<?php if( !empty( $userAvatar ) ){?>
							<figure><img src="<?php echo esc_url( $userAvatar );?>" alt="<?php echo esc_attr( $userName );?>"></figure>
						<?php } ?>
						<div class="dc-description">
							<p><?php echo do_shortcode($userVal['chat_message']); ?></p>
							<div class="clearfix"></div>
							<time datetime="<?php echo esc_attr( $userVal['time_gmt'] );?>"><?php echo esc_html( $message_date );?></time>
						</div>
					</div>
			<?php }
			}
            echo ob_get_clean();
        }

        /**
         * Fetch User Conversation
         *
         * @return void
         */
        public static function fetchUserConversation()
        {
            $json = array();
            
            if( function_exists('doccure_validate_user') ) { 
                doccure_validate_user();	
            };

            //security check
            $do_check = check_ajax_referer('ajax_nonce', 'security', false);
            if ( $do_check == false ) {
                $json['type'] = 'error';
                $json['message'] = esc_html__('No Kiddies Please', 'doccure_core');
                wp_send_json( $json );
            }
            
            $senderID       = !empty( $_POST['current_id'] ) ? intval( $_POST['current_id'] ) : '';
            $receiverID     = !empty( $_POST['user_id'] ) ? intval( $_POST['user_id'] ) : '';
            $thread_page    = !empty( $_POST['thread_page'] ) ? intval( $_POST['thread_page'] ) : 0;
            $current_oldest_id = !empty( $_POST['current_oldest_id'] ) ? intval( $_POST['current_oldest_id'] ) : 0;
            
            if (!empty($_POST) && $receiverID != $senderID ) {

                $usersThreadData = self::getUsersThreadListData($senderID, $receiverID, 'fetch_thread_last_items', array(), '', $thread_page);
                
                //Prepare Chat Nodes
                $chat_nodes = array();
                $new_oldest_id = 0;

                if (!empty($usersThreadData)) {
                    //Update Chat Status in DB only if there are messages
                    self::getUsersThreadListData($senderID, $receiverID, 'set_thread_status', array(), '');
                    
                    // Get the oldest message ID from the current batch
                    $new_oldest_id = $usersThreadData[0]['id'];
                    
                    foreach ($usersThreadData as $key => $val) {
                        // Clear identification of sender
                        $chat_nodes[$key]['chat_is_sender'] = 'no';
                        if (intval($val['sender_id']) === intval($senderID)) {
                            $chat_nodes[$key]['chat_is_sender'] = 'yes';
                        }

                        $date = !empty($val['time_gmt']) ? date_i18n(get_option('date_format'), strtotime($val['time_gmt'])) : '';
                        $chat_nodes[$key]['chat_avatar']           = self::getUserInfoData('avatar', $val['sender_id'], array('width' => 100, 'height' => 100));
                        $chat_nodes[$key]['chat_username']         = self::getUserInfoData('username', $val['sender_id'], array());
                        $chat_nodes[$key]['chat_message']          = html_entity_decode(stripslashes($val['chat_message']), ENT_QUOTES);
                        $chat_nodes[$key]['chat_date']             = $date;
                        $chat_nodes[$key]['chat_id']               = intval($val['id']);
                        $chat_nodes[$key]['chat_current_user_id']  = intval($senderID);
                    }
                }

                //Create Chat Sidebar Data
                $chat_sidebar = array();
                $chat_sidebar['avatar']         = self::getUserInfoData('avatar', $receiverID, array('width' => 100, 'height' => 100));
                $chat_sidebar['username']       = self::getUserInfoData('username', $receiverID, array());
                $chat_sidebar['user_register']  = self::getUserInfoData('user_register', $receiverID, array());

                $json['type']                   = 'success';
                $json['chat_nodes']             = $chat_nodes;
                $json['chat_receiver_id']       = intval($receiverID);
                $json['chat_sender_id']         = intval($senderID);
                $json['chat_sidebar']           = $chat_sidebar;
                $json['current_oldest_id']      = $new_oldest_id;
                $json['message']                = !empty($chat_nodes) ? esc_html__('Chat Messages Found!', 'doccure_core') : esc_html__('Start a new conversation', 'doccure_core');
                $json['thread_page']            = $thread_page + 1;
                
                wp_send_json($json);
                
            } else {
                $json['type']       = 'error';
                $json['message'] = esc_html__('Security check failed!', 'doccure_core');
                wp_send_json($json);
            }
        }

        /**
         * Send user message function with permission validation
         *
         * @return void
         */
        public static function sendUserMessage() 
		{
            global $current_user,$doccure_options;
            $json = array();
			
			if( function_exists('doccure_is_demo_site') ) { 
                doccure_is_demo_site() ;
            }; //if demo site then prevent
			
			if( function_exists('doccure_validate_user') ) { 
				doccure_validate_user();
			}; //if user is logged in

			//security check
			$do_check = check_ajax_referer('ajax_nonce', 'security', false);
			if ( $do_check == false ) {
				$json['type'] = 'error';
				$json['message'] = esc_html__('Security check failed, this could be because of your browser cache. Please clear the cache and check it againe', 'doccure_core');
				wp_send_json( $json );
			}
			
			$senderId   	= $current_user->ID;
			
			
			$receiver_id	= !empty( $_POST['receiver_id'] ) ? intval($_POST['receiver_id']) : '';
            $status			= !empty( $_POST['status'] ) && esc_attr( $_POST['status'] ) === 'read' ? 0 : 1;
            $msg_type		= !empty( $_POST['msg_type'] ) && esc_attr( $_POST['msg_type'] ) === 'modal' ? 'modal' : 'normals';
			$message		= !empty( $_POST['message'] ) ? esc_textarea($_POST['message']) : '';

            if (empty($receiver_id)) {
                $json['type'] = 'error';
                $json['message'] = esc_html__('Security check failed!', 'doccure_core');
                wp_send_json($json);
            }

            // Validate chat permissions before sending
            if (!self::validateChatPermission($senderId, $receiver_id)) {
                $json['type'] = 'error';
                $json['message'] = esc_html__('You are not allowed to chat with this user.', 'doccure_core');
                wp_send_json($json);
            }

            if ( intval( $receiver_id ) === intval( $current_user->ID ) ) {
                $json['type'] = 'error';
                $json['message'] = esc_html__('Something went wrong.', 'doccure_core');
                wp_send_json($json);
            }

            if (empty($message)) {
                $json['type'] = 'error';
                $json['message'] = esc_html__('Message field is required.', 'doccure_core');
                wp_send_json($json);
            }
           
            $receiverId = intval($receiver_id);

            //Prepare Insert Message Data Array
            $current_time  = current_time('mysql');
            $gmt_time      = get_gmt_from_date($current_time);
						
			
            $insert_data = array(
                'sender_id' 		=> $senderId,
                'receiver_id' 		=> $receiverId,
                'chat_message' 		=> $message,
                'status' 			=> $status,
                'timestamp' 		=> time(),
                'time_gmt' 			=> $gmt_time,
            );

            $msg_id = self::getUsersThreadListData($senderId, $receiverId, 'insert_msg', $insert_data, '');

			$receiver_chat_notify = !empty($doccure_options['chat_notify_enable']) ? $doccure_options['chat_notify_enable'] : 'no';

			if (class_exists('doccure_Email_helper') && $receiver_chat_notify === 'yes') {
				if (class_exists('doccureRecChatNotification')) {
					$email_helper = new doccureRecChatNotification();
					$emailData 	  = array();

					$sender_id  	= doccure_get_linked_profile_id($senderId);
					$receiver_id	= doccure_get_linked_profile_id($receiverId);

					$emailData['username'] 		        = get_the_title($receiver_id);
					$emailData['sender_name'] 		    = get_the_title($sender_id);
					$emailData['message']      			= !empty($message) ? $message : '';
					$emailData['email_to']      		= get_userdata($receiverId)->user_email;

					$email_helper->send_chat_notification($emailData);
				}
			}
			
            if (!empty($msg_id)) {
                $fetchRecentThread = self::getUsersThreadListData('', '', 'fetch_recent_thread', array(), $msg_id);

                $message = !empty( $fetchRecentThread['chat_message'] ) ?  $fetchRecentThread['chat_message'] : '';
                $date = !empty($fetchRecentThread['time_gmt']) ? date_i18n(get_option('date_format'), strtotime($fetchRecentThread['time_gmt'])) : '';
                $chat_nodes[0]['chat_avatar'] 		= self::getUserInfoData('avatar', $fetchRecentThread['sender_id'], array('width' => 100, 'height' => 100));
                $chat_nodes[0]['chat_username'] 	= self::getUserInfoData('username', $fetchRecentThread['sender_id'], array());
                $chat_nodes[0]['chat_message'] 		= html_entity_decode( stripslashes($message),ENT_QUOTES );
                $chat_nodes[0]['chat_date'] 		= $date;
                $chat_nodes[0]['chat_id'] 			= intval($fetchRecentThread['id']);
                $chat_nodes[0]['chat_current_user_id'] = intval($senderId);
                $chat_nodes[0]['chat_is_sender'] = 'yes';
				
				//excerpt
				if (strlen($message) > 40) {
					$message = substr($message, 0, 40);
				}

                $json['type'] 			= 'success';
                $json['msg_type']       = $msg_type;
                $json['chat_nodes'] 	= $chat_nodes;
				
				$chat_nodes[0]['chat_is_sender']   	=  'no';
                $json['chat_nodes_receiver'] 		= $chat_nodes;
				$json['chat_receiver_id'] 			= intval($receiverId);
				$json['chat_sender_id'] 			= intval($senderId);
				$json['last_id'] 					= intval($msg_id);
				
                $json['replace_recent_msg_user'] = self::getUserInfoData('username', $fetchRecentThread['receiver_id']);
                $json['replace_recent_msg'] = $message;
                $json['message'] = esc_html__('Message send!', 'doccure_core');

                wp_send_json($json);
            }
            
        }

        /**
         * Get Interval Chat History
         *
         * @return void
         */
        public static function getIntervalChatHistoryData()
        {
            $json = array();
			
			if( function_exists('doccure_validate_user') ) { 
				doccure_validate_user();
			}; //if user is logged in

			//security check
			$do_check = check_ajax_referer('ajax_nonce', 'security', false);
			if ( $do_check == false ) {
				$json['type'] = 'error';
				$json['message'] = esc_html__('No Kiddies Please', 'doccure_core');
				wp_send_json( $json );
			}
			
			$senderID	= !empty( $_POST['sender_id'] ) ? intval($_POST['sender_id']) : '';
			$receiverID	= !empty( $_POST['receiver_id'] ) ? intval($_POST['receiver_id']) : '';
			$lastMsgId	= !empty( $_POST['last_msg_id'] ) ? intval($_POST['last_msg_id']) : '';
			
            if ( !empty($_POST) && $senderID != $receiverID ) {
                $usersThreadData = self::getUsersThreadListData($senderID, $receiverID, 'fetch_interval_thread', array(), '');

                $chat_nodes = array();
				
                $last_id 	= '';
				$newchat    = false; 
				$last_message = '';
                if (!empty($usersThreadData)) {
                    foreach ($usersThreadData as $key => $val) {
                        $last_id = intval( $val['id'] );
						$newchat = true;

						//Update Chat Status in DB
						self::getUsersThreadListData($senderID, $receiverID, 'set_thread_status', array(), '');

						$chat_nodes[$key]['chat_is_sender'] 	= 'no';

						if ($val['sender_id'] == $senderID) {
							$chat_nodes[$key]['chat_is_sender'] = 'yes';
						}

						$date = !empty($val['time_gmt']) ? date_i18n(get_option('date_format'), strtotime($val['time_gmt'])) : '';
						$chat_nodes[$key]['chat_avatar'] 		= self::getUserInfoData('avatar', $val['sender_id'], array('width' => 100, 'height' => 100));
						$chat_nodes[$key]['chat_username'] 		= self::getUserInfoData('username', $val['sender_id'], array());
						$chat_nodes[$key]['chat_message'] 		= html_entity_decode( stripslashes($val['chat_message']),ENT_QUOTES );
						$chat_nodes[$key]['chat_date'] 			= $date;
						$chat_nodes[$key]['chat_id'] 			= intval($val['id']);
						$chat_nodes[$key]['chat_current_user_id'] = intval($senderID);

						$last_message = $val['chat_message'];
                    }
					
					if( $newchat ){
						$json['type'] 		= 'success';
					} else{
						$json['type']       = 'error';
					}
                    
					//excerpt
					if (strlen($last_message) > 40) {
						$last_message = substr($last_message, 0, 40);
					}
					
					
                    $json['chat_nodes'] 	= $chat_nodes;
                    $json['last_id'] 		= intval( $last_id );
                    $json['receiver_id'] 	= $receiverID;
					$json['last_message'] 	= $last_message;
                    $json['message'] 		= esc_html__('Chat messages found!', 'doccure_core');
                    wp_send_json($json);
                }

            } else {
                $json['type']       = 'error';
                $json['message'] = esc_html__('Security check failed!', 'doccure_core');
                wp_send_json($json);
            }
        }

        /**
         * Delete chat message function
         *
         * @return void
         */
        public static function deleteChatMessage()
        {
            global $current_user;  
            $json = array();
			
			if( function_exists('doccure_validate_user') ) { 
				doccure_validate_user();
			}; //if user is logged in

			//security check
			$do_check = check_ajax_referer('ajax_nonce', 'security', false);
			if ( $do_check == false ) {
				$json['type'] = 'error';
				$json['message'] = esc_html__('No Kiddies Please', 'doccure_core');
				wp_send_json( $json );
			}
			
			$senderID      = !empty( $_POST['user_id'] ) ? intval($_POST['user_id']) : '';  
            $messageID     = !empty( $_POST['msgid'] ) ? intval($_POST['msgid']) : '';
			
            //Validation
            if ( empty($senderID) || empty($messageID) ) {
                $json['type'] = 'error';
                $json['message'] = esc_html__('Something went wrong.', 'doccure_core');
                wp_send_json($json);
            }     


            //Check if valid User sent
            if ( $current_user->ID !== $senderID ) {
                $json['type'] 		= 'error';
                $json['message'] 	= esc_html__('Security check failed!', 'doccure_core');
                wp_send_json($json);
            }

            //Delete Thread Message
            $delete_array_data = array(
                "id"            => $messageID,
                "sender_id"     => $senderID                 
            );

            self::getUsersThreadListData($senderID, '', 'delete_thread_msg', $delete_array_data, $messageID);

            //Response
            $json['type']    = 'success';
            $json['message'] = esc_html__('Message deleted.', 'doccure_core');
            wp_send_json($json); 
        }

        /**
         * Get User Information
         *
         * @param string $type
         * @param string $userID
         * @return void
         */
        public static function getUserInfoData($type = '', $userID = '', $sizes = array()) 
        {
            $userinfo = '';
            $user_data = get_userdata($userID);
			$postId = doccure_get_linked_profile_id($userID);

            switch ($type) {
				case "avatar":
					
					if ( apply_filters('doccure_get_user_type', $userID) === 'doctors' ) {
						$userinfo = apply_filters('doccure_doctor_avatar_fallback', doccure_get_doctor_avatar($sizes, $postId), $sizes);
					} 
                    else {
						$userinfo = apply_filters('doccure_doctor_avatar_fallback', doccure_get_others_avatar($sizes, $postId), $sizes);
					}

					break;
				case "username":
					$userinfo = doccure_get_username($userID);
					break;
				case "user_register":
					$userinfo = esc_html__('Member Since','doccure_core').'&nbsp;'.date(get_option('date_format'), strtotime($user_data->user_registered));
					break;
				case "url":
					$userinfo = get_the_permalink($postId);
					break;
            }

            return $userinfo;
        }
		
		/**
         * Get User Information
         *
         * @param string $type
         * @param string $userID
         * @return void
         */
        public static function countUnreadMessages($userID = '',$return = 'no') 
        {
            $users_unread = self::getUsersThreadListData($userID,'','count_unread_msgs');
			if(!empty($return) && $return === 'yes' ){
				return !empty( $users_unread ) ? $users_unread  : 0;
			}
			
            echo !empty( $users_unread ) ? $users_unread  : 0;
        }
    }
	
    ChatSystem::instance();
    
}