<?php
/**
 * Live Traffic Controller
 *
 * @package VMPFence
 * @subpackage Tools
 * @since 2.1.0
 * @since 2.2.2 Added dashboard menu and auto-refresh features
 * @since 2.2.5 Added Enhanced Audit Log integration for live traffic events and settings changes
 */

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

// Load dependencies
require_once plugin_dir_path(__FILE__) . '../models/class-live-traffic.php';

/**
 * Live Traffic Controller Class
 *
 * @since 2.1.0
 */
class VMPFence_Live_Traffic_Controller {

    /**
     * Constructor
     *
     * @since 2.1.0
     */
    public function __construct() {
        // Initialize hooks
        add_action('wp_ajax_vmpfence_get_live_traffic', array($this, 'ajax_get_live_traffic'));
        add_action('wp_ajax_vmpfence_get_audit_log', array($this, 'ajax_get_audit_log'));
        add_action('wp_ajax_vmpfence_get_traffic_stats', array($this, 'ajax_get_traffic_stats'));
        add_action('wp_ajax_vmpfence_get_traffic_options', array($this, 'ajax_get_traffic_options'));
        add_action('wp_ajax_vmpfence_save_traffic_options', array($this, 'ajax_save_traffic_options'));
        add_action('wp_ajax_vmpfence_get_audit_log_options', array($this, 'ajax_get_audit_log_options'));
        add_action('wp_ajax_vmpfence_save_audit_log_options', array($this, 'ajax_save_audit_log_options'));
        
        // Phase 3: Advanced query endpoints
        add_action('wp_ajax_vmpfence_get_live_traffic_realtime', array($this, 'ajax_get_live_traffic_realtime'));
        add_action('wp_ajax_vmpfence_reload_live_traffic_table', array($this, 'ajax_reload_live_traffic_table'));
        add_action('wp_ajax_vmpfence_get_filter_options', array($this, 'ajax_get_filter_options'));
        add_action('wp_ajax_vmpfence_get_groupby_options', array($this, 'ajax_get_groupby_options'));
        
        // Traffic detail endpoint
        add_action('wp_ajax_vmpfence_get_traffic_detail', array($this, 'ajax_get_traffic_detail'));
        
        // Recent traffic by IP endpoint
        add_action('wp_ajax_vmpfence_get_recent_traffic_by_ip', array($this, 'ajax_get_recent_traffic_by_ip'));
    }

