<?php

/**
 * Plugin Name: Clicks User Manager
 * Plugin URI:  https://clicks.com.pk/clicks-user-manager
 * Description: Advanced WordPress user management — bulk delete, filter, export, and mail users from one clean dashboard.
 * Version:     1.2.0
 * Author:      Clicks - Digital Marketing & Software Agency
 * Author URI:  https://clicks.com.pk
 * License:     GPL v2
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain: clicks-user-manager
 * Domain Path: /languages
 */
if ( !defined( 'ABSPATH' ) ) {
    exit;
}
if ( function_exists( 'cum_fs' ) ) {
    cum_fs()->set_basename( false, __FILE__ );
} else {
    // DO NOT REMOVE THIS IF, IT IS ESSENTIAL FOR THE `function_exists` CALL ABOVE TO PROPERLY WORK.
    if ( !function_exists( 'cum_fs' ) ) {
        // Create a helper function for easy SDK access.
        function cum_fs() {
            global $cum_fs;
            if ( !isset( $cum_fs ) ) {
                // Include Freemius SDK.
                require_once dirname( __FILE__ ) . '/vendor/freemius/start.php';
                $cum_fs = fs_dynamic_init( array(
                    'id'               => '32474',
                    'slug'             => 'clicks-user-manager',
                    'type'             => 'plugin',
                    'public_key'       => 'pk_6771eff174cd11459884876fb5017',
                    'is_premium'       => false,
                    'premium_suffix'   => 'Pro',
                    'has_addons'       => false,
                    'has_paid_plans'   => true,
                    'is_org_compliant' => true,
                    'menu'             => array(
                        'slug'    => 'clicks-user-manager',
                        'support' => false,
                    ),
                    'is_live'          => true,
                ) );
            }
            return $cum_fs;
        }

        // Init Freemius.
        cum_fs();
        // Signal that SDK was initiated.
        do_action( 'cum_fs_loaded' );
    }
    // Plugin constants
    define( 'WPUM_VERSION', '1.2.0' );
    define( 'WPUM_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
    define( 'WPUM_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
    define( 'WPUM_PLUGIN_FILE', __FILE__ );
    // Development flag to test Pro features. Set to false to test Free limits.
    if ( !defined( 'WPUM_FORCE_PRO' ) ) {
        define( 'WPUM_FORCE_PRO', false );
    }
    /**
     * Check if the Pro version features should be unlocked.
     *
     * @return bool True if licensed or forced.
     */
    function wpum_is_pro() {
        if ( defined( 'WPUM_FORCE_PRO' ) && WPUM_FORCE_PRO ) {
            return true;
        }
        if ( function_exists( 'cum_fs' ) ) {
            return cum_fs()->can_use_premium_code();
        }
        return false;
    }

    // Include admin files
    require_once WPUM_PLUGIN_DIR . 'admin/filters.php';
    require_once WPUM_PLUGIN_DIR . 'admin/export.php';
    require_once WPUM_PLUGIN_DIR . 'admin/users-page.php';
    require_once WPUM_PLUGIN_DIR . 'admin/notes.php';
    require_once WPUM_PLUGIN_DIR . 'admin/segments.php';
    require_once WPUM_PLUGIN_DIR . 'admin/impersonate.php';
    require_once WPUM_PLUGIN_DIR . 'admin/scheduling.php';
    /**
     * Main plugin class.
     */
    class WPUM_Plugin {
        /**
         * Constructor.
         */
        public function __construct() {
            add_action( 'admin_menu', array($this, 'register_admin_menu') );
            add_action( 'admin_enqueue_scripts', array($this, 'enqueue_assets') );
            add_action( 'wp_dashboard_setup', array($this, 'register_dashboard_widget') );
            add_action(
                'wp_login',
                array($this, 'track_last_login'),
                10,
                2
            );
            add_action( 'wp_ajax_wpum_bulk_action', array($this, 'handle_bulk_action') );
            add_action( 'wp_ajax_wpum_bulk_mail', array($this, 'handle_bulk_mail') );
            add_action( 'wp_ajax_wpum_export_csv', array($this, 'handle_export_csv') );
            add_action( 'wp_ajax_wpum_get_quick_edit', array($this, 'handle_get_quick_edit') );
            add_action( 'wp_ajax_wpum_save_quick_edit', array($this, 'handle_save_quick_edit') );
            if ( wpum_is_woocommerce_active() ) {
                add_action( 'woocommerce_order_status_changed', array($this, 'clear_order_count_cache') );
                add_action( 'woocommerce_new_order', array($this, 'clear_order_count_cache') );
                add_action( 'woocommerce_update_order', array($this, 'clear_order_count_cache') );
                add_action( 'woocommerce_trash_order', array($this, 'clear_order_count_cache') );
            }
        }

        /**
         * Register admin menu and submenus.
         */
        public function register_admin_menu() {
            add_menu_page(
                __( 'Clicks User Manager', 'clicks-user-manager' ),
                __( 'Clicks User Manager', 'clicks-user-manager' ),
                'manage_options',
                'clicks-user-manager',
                'wpum_render_users_page',
                'dashicons-groups',
                72
            );
            add_submenu_page(
                'clicks-user-manager',
                __( 'All Users', 'clicks-user-manager' ),
                __( 'All Users', 'clicks-user-manager' ),
                'manage_options',
                'clicks-user-manager',
                'wpum_render_users_page'
            );
            add_submenu_page(
                'clicks-user-manager',
                __( 'Export Users', 'clicks-user-manager' ),
                __( 'Export Users', 'clicks-user-manager' ),
                'manage_options',
                'clicks-user-manager-export',
                'wpum_render_export_page'
            );
            add_submenu_page(
                'clicks-user-manager',
                __( 'About', 'clicks-user-manager' ),
                __( 'About', 'clicks-user-manager' ),
                'manage_options',
                'clicks-user-manager-about',
                array($this, 'render_about_page')
            );
        }

        /**
         * Enqueue plugin assets.
         *
         * @param string $hook Current admin page hook.
         */
        public function enqueue_assets( $hook ) {
            $pages = array('toplevel_page_clicks-user-manager', 'clicks-user-manager_page_clicks-user-manager-export', 'clicks-user-manager_page_clicks-user-manager-about');
            if ( !in_array( $hook, $pages, true ) ) {
                return;
            }
            wp_enqueue_style(
                'wpum-style',
                WPUM_PLUGIN_URL . 'assets/style.css',
                array(),
                WPUM_VERSION
            );
            wp_enqueue_script(
                'wpum-script',
                WPUM_PLUGIN_URL . 'assets/script.js',
                array('jquery'),
                WPUM_VERSION,
                true
            );
            wp_localize_script( 'wpum-script', 'wpum_ajax', array(
                'ajax_url'              => admin_url( 'admin-ajax.php' ),
                'nonce'                 => wp_create_nonce( 'wpum_nonce' ),
                'confirm_delete'        => __( 'Are you sure you want to delete these users? This cannot be undone.', 'clicks-user-manager' ),
                'confirm_delete_single' => __( 'Are you sure you want to delete this user? This cannot be undone.', 'clicks-user-manager' ),
                'select_users'          => __( 'Please select at least one user.', 'clicks-user-manager' ),
                'select_action'         => __( 'Please select a bulk action.', 'clicks-user-manager' ),
                'select_role'           => __( 'Please select a role for bulk role change.', 'clicks-user-manager' ),
                'mail_subject_required' => __( 'Please enter an email subject.', 'clicks-user-manager' ),
                'mail_message_required' => __( 'Please enter an email message.', 'clicks-user-manager' ),
                'processing'            => __( 'Processing…', 'clicks-user-manager' ),
                'sending'               => __( 'Sending emails…', 'clicks-user-manager' ),
                'is_pro'                => wpum_is_pro(),
            ) );
        }

        /**
         * Track last login time.
         *
         * @param string  $user_login Username.
         * @param WP_User $user       User object.
         */
        public function track_last_login( $user_login, $user ) {
            update_user_meta( $user->ID, '_wpum_last_login', current_time( 'mysql' ) );
        }

        /**
         * Register dashboard widget.
         */
        public function register_dashboard_widget() {
            wp_add_dashboard_widget( 'wpum_dashboard_widget', __( 'User Management Stats', 'clicks-user-manager' ), array($this, 'render_dashboard_widget') );
        }

        /**
         * Render dashboard widget.
         */
        public function render_dashboard_widget() {
            if ( !current_user_can( 'manage_options' ) ) {
                return;
            }
            $total_users = count_users();
            $all_roles = wp_roles()->roles;
            $new_this_month = $this->get_new_users_this_month();
            $inactive_count = $this->get_inactive_users_count( 30 );
            $never_logged = $this->get_never_logged_in_count();
            echo '<div class="wpum-widget">';
            // Total users.
            echo '<div class="wpum-widget-stat">';
            echo '<span class="wpum-stat-label">' . esc_html__( 'Total Users', 'clicks-user-manager' ) . '</span>';
            echo '<span class="wpum-stat-value">' . esc_html( number_format_i18n( $total_users['total_users'] ) ) . '</span>';
            echo '</div>';
            // New this month.
            echo '<div class="wpum-widget-stat">';
            echo '<span class="wpum-stat-label">' . esc_html__( 'New This Month', 'clicks-user-manager' ) . '</span>';
            echo '<span class="wpum-stat-value wpum-green">' . esc_html( number_format_i18n( $new_this_month ) ) . '</span>';
            echo '</div>';
            // Inactive 30 days.
            echo '<div class="wpum-widget-stat">';
            echo '<span class="wpum-stat-label">' . esc_html__( 'Inactive (30 days)', 'clicks-user-manager' ) . '</span>';
            echo '<span class="wpum-stat-value wpum-orange">' . esc_html( number_format_i18n( $inactive_count ) ) . '</span>';
            echo '</div>';
            // Never logged in.
            echo '<div class="wpum-widget-stat">';
            echo '<span class="wpum-stat-label">' . esc_html__( 'Never Logged In', 'clicks-user-manager' ) . '</span>';
            echo '<span class="wpum-stat-value wpum-red">' . esc_html( number_format_i18n( $never_logged ) ) . '</span>';
            echo '</div>';
            // Users by role bars.
            echo '<div class="wpum-widget-roles">';
            echo '<h4>' . esc_html__( 'Users by Role', 'clicks-user-manager' ) . '</h4>';
            $total = max( 1, $total_users['total_users'] );
            foreach ( $total_users['avail_roles'] as $role => $count ) {
                if ( 0 === $count ) {
                    continue;
                }
                $role_name = ( isset( $all_roles[$role]['name'] ) ? translate_user_role( $all_roles[$role]['name'] ) : $role );
                $pct = round( $count / $total * 100 );
                echo '<div class="wpum-role-bar-row">';
                echo '<span class="wpum-role-name">' . esc_html( $role_name ) . '</span>';
                echo '<div class="wpum-role-bar-wrap">';
                echo '<div class="wpum-role-bar" style="width:' . esc_attr( $pct ) . '%"></div>';
                echo '</div>';
                echo '<span class="wpum-role-count">' . esc_html( number_format_i18n( $count ) ) . '</span>';
                echo '</div>';
            }
            echo '</div>';
            // .wpum-widget-roles
            // ---- Premium Dashboard Analytics ----
            if ( !wpum_is_pro() ) {
                echo '<div class="wpum-pro-widget-lock" style="background:#f6f7f7; border:1px dashed #c3c4c7; padding:15px; margin-top:15px; text-align:center; border-radius:4px; position:relative;">';
                echo '<span style="font-size:24px; display:block; margin-bottom:5px;">📈</span>';
                echo '<strong>' . esc_html__( 'Unlock Registration & Activity Charts', 'clicks-user-manager' ) . '</strong>';
                echo '<p style="margin:5px 0 10px; font-size:11px; color:#646970;">' . esc_html__( 'Upgrade to Pro to view interactive trend lines, activity metrics, and WooCommerce revenue statistics.', 'clicks-user-manager' ) . '</p>';
                echo '<a href="' . esc_url( admin_url( 'admin.php?page=clicks-user-manager-about' ) ) . '" class="button button-primary button-small">' . esc_html__( 'Upgrade to Pro', 'clicks-user-manager' ) . '</a>';
                echo '</div>';
            } else {
                // 1. User Registrations Line Chart (SVG)
                global $wpdb;
                $days_data = array();
                for ($i = 14; $i >= 0; $i--) {
                    $date = gmdate( 'Y-m-d', strtotime( "-{$i} days" ) );
                    $days_data[$date] = 0;
                }
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                $results = $wpdb->get_results( $wpdb->prepare( "SELECT DATE(user_registered) as reg_date, COUNT(*) as count \n\t\t\t\t\t FROM {$wpdb->users} \n\t\t\t\t\t WHERE user_registered >= %s \n\t\t\t\t\t GROUP BY DATE(user_registered)", gmdate( 'Y-m-d 00:00:00', strtotime( '-14 days' ) ) ) );
                foreach ( $results as $row ) {
                    if ( isset( $days_data[$row->reg_date] ) ) {
                        $days_data[$row->reg_date] = (int) $row->count;
                    }
                }
                $max_val = max( 1, max( $days_data ) );
                $points = array();
                $x_step = 280 / 14;
                $idx = 0;
                foreach ( $days_data as $date => $val ) {
                    $x = $idx * $x_step;
                    $y = 70 - $val / $max_val * 50;
                    $points[] = "{$x},{$y}";
                    $idx++;
                }
                $polyline_points = implode( ' ', $points );
                echo '<div class="wpum-widget-analytics" style="margin-top: 15px; border-top: 1px solid #eee; padding-top: 15px;">';
                echo '<h4 style="margin: 0 0 8px 0;">' . esc_html__( 'Registration Trend (Last 15 Days)', 'clicks-user-manager' ) . '</h4>';
                echo '<div style="background: #fafafa; border: 1px solid #e5e5e5; padding: 10px; border-radius: 3px; margin-bottom: 15px;">';
                echo '<svg width="100%" height="80" viewBox="0 0 280 80" preserveAspectRatio="none" style="display:block; overflow:visible;">';
                // Grid lines
                echo '<line x1="0" y1="20" x2="280" y2="20" stroke="#f0f0f0" stroke-width="1" />';
                echo '<line x1="0" y1="45" x2="280" y2="45" stroke="#f0f0f0" stroke-width="1" />';
                echo '<line x1="0" y1="70" x2="280" y2="70" stroke="#e5e5e5" stroke-width="1" />';
                // Gradient fill
                echo '<defs>';
                echo '<linearGradient id="wpum-chart-grad" x1="0" y1="0" x2="0" y2="1">';
                echo '<stop offset="0%" stop-color="#2271b1" stop-opacity="0.3" />';
                echo '<stop offset="100%" stop-color="#2271b1" stop-opacity="0.0" />';
                echo '</linearGradient>';
                echo '</defs>';
                echo '<polygon points="0,70 ' . esc_attr( $polyline_points ) . ' 280,70" fill="url(#wpum-chart-grad)" />';
                // Trend line
                echo '<polyline points="' . esc_attr( $polyline_points ) . '" fill="none" stroke="#2271b1" stroke-width="2" />';
                // Dots at data points
                $idx = 0;
                foreach ( $days_data as $date => $val ) {
                    $x = $idx * $x_step;
                    $y = 70 - $val / $max_val * 50;
                    $tooltip = esc_attr( wp_date( 'M d', strtotime( $date ) ) . ': ' . $val . ' registrations' );
                    echo '<circle cx="' . esc_attr( $x ) . '" cy="' . esc_attr( $y ) . '" r="3" fill="#2271b1" stroke="#fff" stroke-width="1">';
                    echo '<title>' . $tooltip . '</title>';
                    echo '</circle>';
                    $idx++;
                }
                echo '</svg>';
                echo '</div>';
                // 2. Inactivity Breakdown Stacked Bar
                $active_users = $this->get_inactive_users_count_inverse( 30 );
                $inactive_30_90 = $this->get_inactive_users_range( 30, 90 );
                $dormant_90 = $this->get_inactive_users_count( 90 );
                $never_logged = $this->get_never_logged_in_count();
                $total_breakdown = max( 1, $active_users + $inactive_30_90 + $dormant_90 + $never_logged );
                $p_active = round( $active_users / $total_breakdown * 100 );
                $p_inactive = round( $inactive_30_90 / $total_breakdown * 100 );
                $p_dormant = round( $dormant_90 / $total_breakdown * 100 );
                $p_never = round( $never_logged / $total_breakdown * 100 );
                echo '<h4 style="margin: 0 0 8px 0;">' . esc_html__( 'User Activity Breakdown', 'clicks-user-manager' ) . '</h4>';
                echo '<div style="display:flex; height:12px; border-radius:6px; overflow:hidden; background:#eee; margin-bottom:10px;">';
                if ( $p_active > 0 ) {
                    echo '<div style="width:' . $p_active . '%; background:#2271b1;" title="Active"></div>';
                }
                if ( $p_inactive > 0 ) {
                    echo '<div style="width:' . $p_inactive . '%; background:#cca300;" title="Inactive"></div>';
                }
                if ( $p_dormant > 0 ) {
                    echo '<div style="width:' . $p_dormant . '%; background:#d54e21;" title="Dormant"></div>';
                }
                if ( $p_never > 0 ) {
                    echo '<div style="width:' . $p_never . '%; background:#72777c;" title="Never Logged In"></div>';
                }
                echo '</div>';
                // Legend
                echo '<div style="display:flex; flex-wrap:wrap; gap:8px 12px; font-size:11px; color:#50575e; margin-bottom:15px;">';
                echo '<div><span style="display:inline-block; width:8px; height:8px; border-radius:50%; background:#2271b1; margin-right:4px;"></span>Active: ' . $p_active . '%</div>';
                echo '<div><span style="display:inline-block; width:8px; height:8px; border-radius:50%; background:#cca300; margin-right:4px;"></span>Inactive: ' . $p_inactive . '%</div>';
                echo '<div><span style="display:inline-block; width:8px; height:8px; border-radius:50%; background:#d54e21; margin-right:4px;"></span>Dormant: ' . $p_dormant . '%</div>';
                echo '<div><span style="display:inline-block; width:8px; height:8px; border-radius:50%; background:#72777c; margin-right:4px;"></span>Never: ' . $p_never . '%</div>';
                echo '</div>';
                // 3. WooCommerce LTV statistics
                if ( wpum_is_woocommerce_active() ) {
                    global $wpdb;
                    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                    $ltv_total = floatval( $wpdb->get_var( "SELECT SUM(CAST(meta_value AS DECIMAL(10,2))) FROM {$wpdb->usermeta} WHERE meta_key = '_money_spent'" ) );
                    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                    $customer_count = intval( $wpdb->get_var( "SELECT COUNT(DISTINCT user_id) FROM {$wpdb->usermeta} WHERE meta_key = '_money_spent' AND CAST(meta_value AS DECIMAL(10,2)) > 0" ) );
                    $aov_avg = ( $customer_count > 0 ? $ltv_total / $customer_count : 0 );
                    echo '<h4 style="margin: 0 0 8px 0;">' . esc_html__( 'WooCommerce Revenue Analytics', 'clicks-user-manager' ) . '</h4>';
                    echo '<div style="display:flex; justify-content:space-between; background:#fafafa; border:1px solid #e5e5e5; padding:10px; border-radius:3px; margin-bottom:10px;">';
                    echo '<div><strong style="display:block; font-size:10px; color:#50575e; line-height:1.2;">Registered LTV</strong><span style="font-size:12px; font-weight:600; color:#2271b1;">' . html_entity_decode( strip_tags( wc_price( $ltv_total ) ) ) . '</span></div>';
                    echo '<div><strong style="display:block; font-size:10px; color:#50575e; line-height:1.2;">Average Spending</strong><span style="font-size:12px; font-weight:600; color:#2271b1;">' . html_entity_decode( strip_tags( wc_price( $aov_avg ) ) ) . '</span></div>';
                    echo '</div>';
                }
            }
            echo '<p class="wpum-widget-link"><a href="' . esc_url( admin_url( 'admin.php?page=clicks-user-manager' ) ) . '">' . esc_html__( 'Manage Users →', 'clicks-user-manager' ) . '</a></p>';
            echo '</div>';
            // .wpum-widget
        }

        /**
         * Handle bulk actions via AJAX.
         */
        public function handle_bulk_action() {
            check_ajax_referer( 'wpum_nonce', 'nonce' );
            if ( !current_user_can( 'manage_options' ) ) {
                wp_send_json_error( array(
                    'message' => __( 'Permission denied.', 'clicks-user-manager' ),
                ) );
            }
            $action = ( isset( $_POST['bulk_action'] ) ? sanitize_key( $_POST['bulk_action'] ) : '' );
            $user_ids = ( isset( $_POST['user_ids'] ) ? array_map( 'absint', (array) $_POST['user_ids'] ) : array() );
            if ( empty( $user_ids ) ) {
                wp_send_json_error( array(
                    'message' => __( 'No users selected.', 'clicks-user-manager' ),
                ) );
            }
            // Remove current user from bulk delete.
            $current_user_id = get_current_user_id();
            switch ( $action ) {
                case 'delete':
                    $deleted = 0;
                    require_once ABSPATH . 'wp-admin/includes/user.php';
                    foreach ( $user_ids as $uid ) {
                        if ( $uid === $current_user_id ) {
                            continue;
                        }
                        if ( wp_delete_user( $uid ) ) {
                            $deleted++;
                        }
                    }
                    wp_send_json_success( array(
                        'message' => sprintf( _n(
                            '%d user deleted.',
                            '%d users deleted.',
                            $deleted,
                            'clicks-user-manager'
                        ), $deleted ),
                    ) );
                    break;
                case 'change_role':
                    $new_role = ( isset( $_POST['new_role'] ) ? sanitize_key( $_POST['new_role'] ) : '' );
                    if ( empty( $new_role ) || !isset( wp_roles()->roles[$new_role] ) ) {
                        wp_send_json_error( array(
                            'message' => __( 'Invalid role selected.', 'clicks-user-manager' ),
                        ) );
                    }
                    $changed = 0;
                    foreach ( $user_ids as $uid ) {
                        $user = new WP_User($uid);
                        if ( $user->exists() ) {
                            $user->set_role( $new_role );
                            $changed++;
                        }
                    }
                    wp_send_json_success( array(
                        'message' => sprintf( _n(
                            '%d user role updated.',
                            '%d user roles updated.',
                            $changed,
                            'clicks-user-manager'
                        ), $changed ),
                    ) );
                    break;
                default:
                    wp_send_json_error( array(
                        'message' => __( 'Unknown action.', 'clicks-user-manager' ),
                    ) );
            }
        }

        /**
         * Handle bulk mail via AJAX.
         */
        public function handle_bulk_mail() {
            check_ajax_referer( 'wpum_nonce', 'nonce' );
            if ( !current_user_can( 'manage_options' ) ) {
                wp_send_json_error( array(
                    'message' => __( 'Permission denied.', 'clicks-user-manager' ),
                ) );
            }
            $user_ids = ( isset( $_POST['user_ids'] ) ? array_map( 'absint', (array) $_POST['user_ids'] ) : array() );
            $subject = ( isset( $_POST['subject'] ) ? sanitize_text_field( wp_unslash( $_POST['subject'] ) ) : '' );
            $message = ( isset( $_POST['message'] ) ? wp_kses_post( wp_unslash( $_POST['message'] ) ) : '' );
            if ( empty( $user_ids ) ) {
                wp_send_json_error( array(
                    'message' => __( 'No users selected.', 'clicks-user-manager' ),
                ) );
            }
            if ( empty( $subject ) ) {
                wp_send_json_error( array(
                    'message' => __( 'Email subject is required.', 'clicks-user-manager' ),
                ) );
            }
            if ( empty( $message ) ) {
                wp_send_json_error( array(
                    'message' => __( 'Email message is required.', 'clicks-user-manager' ),
                ) );
            }
            $sent = 0;
            $failed = 0;
            $headers = array('Content-Type: text/html; charset=UTF-8');
            foreach ( $user_ids as $uid ) {
                $user = get_userdata( $uid );
                if ( !$user || empty( $user->user_email ) ) {
                    $failed++;
                    continue;
                }
                $search_tokens = array(
                    '{first_name}',
                    '{last_name}',
                    '{username}',
                    '{email}'
                );
                $replace_tokens = array(
                    esc_html( $user->first_name ),
                    esc_html( $user->last_name ),
                    esc_html( $user->user_login ),
                    esc_html( $user->user_email )
                );
                if ( wpum_is_pro() ) {
                    $search_tokens[] = '{registration_date}';
                    $replace_tokens[] = esc_html( $user->user_registered );
                    $last_login = get_user_meta( $user->ID, '_wpum_last_login', true );
                    $search_tokens[] = '{last_login_date}';
                    $replace_tokens[] = esc_html( ( $last_login ? $last_login : 'Never' ) );
                    if ( wpum_is_woocommerce_active() ) {
                        $ltv = get_user_meta( $user->ID, '_money_spent', true );
                        $cnt = get_user_meta( $user->ID, '_order_count', true );
                        global $wpdb;
                        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                        $last_order_date = $wpdb->get_var( $wpdb->prepare( "SELECT p.post_date FROM {$wpdb->posts} p\n\t\t\t\t\t\t\t INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id\n\t\t\t\t\t\t\t WHERE pm.meta_key = '_customer_user' AND pm.meta_value = %d\n\t\t\t\t\t\t\t AND p.post_type = 'shop_order' AND p.post_status NOT IN ('trash','auto-draft')\n\t\t\t\t\t\t\t ORDER BY p.ID DESC LIMIT 1", $user->ID ) );
                        $search_tokens[] = '{wc_total_spent}';
                        $replace_tokens[] = esc_html( ( $ltv ? html_entity_decode( strip_tags( wc_price( $ltv ) ) ) : '0' ) );
                        $search_tokens[] = '{wc_order_count}';
                        $replace_tokens[] = esc_html( ( $cnt ? $cnt : 0 ) );
                        $search_tokens[] = '{wc_last_order_date}';
                        $replace_tokens[] = esc_html( ( $last_order_date ? $last_order_date : 'Never' ) );
                    }
                    // Meta key matching
                    $combined_text = $message . ' ' . $subject;
                    preg_match_all( '/\\{meta:([a-zA-Z0-9_\\-]+)\\}/', $combined_text, $matches );
                    if ( !empty( $matches[0] ) ) {
                        foreach ( $matches[1] as $index => $meta_key ) {
                            $meta_val = get_user_meta( $user->ID, $meta_key, true );
                            $meta_display = ( is_array( $meta_val ) ? wp_json_encode( $meta_val ) : $meta_val );
                            $search_tokens[] = $matches[0][$index];
                            $replace_tokens[] = esc_html( $meta_display );
                        }
                    }
                }
                $personalised_message = str_replace( $search_tokens, $replace_tokens, $message );
                $personalised_subject = str_replace( $search_tokens, $replace_tokens, $subject );
                if ( wp_mail(
                    $user->user_email,
                    $personalised_subject,
                    $personalised_message,
                    $headers
                ) ) {
                    $sent++;
                } else {
                    $failed++;
                }
            }
            /* translators: 1: sent count, 2: failed count */
            $msg = sprintf( __( '%1$d email(s) sent. %2$d failed.', 'clicks-user-manager' ), $sent, $failed );
            wp_send_json_success( array(
                'message' => $msg,
            ) );
        }

        /**
         * Handle CSV export via AJAX.
         */
        public function handle_export_csv() {
            check_ajax_referer( 'wpum_nonce', 'nonce' );
            if ( !current_user_can( 'manage_options' ) ) {
                wp_die( esc_html__( 'Permission denied.', 'clicks-user-manager' ) );
            }
            wpum_export_csv();
        }

        /**
         * Render About page.
         */
        public function render_about_page() {
            if ( !current_user_can( 'manage_options' ) ) {
                wp_die( esc_html__( 'Permission denied.', 'clicks-user-manager' ) );
            }
            ?>
		<div class="wrap wpum-wrap">
			<?php 
            wpum_upsell_banner();
            ?>
			<h1><?php 
            esc_html_e( 'About Clicks User Manager', 'clicks-user-manager' );
            ?></h1>

			<div class="wpum-about-box">
				<div class="wpum-about-logo">
					<img src="<?php 
            echo esc_url( WPUM_PLUGIN_URL . 'assets/clicks-logo.png' );
            ?>" alt="Clicks" onerror="this.style.display='none'" />
					<div class="wpum-about-brand">Clicks</div>
				</div>

				<div class="wpum-about-content">
					<h2><?php 
            esc_html_e( 'Clicks User Manager', 'clicks-user-manager' );
            ?> <span class="wpum-version">v<?php 
            echo esc_html( WPUM_VERSION );
            ?></span></h2>
					<p><?php 
            esc_html_e( 'Developed with ❤️ by Clicks — Visit us at clicks.com.pk', 'clicks-user-manager' );
            ?></p>

					<p>
						<a href="https://clicks.com.pk" target="_blank" rel="noopener noreferrer" class="button button-primary">
							<?php 
            esc_html_e( 'Visit Clicks.com.pk', 'clicks-user-manager' );
            ?>
						</a>
						&nbsp;
						<a href="https://clicks.com.pk/contact" target="_blank" rel="noopener noreferrer" class="button button-secondary">
							<?php 
            esc_html_e( 'Contact Us', 'clicks-user-manager' );
            ?>
						</a>
					</p>

					<hr />

					<h3><?php 
            esc_html_e( 'Plugin Features', 'clicks-user-manager' );
            ?></h3>
					<ul class="wpum-feature-list">
						<li>✅ <?php 
            esc_html_e( 'Advanced user filtering (role, date, last login, post count)', 'clicks-user-manager' );
            ?></li>
						<li>✅ <?php 
            esc_html_e( 'Bulk delete users with confirmation modal', 'clicks-user-manager' );
            ?></li>
						<li>✅ <?php 
            esc_html_e( 'Bulk role change', 'clicks-user-manager' );
            ?></li>
						<li>✅ <?php 
            esc_html_e( 'Bulk email users via wp_mail', 'clicks-user-manager' );
            ?></li>
						<li>✅ <?php 
            esc_html_e( 'CSV export with custom column selector', 'clicks-user-manager' );
            ?></li>
						<li>✅ <?php 
            esc_html_e( 'Last login tracking', 'clicks-user-manager' );
            ?></li>
						<li>✅ <?php 
            esc_html_e( 'Dashboard stats widget', 'clicks-user-manager' );
            ?></li>
					</ul>

					<hr />

					<h3><?php 
            esc_html_e( 'Developer Information', 'clicks-user-manager' );
            ?></h3>
					<table class="widefat wpum-about-table">
						<tbody>
							<tr>
								<th><?php 
            esc_html_e( 'Developer', 'clicks-user-manager' );
            ?></th>
								<td>Clicks - Digital Marketing &amp; Software Agency</td>
							</tr>
							<tr>
								<th><?php 
            esc_html_e( 'Website', 'clicks-user-manager' );
            ?></th>
								<td><a href="https://clicks.com.pk" target="_blank" rel="noopener noreferrer">clicks.com.pk</a></td>
							</tr>
							<tr>
								<th><?php 
            esc_html_e( 'Version', 'clicks-user-manager' );
            ?></th>
								<td><?php 
            echo esc_html( WPUM_VERSION );
            ?></td>
							</tr>
							<tr>
								<th><?php 
            esc_html_e( 'License', 'clicks-user-manager' );
            ?></th>
								<td><a href="https://www.gnu.org/licenses/gpl-2.0.html" target="_blank" rel="noopener noreferrer">GPL v2</a></td>
							</tr>
						</tbody>
					</table>
				</div>
			</div>
		</div>
		<?php 
        }

        // -------------------------------------------------------------------------
        // Helper query methods
        // -------------------------------------------------------------------------
        /**
         * Get new users registered this calendar month.
         *
         * @return int
         */
        private function get_new_users_this_month() {
            $first = gmdate( 'Y-m-01 00:00:00' );
            $query = new WP_User_Query(array(
                'date_query'  => array(array(
                    'after'     => $first,
                    'inclusive' => true,
                )),
                'count_total' => true,
                'number'      => 0,
            ));
            return (int) $query->get_total();
        }

        /**
         * Get inactive user count.
         *
         * @param int $days Days of inactivity.
         * @return int
         */
        private function get_inactive_users_count( $days ) {
            $cutoff = gmdate( 'Y-m-d H:i:s', strtotime( "-{$days} days" ) );
            $query = new WP_User_Query(array(
                'meta_query'  => array(
                    'relation' => 'AND',
                    array(
                        'key'     => '_wpum_last_login',
                        'value'   => $cutoff,
                        'compare' => '<',
                        'type'    => 'DATETIME',
                    ),
                ),
                'count_total' => true,
                'number'      => 0,
            ));
            return (int) $query->get_total();
        }

        /**
         * Get count of users who have never logged in.
         *
         * @return int
         */
        private function get_never_logged_in_count() {
            $query = new WP_User_Query(array(
                'meta_query'  => array(
                    // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
                    array(
                        'key'     => '_wpum_last_login',
                        'compare' => 'NOT EXISTS',
                    ),
                ),
                'count_total' => true,
                'number'      => 0,
            ));
            return (int) $query->get_total();
        }

        /**
         * Clear the cached WooCommerce order counts.
         *
         * Hooked into WooCommerce order lifecycle actions so the
         * "Orders" column and order-based filters stay accurate.
         */
        public function clear_order_count_cache() {
            delete_transient( 'wpum_wc_order_counts' );
        }

        /**
         * AJAX handler to get user details for Quick Edit.
         */
        public function handle_get_quick_edit() {
            check_ajax_referer( 'wpum_nonce', 'nonce' );
            if ( !current_user_can( 'manage_options' ) ) {
                wp_send_json_error( array(
                    'message' => __( 'Permission denied.', 'clicks-user-manager' ),
                ) );
            }
            $user_id = ( isset( $_POST['user_id'] ) ? absint( $_POST['user_id'] ) : 0 );
            $user = get_userdata( $user_id );
            if ( !$user ) {
                wp_send_json_error( array(
                    'message' => __( 'User not found.', 'clicks-user-manager' ),
                ) );
            }
            $data = array(
                'ID'           => $user->ID,
                'user_login'   => $user->user_login,
                'user_email'   => $user->user_email,
                'first_name'   => $user->first_name,
                'last_name'    => $user->last_name,
                'display_name' => $user->display_name,
                'role'         => ( !empty( $user->roles ) ? reset( $user->roles ) : '' ),
            );
            // Gather user meta (skip internal system keys)
            $all_meta = get_user_meta( $user->ID );
            $formatted_meta = array();
            $skip_keys = array(
                'user_pass',
                'session_tokens',
                '_wpum_notes',
                '_wpum_last_login',
                'community-meta-fields'
            );
            foreach ( $all_meta as $key => $values ) {
                if ( strpos( $key, 'wp_' ) === 0 || in_array( $key, $skip_keys, true ) ) {
                    continue;
                }
                $formatted_meta[$key] = $values[0];
            }
            wp_send_json_success( array(
                'user'   => $data,
                'meta'   => $formatted_meta,
                'is_pro' => wpum_is_pro(),
            ) );
        }

        /**
         * AJAX handler to save user details from Quick Edit.
         */
        public function handle_save_quick_edit() {
            check_ajax_referer( 'wpum_nonce', 'nonce' );
            if ( !current_user_can( 'manage_options' ) ) {
                wp_send_json_error( array(
                    'message' => __( 'Permission denied.', 'clicks-user-manager' ),
                ) );
            }
            $user_data = ( isset( $_POST['user_data'] ) ? (array) $_POST['user_data'] : array() );
            $user_id = ( isset( $user_data['ID'] ) ? absint( $user_data['ID'] ) : 0 );
            if ( !$user_id ) {
                wp_send_json_error( array(
                    'message' => __( 'Invalid user ID.', 'clicks-user-manager' ),
                ) );
            }
            // Update core fields
            $userdata = array(
                'ID'           => $user_id,
                'user_email'   => sanitize_email( $user_data['user_email'] ),
                'first_name'   => sanitize_text_field( $user_data['first_name'] ),
                'last_name'    => sanitize_text_field( $user_data['last_name'] ),
                'display_name' => sanitize_text_field( $user_data['display_name'] ),
            );
            if ( empty( $userdata['user_email'] ) || !is_email( $userdata['user_email'] ) ) {
                wp_send_json_error( array(
                    'message' => __( 'Invalid email address.', 'clicks-user-manager' ),
                ) );
            }
            $existing_user = get_user_by( 'email', $userdata['user_email'] );
            if ( $existing_user && $existing_user->ID !== $user_id ) {
                wp_send_json_error( array(
                    'message' => __( 'Email address already in use by another user.', 'clicks-user-manager' ),
                ) );
            }
            $updated_user_id = wp_update_user( $userdata );
            if ( is_wp_error( $updated_user_id ) ) {
                wp_send_json_error( array(
                    'message' => $updated_user_id->get_error_message(),
                ) );
            }
            // Update role
            if ( isset( $user_data['role'] ) ) {
                $new_role = sanitize_key( $user_data['role'] );
                if ( !empty( $new_role ) && isset( wp_roles()->roles[$new_role] ) ) {
                    $u = new WP_User($user_id);
                    $u->set_role( $new_role );
                }
            }
            // Save custom meta if Pro
            if ( wpum_is_pro() ) {
                $meta_data = ( isset( $_POST['meta_data'] ) ? (array) $_POST['meta_data'] : array() );
                $deleted_meta = ( isset( $_POST['deleted_meta'] ) ? (array) $_POST['deleted_meta'] : array() );
                foreach ( $deleted_meta as $key ) {
                    delete_user_meta( $user_id, sanitize_key( $key ) );
                }
                foreach ( $meta_data as $key => $val ) {
                    $clean_key = sanitize_key( $key );
                    if ( !empty( $clean_key ) ) {
                        update_user_meta( $user_id, $clean_key, sanitize_text_field( wp_unslash( $val ) ) );
                    }
                }
            }
            wp_send_json_success( array(
                'message' => __( 'User updated successfully.', 'clicks-user-manager' ),
            ) );
        }

        /**
         * Get count of active users who logged in within last N days.
         *
         * @param int $days Days.
         * @return int
         */
        private function get_inactive_users_count_inverse( $days ) {
            $cutoff = gmdate( 'Y-m-d H:i:s', strtotime( "-{$days} days" ) );
            $query = new WP_User_Query(array(
                'meta_query'  => array(
                    // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
                    array(
                        'key'     => '_wpum_last_login',
                        'value'   => $cutoff,
                        'compare' => '>=',
                        'type'    => 'DATETIME',
                    ),
                ),
                'count_total' => true,
                'number'      => 0,
            ));
            return (int) $query->get_total();
        }

        /**
         * Get count of users who logged in in a range of days ago.
         *
         * @param int $min_days Minimum days ago.
         * @param int $max_days Maximum days ago.
         * @return int
         */
        private function get_inactive_users_range( $min_days, $max_days ) {
            $start = gmdate( 'Y-m-d H:i:s', strtotime( "-{$max_days} days" ) );
            $end = gmdate( 'Y-m-d H:i:s', strtotime( "-{$min_days} days" ) );
            $query = new WP_User_Query(array(
                'meta_query'  => array(
                    // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
                    array(
                        'key'     => '_wpum_last_login',
                        'value'   => array($start, $end),
                        'compare' => 'BETWEEN',
                        'type'    => 'DATETIME',
                    ),
                ),
                'count_total' => true,
                'number'      => 0,
            ));
            return (int) $query->get_total();
        }

    }

    new WPUM_Plugin();
}