<?php
/**
 * Scan Debug Panel
 * 
 * A dedicated admin page to monitor scan status and debug issues with pause/resume.
 */

// Exit if accessed directly
if (!defined('ABSPATH')) {
    exit;
}

/**
 * Register the debug panel in the admin menu
 */
function wpsec_register_debug_menu() {
    add_menu_page(
        'WPFort Scan Debug',
        'WPFort Debug',
        'manage_options',
        'wpsec-scan-debug',
        'wpsec_render_debug_panel',
        'dashicons-shield',
        80
    );
}
add_action('admin_menu', 'wpsec_register_debug_menu');

/**
 * Process debug actions
 */
function wpsec_process_debug_actions() {
    if (!isset($_GET['_wpnonce']) || !wp_verify_nonce($_GET['_wpnonce'], 'wpsec_debug_action')) {
        return;
    }

    if (isset($_GET['action']) && isset($_GET['scan_id'])) {
        $action = sanitize_text_field($_GET['action']);
        $scan_id = sanitize_text_field($_GET['scan_id']);

        switch ($action) {
            case 'force_resume':
                $resume_from = get_option('wpsec_scan_' . $scan_id . '_resume_position', 0);
                $deep_scan = get_option('wpsec_scan_' . $scan_id . '_deep', false);
                $verbose = get_option('wpsec_scan_' . $scan_id . '_verbose', false);
                
                update_option('wpsec_scan_' . $scan_id . '_status', 'resuming');
                wpsec_run_scan($scan_id, $deep_scan, $verbose, $resume_from);
                break;
                
            case 'force_stop':
                update_option('wpsec_scan_' . $scan_id . '_status', 'stopped');
                break;
                
            case 'clear_cron':
                wp_clear_scheduled_hook('wpsec_resume_scan', array($scan_id));
                wp_clear_scheduled_hook('wpsec_check_scan_recovery', array($scan_id));
                break;
                
            case 'reset_scan':
                // Reset scan completely
                update_option('wpsec_scan_' . $scan_id . '_status', 'stopped');
                update_option('wpsec_scan_' . $scan_id . '_resume_position', 0);
                update_option('wpsec_scan_' . $scan_id . '_files_processed', 0);
                update_option('wpsec_scan_' . $scan_id . '_last_update', time());
                wp_clear_scheduled_hook('wpsec_resume_scan', array($scan_id));
                wp_clear_scheduled_hook('wpsec_check_scan_recovery', array($scan_id));
                delete_transient('wpsec_scan_resume_' . $scan_id);
                break;
        }

        // Redirect to remove the action from URL
        wp_redirect(admin_url('admin.php?page=wpsec-scan-debug'));
        exit;
    }

    // Create recovery key if not exists
    if (!get_option('wpsec_recovery_key')) {
        update_option('wpsec_recovery_key', wp_generate_password(32, false));
    }
}
add_action('admin_init', 'wpsec_process_debug_actions');

/**
 * Render the debug panel
 */