    /**
     * Get live traffic data via AJAX
     *
     * @since 2.1.0
     * @return void
     */
    public function ajax_get_live_traffic() {
        // Verify nonce
        check_ajax_referer('vmpfence_tools_nonce', 'nonce');

        // Verify capabilities
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => __('Insufficient permissions', 'vmpfence-security')));
        }

        // Get parameters
        $page = isset($_POST['page']) ? intval($_POST['page']) : 1;
        $per_page = isset($_POST['per_page']) ? intval($_POST['per_page']) : 25;
        $filter = isset($_POST['filter']) ? sanitize_text_field($_POST['filter']) : 'all';

        // Advanced filter parameters
        $params = isset($_POST['param']) && is_array($_POST['param']) ? $_POST['param'] : array();
        $operators = isset($_POST['operator']) && is_array($_POST['operator']) ? $_POST['operator'] : array();
        $values = isset($_POST['value']) && is_array($_POST['value']) ? $_POST['value'] : array();
        
        // Group by parameter
        $groupby = isset($_POST['groupby']) ? sanitize_text_field($_POST['groupby']) : '';
        
        // Date range parameters
        $startDate = isset($_POST['startDate']) ? floatval($_POST['startDate']) : 0;
        $endDate = isset($_POST['endDate']) ? floatval($_POST['endDate']) : 0;
        
        // Since parameter for real-time
        $since = isset($_POST['since']) ? floatval($_POST['since']) : 0;

        // Calculate offset
        $offset = ($page - 1) * $per_page;

        // Build arguments array for advanced query
        $args = array(
            'limit' => $per_page,
            'offset' => $offset
        );

        // Add filters if provided
        if (!empty($params) && !empty($operators) && !empty($values)) {
            $count = min(count($params), count($operators), count($values));
            
            // Model expects param[], operator[], value[] arrays
            $args['param'] = array();
            $args['operator'] = array();
            $args['value'] = array();
            
            for ($i = 0; $i < $count; $i++) {
                $args['param'][] = sanitize_text_field($params[$i]);
                $args['operator'][] = sanitize_text_field($operators[$i]);
                $args['value'][] = sanitize_text_field($values[$i]);
            }
        }

        // Add group by if provided
        if (!empty($groupby)) {
            $args['groupby'] = $groupby;
        }

        // Add date range if provided
        if ($startDate > 0) {
            $args['startDate'] = $startDate;
        }
        if ($endDate > 0) {
            $args['endDate'] = $endDate;
        }

        // Add since parameter for polling
        if ($since > 0) {
            $args['since'] = $since;
        }

        // Use advanced query if any advanced parameters are present
        if (!empty($args['param']) || !empty($args['groupby']) || $startDate > 0 || $endDate > 0 || $since > 0) {
            $result = VMPFence_Live_Traffic_Model::get_live_traffic_advanced($args);
        } else {
            // Fall back to simple query for backward compatibility
            $result = VMPFence_Live_Traffic_Model::get_live_traffic(array(
                'limit' => $per_page,
                'offset' => $offset,
                'filter_type' => $filter
            ));
        }

        // Validate result structure
        if (!is_array($result) || !isset($result['data']) || !isset($result['total'])) {
            wp_send_json_error(array('message' => __('Invalid query result', 'vmpfence-security')));
            return;
        }

        // Send response
        wp_send_json_success(array(
            'data' => $result['data'],
            'total' => $result['total'],
            'page' => $page,
            'per_page' => $per_page,
            'total_pages' => ceil($result['total'] / $per_page),
            'grouped' => !empty($args['groupby'])
        ));
    }

    /**
     * Get audit log data via AJAX
     *
     * @since 2.1.0
     * @return void
     */
    public function ajax_get_audit_log() {
        // Verify nonce
        check_ajax_referer('vmpfence_tools_nonce', 'nonce');

        // Verify capabilities
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => __('Insufficient permissions', 'vmpfence-security')));
        }

        // Get parameters
        $page = isset($_POST['page']) ? intval($_POST['page']) : 1;
        $per_page = isset($_POST['per_page']) ? intval($_POST['per_page']) : 25;
        $event_type = isset($_POST['event_type']) ? sanitize_text_field($_POST['event_type']) : '';

        // Calculate offset
        $offset = ($page - 1) * $per_page;

        // Get data
        $result = VMPFence_Live_Traffic_Model::get_audit_logs(array(
            'limit' => $per_page,
            'offset' => $offset,
            'event_type' => $event_type
        ));

        // Send response
        wp_send_json_success(array(
            'data' => $result['data'],
            'total' => $result['total'],
            'page' => $page,
            'per_page' => $per_page,
            'total_pages' => ceil($result['total'] / $per_page)
        ));
    }

    /**
     * Get live traffic data for real-time polling via AJAX
     *
     * @since 2.1.0
     * @return void
     */
    public function ajax_get_live_traffic_realtime() {
        // Verify nonce
        check_ajax_referer('vmpfence_tools_nonce', 'nonce');

        // Verify capabilities
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => __('Insufficient permissions', 'vmpfence-security')));
        }

        // Get since parameter (timestamp)
        $since = isset($_POST['since']) ? floatval($_POST['since']) : 0;

        if ($since <= 0) {
            wp_send_json_error(array('message' => __('Invalid since parameter', 'vmpfence-security')));
        }

        // Build arguments for query - only get records newer than since timestamp
        $args = array(
            'limit' => 20, // Limit to 20 records max for polling
            'offset' => 0,
            'since' => $since
        );

        // Get new records
        $result = VMPFence_Live_Traffic_Model::get_live_traffic_advanced($args);

        // Send response with new records
        wp_send_json_success(array(
            'data' => $result['data'],
            'count' => count($result['data']),
            'timestamp' => microtime(true)
        ));
    }

    /**
     * Get traffic statistics via AJAX
     *
     * @since 2.1.0
     * @return void
     */
    public function ajax_get_traffic_stats() {
        // Verify nonce
        check_ajax_referer('vmpfence_tools_nonce', 'nonce');

        // Verify capabilities
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => __('Insufficient permissions', 'vmpfence-security')));
        }

        // Get statistics
        $stats = VMPFence_Live_Traffic_Model::get_traffic_stats();

        // Send response
        wp_send_json_success($stats);
    }

    /**
     * Get traffic options via AJAX
     *
     * @since 2.1.0
     * @return void
     */
    public function ajax_get_traffic_options() {
        // Verify nonce
        check_ajax_referer('vmpfence_tools_nonce', 'nonce');

        // Verify capabilities
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => __('Insufficient permissions', 'vmpfence-security')));
        }

        // Get options from database
        $options = array(
            'traffic_logging_mode' => get_option('vmpfence_traffic_logging_mode', 'security_only'),
            'ignore_publishing_users' => get_option('vmpfence_ignore_publishing_users', '0'),
            'ignore_usernames' => get_option('vmpfence_ignore_usernames', ''),
            'ignore_ips' => get_option('vmpfence_ignore_ips', ''),
            'ignore_user_agent' => get_option('vmpfence_ignore_user_agent', ''),
            'max_traffic_rows' => get_option('vmpfence_max_traffic_rows', '2000'),
            'max_traffic_days' => get_option('vmpfence_max_traffic_days', '30'),
            'display_live_traffic_menu' => VMPFence_Config::get('display_live_traffic_menu', 1),
        );

        // Send response
        wp_send_json_success($options);
    }

    /**
     * Save traffic options via AJAX
     *
     * @since 2.1.0
     * @return void
     */
    public function ajax_save_traffic_options() {
        // Verify nonce
        check_ajax_referer('vmpfence_tools_nonce', 'nonce');

        // Verify capabilities
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => __('Insufficient permissions', 'vmpfence-security')));
        }

        // Parse the serialized form data
        parse_str($_POST['options'], $options);

        // Save each option
        update_option('vmpfence_traffic_logging_mode', sanitize_text_field($options['traffic_logging_mode']));
        update_option('vmpfence_ignore_publishing_users', isset($options['ignore_publishing_users']) ? '1' : '0');
        update_option('vmpfence_ignore_usernames', sanitize_textarea_field($options['ignore_usernames']));
        update_option('vmpfence_ignore_ips', sanitize_textarea_field($options['ignore_ips']));
        update_option('vmpfence_ignore_user_agent', sanitize_text_field($options['ignore_user_agent']));
        update_option('vmpfence_max_traffic_rows', absint($options['max_traffic_rows']));
        update_option('vmpfence_max_traffic_days', absint($options['max_traffic_days']));
        VMPFence_Config::set('display_live_traffic_menu', isset($options['display_live_traffic_menu']) ? 1 : 0);

        // Send response
        wp_send_json_success(array('message' => __('Settings saved successfully', 'vmpfence-security')));
    }

    /**
     * Get audit log options via AJAX
     *
     * @since 2.1.0
     * @return void
     */
    public function ajax_get_audit_log_options() {
        // Verify nonce
        check_ajax_referer('vmpfence_tools_nonce', 'nonce');

        // Verify capabilities
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => __('Insufficient permissions', 'vmpfence-security')));
        }

        // Get options from database
        $options = array(
            'audit_log_logging_mode' => get_option('vmpfence_audit_log_logging_mode', 'preview'),
            'display_audit_log_menu' => VMPFence_Config::get('display_audit_log_menu', 1),
        );

        // Send response
        wp_send_json_success($options);
    }

    /**
     * Get available filter options via AJAX
     *
     * @since 2.1.0
     * @return void
     */
    public function ajax_get_filter_options() {
        // Verify nonce
        check_ajax_referer('vmpfence_tools_nonce', 'nonce');

        // Verify capabilities
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => __('Insufficient permissions', 'vmpfence-security')));
        }

        // Get filter parameters metadata from model
        $filterParams = VMPFence_Live_Traffic_Model::get_filter_params();

        // Send response
        wp_send_json_success(array(
            'params' => $filterParams
        ));
    }

    /**
     * Get available group by options via AJAX
     *
     * @since 2.1.0
     * @return void
     */
    public function ajax_get_groupby_options() {
        // Verify nonce
        check_ajax_referer('vmpfence_tools_nonce', 'nonce');

        // Verify capabilities
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => __('Insufficient permissions', 'vmpfence-security')));
        }

        // Get group by options from model
        $groupByOptions = VMPFence_Live_Traffic_Model::get_group_by_options();

        // Send response
        wp_send_json_success(array(
            'options' => $groupByOptions
        ));
    }

    /**
     * Save audit log options via AJAX
     *
     * @since 2.1.0
     * @return void
     */
    public function ajax_save_audit_log_options() {
        // Verify nonce
        check_ajax_referer('vmpfence_tools_nonce', 'nonce');

        // Verify capabilities
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => __('Insufficient permissions', 'vmpfence-security')));
        }

        // Parse the serialized form data
        parse_str($_POST['options'], $options);

        // Save each option
        $old_al_mode = get_option('vmpfence_audit_log_logging_mode', 'preview');
        $new_al_mode = sanitize_text_field($options['audit_log_logging_mode']);
        update_option('vmpfence_audit_log_logging_mode', $new_al_mode);
        if ($old_al_mode !== $new_al_mode) {
            do_action('vmpfence_audit_log_mode_changed', $old_al_mode, $new_al_mode);
        }
        VMPFence_Config::set('display_audit_log_menu', isset($options['display_audit_log_menu']) ? 1 : 0);

        // Send response
        wp_send_json_success(array('message' => __('Settings saved successfully', 'vmpfence-security')));
    }

    /**
     * Get traffic detail via AJAX
     *
     * @since 2.1.0
     * @return void
     */
    public function ajax_get_traffic_detail() {
        // Verify nonce
        check_ajax_referer('vmpfence_tools_nonce', 'nonce');

        // Verify capabilities
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => __('Insufficient permissions', 'vmpfence-security')));
        }

        // Get record ID
        $id = isset($_POST['id']) ? intval($_POST['id']) : 0;

        if (!$id) {
            wp_send_json_error(array('message' => __('Invalid record ID', 'vmpfence-security')));
        }

        // Get record from database
        global $wpdb;
        $table_name = VMPFence_Constants::get_table_name(VMPFence_Constants::TABLE_HITS);

        // Select specific columns to avoid unnecessary data transfer
        $record = $wpdb->get_row($wpdb->prepare(
            "SELECT id, attackLogTime, ctime, IP, jsRun, statusCode, isGoogle, userID, 
                    newVisit, URL, referer, UA, action, actionDescription 
             FROM {$table_name} WHERE id = %d",
            $id
        ), ARRAY_A);

        if (!$record) {
            wp_send_json_error(array('message' => __('Record not found', 'vmpfence-security')));
        }

        // Format timestamp
        $record['formatted_time'] = date('m/d/Y h:i:s A', (int)$record['ctime']);
        
        // Calculate time ago
        $time_diff = time() - (int)$record['ctime'];
        if ($time_diff < 60) {
            $record['time_ago'] = $time_diff . ' seconds ago';
        } elseif ($time_diff < 3600) {
            $record['time_ago'] = floor($time_diff / 60) . ' minutes ago';
        } elseif ($time_diff < 86400) {
            $record['time_ago'] = floor($time_diff / 3600) . ' hours ago';
        } else {
            $record['time_ago'] = floor($time_diff / 86400) . ' days ago';
        }

        // Convert binary IP to readable format
        if (!empty($record['IP'])) {
            $ip_string = @inet_ntop($record['IP']);
            if ($ip_string !== false) {
                $record['IP'] = $ip_string;
            } else {
                // Fallback if already string or invalid binary
                $record['IP'] = is_string($record['IP']) ? $record['IP'] : '0.0.0.0';
            }
        } else {
            $record['IP'] = '0.0.0.0';
        }

        // Get hostname (consistent with main traffic table)
        // Uses cached reverse DNS lookup (7-day cache) to avoid performance issues
        $record['hostname'] = VMPFence_Live_Traffic_Model::get_hostname($record['IP']);

        // Map UA to user_agent for JavaScript compatibility
        $record['user_agent'] = !empty($record['UA']) ? $record['UA'] : '';

        // Get user information if logged in
        if (!empty($record['userID']) && $record['userID'] > 0) {
            $user = get_userdata($record['userID']);
            if ($user) {
                $record['user_login'] = $user->user_login;
                $record['display_name'] = $user->display_name;
            }
        }

        // Get country info from GeoIP lookup
        $country_info = VMPFence_Live_Traffic_Model::get_country_info($record['IP']);
        $record['countryCode'] = $country_info['code'];
        $record['countryName'] = $country_info['name'];
        $record['countryFlag'] = $country_info['flag'];

        // Send response
        wp_send_json_success($record);
    }

    /**
     * Get recent traffic by IP via AJAX
     *
     * @since 2.1.0
     * @return void
     */
    public function ajax_get_recent_traffic_by_ip() {
        // Verify nonce
        check_ajax_referer('vmpfence_tools_nonce', 'nonce');

        // Verify capabilities
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => __('Insufficient permissions', 'vmpfence-security')));
        }

        // Get IP parameter
        $ip = isset($_POST['ip']) ? sanitize_text_field($_POST['ip']) : '';

        if (empty($ip)) {
            wp_send_json_error(array('message' => __('Invalid IP address', 'vmpfence-security')));
        }

        // Get recent traffic for this IP (latest 10 entries)
        $traffic_data = VMPFence_Live_Traffic_Model::get_recent_traffic_by_ip($ip, 10);

        wp_send_json_success($traffic_data);
    }

    /**
     * Initialize controller
     *
     * @since 2.1.0
     * @return VMPFence_Live_Traffic_Controller
     */
    public static function init() {
        static $instance = null;

        if (null === $instance) {
            $instance = new self();
        }

        return $instance;
    }
    /**
     * Reload Live Traffic table (for auto-refresh with full table reload)
     *
     * @since 2.2.2
     * @return void
     */
    public function ajax_reload_live_traffic_table() {
        // Verify nonce
        check_ajax_referer('vmpfence_tools_nonce', 'nonce');

        // Verify capabilities
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => __('Insufficient permissions', 'vmpfence-security')));
        }

        // Get parameters
        $page = isset($_POST['page']) ? intval($_POST['page']) : 1;
        $per_page = isset($_POST['per_page']) ? intval($_POST['per_page']) : 100;

        // Calculate offset
        $offset = ($page - 1) * $per_page;

        // Build arguments array
        $args = array(
            'limit' => $per_page,
            'offset' => $offset
        );

        // Get records
        $result = VMPFence_Live_Traffic_Model::get_live_traffic_advanced($args);
        $records = $result['data'];

        // Generate HTML for table rows
        ob_start();
        if (!empty($records)) {
            foreach ($records as $record) {
                $this->render_traffic_row($record);
            }
        }
        $html = ob_get_clean();

        wp_send_json_success(array(
            'html' => $html,
            'count' => count($records)
        ));
    }

    /**
     * Render a single traffic table row
     *@since 2.2.2
     * @param array $record Traffic record
     * @return void
     */
    private function render_traffic_row($record) {
        // Determine type class and label
        $type = isset($record['type']) ? $record['type'] : 'unspecified';
        $type_class = $type;
        
        $type_labels = array(
            'human' => 'Human',
            'bot' => 'Bot',
            'blocked' => 'Blocked',
            'warning' => 'Warning',
            'unspecified' => 'Unspecified'
        );
        $type_label = isset($type_labels[$type]) ? $type_labels[$type] : 'Unknown';
        
        // Get action label
        $action = isset($record['action']) ? $record['action'] : '';
        $action_label = $this->get_action_label($action);
        
        // Format time
        $formatted_time = isset($record['formatted_time']) ? $record['formatted_time'] : human_time_diff($record['ctime'], time()) . ' ago';
        
        // Get hostname
        $hostname = isset($record['hostname']) && !empty($record['hostname']) ? $record['hostname'] : '-';
        
        // Get response
        $response = isset($record['response']) ? $record['response'] : '200';
        ?>
        <tr>
            <td>
                <span class="vmpfence-traffic-type">
                    <span class="vmpfence-traffic-icon <?php echo esc_attr($type_class); ?>"></span>
                    <?php echo esc_html($type_label); ?>
                </span>
            </td>
            <td><?php
                $country_name = isset($record['countryName']) && $record['countryName'] !== 'Unspecified' ? $record['countryName'] : '';
                $country_flag = isset($record['countryFlag']) ? $record['countryFlag'] : '';
                if (!empty($country_name)) {
                    if (!empty($country_flag)) {
                        echo '<img src="' . esc_url($country_flag) . '" alt="' . esc_attr($record['countryCode'] ?? '') . '" class="country-flag" style="width:20px;height:15px;vertical-align:middle;margin-right:5px;"> ';
                    }
                    echo esc_html($country_name);
                } else {
                    echo '<span class="vmpfence-location-unspecified">Unspecified</span>';
                }
            ?></td>
            <td class="vmpfence-page-visited" title="<?php echo esc_attr($record['URL']); ?>"><?php echo esc_html($record['URL']); ?></td>
            <td><?php echo esc_html($formatted_time); ?></td>
            <td class="vmpfence-ip-cell" title="<?php echo esc_attr($record['IP']); ?>"><?php echo esc_html($record['IP']); ?></td>
            <td class="vmpfence-hostname-cell" title="<?php echo esc_attr($hostname); ?>"><?php echo esc_html($hostname); ?></td>
            <td><span class="vmpfence-response-badge response-<?php echo esc_attr($response); ?>"><?php echo esc_html($response); ?></span></td>
            <td>
                <button class="vmpfence-action-btn view vmpfence-view-details" data-id="<?php echo esc_attr($record['id']); ?>">
                    <span class="dashicons dashicons-visibility"></span>
                </button>
            </td>
        </tr>
        <?php
    }
    
    /**
     * Get action label (matches JavaScript getActionLabel)
     * @since 2.2.2
     * @param string $action Action code
     * @return string Action label
     */
    private function get_action_label($action) {
        if (empty($action)) {
            return 'Unspecified';
        }
        
        $labels = array(
            'blocked:waf' => 'Blocked WAF',
            'logged:waf' => 'Logged WAF',
            'lockedOut' => 'Locked Out',
            'loginOK' => 'Login Success',
            'loginFailValidUsername' => 'Login Failed (Valid User)',
            'loginFailInvalidUsername' => 'Login Failed (Invalid User)',
            'logout' => 'Logout',
            'lostPassword' => 'Password Reset Request',
            'user:adminCreate' => 'Admin Created',
            'user:passwordReset' => 'Password Reset',
            'rate_limit_block' => 'Rate Limited (Blocked)',
            'rate_limit_throttle' => 'Rate Limited (Throttled)'
        );
        
        // Check for exact match
        if (isset($labels[$action])) {
            return $labels[$action];
        }
        
        // Check for partial matches
        if (strpos($action, 'rate_limit') !== false) return 'Rate Limited';
        if (strpos($action, 'lockedOut') !== false) return 'Locked Out';
        if (strpos($action, 'blocked') !== false) return 'Blocked';
        
        return ucfirst(str_replace('_', ' ', $action));
    }}
