<?php
defined('ABSPATH') || exit;

/**
 * WPFort Scan Resume System
 * 
 * This file provides functionality to handle scan resuming and recovery
 * for scans that get interrupted or stalled due to server issues
 */

/**
 * Handle scan resume request from scheduled event
 * 
 * @param array $args Arguments containing scan_id, force_deep_scan, and resume_position
 * @return void
 */
function wpsec_handle_scan_resume($args) {
    if (!isset($args['scan_id']) || !isset($args['resume_position']) || !isset($args['force_deep_scan'])) {
        wpsec_debug_log('⚠️ WPFort: Invalid resume scan arguments', 'warning');
        return;
    }
    
    $scan_id = $args['scan_id'];
    $resume_position = $args['resume_position'];
    $force_deep_scan = $args['force_deep_scan'];
    
    wpsec_debug_log('🔄 WPFort: Resuming scan ID ' . $scan_id . ' from position ' . $resume_position, 'info');
    
    // Update status to show we're resuming
    update_option('wpsec_scan_' . $scan_id . '_status', 'resuming');
    
    // Run the scan with resume position
    wpsec_run_scan($scan_id, $force_deep_scan, false, $resume_position);
}

/**
 * Watchdog function to check for stalled scans and attempt recovery
 * 
 * @param string $scan_id The scan ID to check
 * @return void
 */
function wpsec_scan_timeout_watchdog($scan_id) {
    $status = get_option('wpsec_scan_' . $scan_id . '_status', '');
    $last_update = get_option('wpsec_scan_' . $scan_id . '_last_progress_update', 0);
    $current_time = time();
    $timeout_duration = 180; // 3 minutes timeout
    
    // Only check active scans
    if ($status === 'scanning' || $status === 'resuming' || $status === 'running') {
        // If no update in 3 minutes, attempt recovery
        if (($current_time - $last_update) > $timeout_duration) {
            wpsec_debug_log('⚠️ WPFort: Scan ' . $scan_id . ' appears to be stalled. Last update was ' . 
                      ($current_time - $last_update) . ' seconds ago. Attempting recovery.', 'warning');
            
            // Get the last scanned file index
            $last_index = get_option('wpsec_scan_' . $scan_id . '_last_scanned_index', 0);
            $force_deep_scan = get_option('wpsec_scan_' . $scan_id . '_force_deep_scan', false);
            
            // Only attempt recovery if we have a valid index
            if ($last_index > 0) {
                // Schedule resume with a position slightly before where it stalled to ensure no files are missed
                $resume_position = max(0, $last_index - 10);
                
                wpsec_debug_log('🔄 WPFort: Scheduling scan recovery from position ' . $resume_position, 'info');
                
                // Schedule resume in 30 seconds
                wp_schedule_single_event(time() + 30, 'wpsec_resume_scan', [
                    'scan_id' => $scan_id,
                    'force_deep_scan' => $force_deep_scan,
                    'resume_position' => $resume_position
                ]);
            } else {
                // Can't recover, mark as failed
                update_option('wpsec_scan_' . $scan_id . '_status', 'error');
                update_option('wpsec_scan_' . $scan_id . '_error', 'Scan stalled and recovery failed');
                
                wpsec_debug_log('❌ WPFort: Scan recovery failed for scan ' . $scan_id . ' - no valid resume position', 'error');
            }
        } else {
            // Still within timeout, schedule another check
            wp_schedule_single_event(time() + 60, 'wpsec_scan_watchdog', [$scan_id]);
        }
    }
}

// Register the action hooks
add_action('wpsec_resume_scan', 'wpsec_handle_scan_resume');
add_action('wpsec_scan_watchdog', 'wpsec_scan_timeout_watchdog');

// Modify the existing timeout check to incorporate our new recovery system
add_action('wpsec_check_scan_timeout', function($scan_id) {
    // Check if the scan is already in error state
    $status = get_option('wpsec_scan_' . $scan_id . '_status', '');
    if ($status === 'error') {
        return;
    }
    
    // Schedule our more advanced watchdog
    wp_schedule_single_event(time(), 'wpsec_scan_watchdog', [$scan_id]);
}, 5); // Run before the default handler