function wpsec_render_debug_panel() {
    // Security check
    if (!current_user_can('manage_options')) {
        return;
    }
    
    echo '<div class="wrap">';
    echo '<h1>Scan Debug Panel</h1>';
    
    // Show active scans
    $active_scans = get_option('wpsec_active_scans', array());
    
    echo '<h2>Active Scans</h2>';
    
    if (empty($active_scans)) {
        echo '<p>No active scans found.</p>';
    } else {
        echo '<table class="widefat striped">';
        echo '<thead><tr>
            <th>Scan ID</th>
            <th>Status</th>
            <th>Last Update</th>
            <th>Files Processed</th>
            <th>Resume Position</th>
            <th>Stalled?</th>
            <th>Actions</th>
        </tr></thead><tbody>';
        
        foreach ($active_scans as $scan_id) {
            $status = get_option('wpsec_scan_' . $scan_id . '_status', 'unknown');
            $last_update = get_option('wpsec_scan_' . $scan_id . '_last_update', 0);
            $last_update_str = $last_update ? human_time_diff($last_update) . ' ago' : 'Never';
            $files_processed = get_option('wpsec_scan_' . $scan_id . '_files_processed', 0);
            $resume_position = get_option('wpsec_scan_' . $scan_id . '_resume_position', 0);
            
            // Check if scan is stalled
            $stalled = false;
            if ($status == 'scanning' || $status == 'paused') {
                $stalled = (time() - $last_update > 300); // 5 minutes
            }
            
            $nonce = wp_create_nonce('wpsec_debug_action');
            
            echo '<tr>';
            echo '<td>' . esc_html($scan_id) . '</td>';
            echo '<td>' . esc_html($status) . '</td>';
            echo '<td>' . esc_html($last_update_str) . '</td>';
            echo '<td>' . esc_html($files_processed) . '</td>';
            echo '<td>' . esc_html($resume_position) . '</td>';
            echo '<td>' . ($stalled ? '<span style="color:red">Yes</span>' : 'No') . '</td>';
            echo '<td>';
            echo '<a href="' . esc_url(admin_url('admin.php?page=wpsec-scan-debug&action=force_resume&scan_id=' . $scan_id . '&_wpnonce=' . $nonce)) . '" class="button-primary">Force Resume</a> ';
            echo '<a href="' . esc_url(admin_url('admin.php?page=wpsec-scan-debug&action=force_stop&scan_id=' . $scan_id . '&_wpnonce=' . $nonce)) . '" class="button">Stop</a> ';
            echo '<a href="' . esc_url(admin_url('admin.php?page=wpsec-scan-debug&action=clear_cron&scan_id=' . $scan_id . '&_wpnonce=' . $nonce)) . '" class="button">Clear Cron</a> ';
            echo '<a href="' . esc_url(admin_url('admin.php?page=wpsec-scan-debug&action=reset_scan&scan_id=' . $scan_id . '&_wpnonce=' . $nonce)) . '" class="button" onclick="return confirm(\'Are you sure? This will reset all scan progress.\')">Reset</a>';
            echo '</td>';
            echo '</tr>';
        }
        
        echo '</tbody></table>';
    }
    
    // Show WP Cron events
    echo '<h2>Scheduled WP Cron Events</h2>';
    
    $cron_events = _get_cron_array();
    $found_events = false;
    
    if (empty($cron_events)) {
        echo '<p>No scheduled events found.</p>';
    } else {
        echo '<table class="widefat striped">';
        echo '<thead><tr>
            <th>Hook</th>
            <th>Arguments</th>
            <th>Scheduled Time</th>
            <th>Time Until Run</th>
        </tr></thead><tbody>';
        
        foreach ($cron_events as $time => $hooks) {
            foreach ($hooks as $hook => $events) {
                if (strpos($hook, 'wpsec') !== false) {
                    $found_events = true;
                    foreach ($events as $event) {
                        $args_str = !empty($event['args']) ? json_encode($event['args']) : 'none';
                        
                        echo '<tr>';
                        echo '<td>' . esc_html($hook) . '</td>';
                        echo '<td>' . esc_html($args_str) . '</td>';
                        echo '<td>' . esc_html(gmdate('Y-m-d H:i:s', $time)) . '</td>';
                        echo '<td>' . esc_html(human_time_diff($time)) . '</td>';
                        echo '</tr>';
                    }
                }
            }
        }
        
        echo '</tbody></table>';
        
        if (!$found_events) {
            echo '<p>No WPFort scan events found in WP Cron.</p>';
        }
    }
    
    // Show transients
    echo '<h2>Active Scan Transients</h2>';
    
    global $wpdb;
    $transients = $wpdb->get_results(
        "SELECT option_name, option_value FROM $wpdb->options 
        WHERE option_name LIKE '%_transient_wpsec_scan%' 
        OR option_name LIKE '%_transient_timeout_wpsec_scan%'"
    );
    
    if (empty($transients)) {
        echo '<p>No scan transients found.</p>';
    } else {
        echo '<table class="widefat striped">';
        echo '<thead><tr>
            <th>Transient Name</th>
            <th>Value</th>
        </tr></thead><tbody>';
        
        foreach ($transients as $transient) {
            $name = str_replace('_transient_', '', $transient->option_name);
            $name = str_replace('_transient_timeout_', '', $name);
            
            echo '<tr>';
            echo '<td>' . esc_html($name) . '</td>';
            echo '<td>' . esc_html($transient->option_value) . '</td>';
            echo '</tr>';
        }
        
        echo '</tbody></table>';
    }
    
    // Show Server Environment
    echo '<h2>Server Environment</h2>';
    
    $server_env = function_exists('wpsec_detect_server_environment') ? wpsec_detect_server_environment() : array();
    
    echo '<table class="widefat striped">';
    echo '<tbody>';
    
    if (!empty($server_env)) {
        foreach ($server_env as $key => $value) {
            echo '<tr>';
            echo '<th>' . esc_html(ucwords(str_replace('_', ' ', $key))) . '</th>';
            echo '<td>' . esc_html(is_array($value) ? json_encode($value) : $value) . '</td>';
            echo '</tr>';
        }
    }
    
    // Add PHP info
    echo '<tr><th>PHP Memory Limit</th><td>' . esc_html(ini_get('memory_limit')) . '</td></tr>';
    echo '<tr><th>PHP Max Execution Time</th><td>' . esc_html(ini_get('max_execution_time')) . ' seconds</td></tr>';
    echo '<tr><th>PHP Version</th><td>' . esc_html(phpversion()) . '</td></tr>';
    
    echo '</tbody></table>';
    
    // Direct recovery URL
    $recovery_key = get_option('wpsec_recovery_key', '');
    $recovery_url = plugins_url('scan-recovery-direct.php', dirname(__FILE__)) . '?key=' . $recovery_key;
    
    echo '<h2>Direct Recovery</h2>';
    echo '<p>Use this URL for external cron jobs to trigger scan recovery without relying on WP Cron:</p>';
    echo '<input type="text" class="regular-text" readonly value="' . esc_url($recovery_url) . '" onclick="this.select();">';
    echo '<p>Example cURL command: <code>curl -s "' . esc_url($recovery_url) . '"</code></p>';
    
    echo '</div>'; // End .wrap
}
