<?php
/**
 * Optimized Background Unarchive Processor for Archived Orders
 *
 * Two-Phase Approach:
 * Phase 1: Unarchive all orders (restore to WooCommerce)
 * Phase 2: Delete successfully unarchived orders from archive table
 */

/**
 * Unarchive Background Process Class
 */
namespace ARCHM\Features;

if ( ! defined('ABSPATH') ) {
    // phpcs:ignore Universal.PHP.RequireExitDieParentheses.Missing
    exit;
}

use ARCHM\Admin\AdminRest;

class ARCM_Unarchive_Background_Process extends \WP_Background_Process {

    use \ARCHM\Helpers\Utilities;
    use \ARCHM\Helpers\DBHelper;
    use \ARCHM\Helpers\BGProcessHelper;

    /**
     * Background cron prefix
     *
     * @var string
     */
    protected $prefix = 'unarchive';

    /**
     * Action name
     *
     * @var string
     */
    protected $action = 'arcm_unarchive_orders';

    public function __construct() {
        parent::__construct();
        $this->set_remote_db_settings();
        $this->set_main_deb_settings();
        $this->set_db_instance();
        // Hook into WordPress
        add_action('wp_ajax_start_unarchive_orders', [ $this, 'start_unarchive' ]);
        add_action('wp_ajax_check_unarchive_progress', [ $this, 'check_progress' ]);
        add_action('wp_ajax_cancel_archiving', [ $this, 'cancel_archiving' ]);
        add_action('wp_ajax_check_bg_archiving', [ $this, 'check_bg_progress' ]);
        add_action('wp_ajax_check_duplicate_orders', [ $this, 'check_duplicate_orders' ]);
        add_action('wp_ajax_skip_duplicate_orders', [ $this, 'skip_duplicate_orders' ]);
    }

    /**
     * Start Unarchive Order with Two-Phase Approach
     */
    public function start_unarchive() {
        // Check if there's already a process running (with force override option)
        if ( $this->is_process_already_running() ) {
            // error_log('Unarchive process already running - forcing cleanup and restart');
            $this->force_cleanup_and_reset();
        }

        // COMPREHENSIVE CLEANUP - Clear ALL previous data and states
        delete_option('arcm_unarchive_cancelled');
        delete_option('arcm_unarchive_jobs');
        delete_option('arcm_unarchive_processed_orders');
        delete_option('arcm_bg_unarchive_running');

        // Clear any existing queue data from previous runs
        $this->clear_queue();

        // Verify nonce and permissions
        if ( ! current_user_can('manage_options') ) {
            wp_die('Unauthorized');
        }

        $inputs                = $this->io()->get_inputs();
        $bulk_selected_orders  = $inputs['bulk_selected_order'];
        $allow_duplicate_order = $inputs['allow_duplicate_orders'];
        $batch_size            = 20;

        // Get total orders
        if ( ! empty($bulk_selected_orders) ) {
            $total_orders   = count($bulk_selected_orders);
            $chunked_orders = array_chunk($bulk_selected_orders, $batch_size);
            $total_batches  = count($chunked_orders);

            // error_log('Starting NEW bulk operation: ' . esc_html($total_orders) . ' orders in ' . esc_html($total_batches) . ' batches');

            // Phase 1: Unarchive batches
            for ( $batch_number = 1; $batch_number <= $total_batches; $batch_number++ ) {
                $this->push_to_queue([
                    'batch_number'           => $batch_number,
                    'total_batches'          => $total_batches,
                    'allow_duplicate_orders' => $allow_duplicate_order,
                    'selected_bulk_order'    => $chunked_orders[ $batch_number - 1 ],
                    'phase'                  => 'unarchive',
                    'is_bulk_operation'      => true,
                ]);
            }

            // Phase 2: Single deletion task after all unarchive batches
            $this->push_to_queue([
                'batch_number'           => $total_batches + 1,
                'total_batches'          => $total_batches + 1, // +1 for deletion phase
                'allow_duplicate_orders' => $allow_duplicate_order,
                'phase'                  => 'delete',
                'is_bulk_operation'      => true,
            ]);

        } else {
            $total_orders  = $this->get_total_orders_count();
            $total_batches = ceil($total_orders / $batch_size);

            // error_log('Starting NEW full operation: ' . esc_html($total_orders) . ' orders in ' . esc_html($total_batches) . ' batches');

            // Phase 1: Unarchive batches
            for ( $batch_number = 1; $batch_number <= $total_batches; $batch_number++ ) {
                $this->push_to_queue([
                    'batch_number'           => $batch_number,
                    'total_batches'          => $total_batches,
                    'allow_duplicate_orders' => $allow_duplicate_order,
                    'batch_size'             => $batch_size,
                    'phase'                  => 'unarchive',
                    'is_bulk_operation'      => false,
                ]);
            }

            // Phase 2: Single deletion task after all unarchive batches
            $this->push_to_queue([
                'batch_number'           => $total_batches + 1,
                'total_batches'          => $total_batches + 1, // +1 for deletion phase
                'allow_duplicate_orders' => $allow_duplicate_order,
                'phase'                  => 'delete',
                'is_bulk_operation'      => false,
            ]);
        }

        if ( 0 === $total_orders ) {
            $this->io()->send_json(false, __('No orders found to Unarchive', 'archive-master'));
            return;
        }

        // Store job information
        $jobs = [
            'status'            => 'processing',
            'progress'          => 0,
            'unarchived_order'  => 0,
            'total_orders'      => $total_orders,
            'total_batches'     => $total_batches + 1, // +1 for deletion phase
            'unarchive_batches' => $total_batches,     // Actual unarchive batches (without delete phase)
            'current_phase'     => 'unarchive',
            'created_at'        => current_time('mysql'),
            'updated_at'        => current_time('mysql'),
        ];

        update_option('arcm_unarchive_jobs', $jobs);
        update_option('arcm_bg_unarchive_running', true);

        // Dispatch the background process
        $dispatched = $this->save()->dispatch();

        if ( $dispatched ) {
            // error_log('Background process dispatched successfully');
            $this->io()->send_json(true, __('Unarchive started successfully', 'archive-master'));
        } else {
            // error_log('Failed to dispatch background process');
            // Clean up if dispatch failed
            update_option('arcm_bg_unarchive_running', false);
            delete_option('arcm_unarchive_jobs');
            $this->io()->send_json(false, __('Failed to start unarchive process', 'archive-master'));
        }
    }

    /**
     * Check if there's already a process running
     */
    private function is_process_already_running() {
        // Check multiple indicators
        $bg_running     = get_option('arcm_bg_unarchive_running', false);
        $jobs           = get_option('arcm_unarchive_jobs', []);
        $is_processing  = ! empty($jobs) && isset($jobs['status']) && 'processing' === $jobs['status'];
        $cancelled_flag = get_option('arcm_unarchive_cancelled', false);

        // If cancelled flag is set but other indicators show running, it's a stale state
        if ( $cancelled_flag && ( $bg_running || $is_processing ) ) {
            return true;
        }

        return $bg_running || $is_processing;
    }

    /**
     * Force cleanup and reset all states
     */
    private function force_cleanup_and_reset() {
        try {
            // error_log('Force cleanup: Clearing stale background process state');

            // Cancel any existing process
            $this->cancel_process();
            $this->clear_scheduled_event();
            $this->clear_queue();

            // Clear all options
            delete_option('arcm_unarchive_cancelled');
            delete_option('arcm_unarchive_jobs');
            delete_option('arcm_unarchive_processed_orders');
            delete_option('arcm_bg_unarchive_running');

            // error_log('Force cleanup completed');

        } catch ( \Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
            // error_log('Force cleanup error: ' . $e->getMessage());
        }
    }

    /**
     * Get total orders count
     */
    private function get_total_orders_count() {
        try {
            $selected_storage = get_option('archm_selected_database', 'sqlite');
            if ( 'sqlite' === $selected_storage || 'google_drive' === $selected_storage ) {
                $sqlite = Sqlite::get_instance();
                return $sqlite->count_total_archived_order();
            } elseif ( 'custom_mysql' === $selected_storage ) {
                $table_name = $this->wpdb->prefix . 'archived_orders';

                // Count total archived orders
                $count = $this->remote_db->get_var("SELECT COUNT(*) FROM `{$table_name}`");

                return $count ? (int) $count : 0;
            } else {
                return 0;
            }
        } catch ( \Exception $e ) {
            // error_log('Failed to get orders count: ' . $e->getMessage());
            return 0;
        }
    }

    /**
     * Task handler with two-phase processing and cancellation check
     *
     * @param mixed $item Queue item to iterate over
     * @return mixed
     */
    protected function task( $item ) {
        // Check if cancellation was requested before processing
        if ( $this->is_cancelled() ) {
            // error_log('Unarchive process cancelled - stopping batch processing');
            return false;
        }

        $phase = $item['phase'];

        try {
            if ( 'unarchive' === $phase ) {
                return $this->handle_unarchive_phase($item);
            } elseif ( 'delete' === $phase ) {
                return $this->handle_delete_phase($item);
            }
		} catch ( \Exception $e ) {
            // error_log('Unarchive task failed: ' . $e->getMessage());
            $this->mark_job_failed($e->getMessage());
            return false;
        }

        return false; // Remove item from queue
    }

    /**
     * Enhanced handle_unarchive_phase with better cancellation handling
     */
    private function handle_unarchive_phase( $item ) {
        $batch_number           = $item['batch_number'];
        $total_batches          = $item['total_batches'];
        $allow_duplicate_orders = $item['allow_duplicate_orders'];
        $is_bulk_operation      = $item['is_bulk_operation'];

        // Check for cancellation
        if ( $this->is_cancelled() ) {
            // error_log('Unarchive process cancelled during batch ' . esc_html($batch_number));
            return false;
        }

        // Get orders for this batch
        if ( $is_bulk_operation ) {
            $orders = $item['selected_bulk_order'];
        } else {
            $orders = $this->fetch_orders_batch($batch_number);
        }

        $batch_order = count($orders);
        // error_log('UNARCHIVE Phase - Batch ' . esc_html($batch_number) . ': Processing ' . esc_html($batch_order) . ' orders');

        if ( ! empty($orders) ) {
            // Final check before processing batch
            if ( $this->is_cancelled() ) {
                // error_log('Unarchive process cancelled before processing batch ' . esc_html($batch_number));
                return false;
            }

            // Process unarchiving WITHOUT deletion (with granular cancellation checks)
            $this->process_unarchive_only($orders, $batch_order, $batch_number, $allow_duplicate_orders);
        }

        // // Check for cancellation before updating progress
        // if ($this->is_cancelled()) {
        //     error_log("Unarchive process cancelled after batch $batch_number - skipping progress update");
        //     return false;
        // }

        // Update progress (Phase 1 takes up 90% of progress)
        $jobs                     = get_option('arcm_unarchive_jobs', []);
        $actual_unarchive_batches = isset($jobs['unarchive_batches']) ? $jobs['unarchive_batches'] : ( $total_batches - 1 );
        $unarchive_progress       = round(( $batch_number / $actual_unarchive_batches ) * 90);
        $this->update_job_progress($unarchive_progress, $batch_order, 'Unarchiving batch ' . esc_html($batch_number) . ' of ' . esc_html($actual_unarchive_batches));

        return false;
    }

    /**
     * Handle Phase 2: Deleting successfully unarchived orders
     */
    private function handle_delete_phase( $item ) {
        // Check for cancellation
        if ( $this->is_cancelled() ) {
            // error_log('Delete phase cancelled');
            return false;
        }

        // Get all successfully processed orders
        $processed_orders = get_option('arcm_unarchive_processed_orders', []);

        if ( ! empty($processed_orders) ) {
                                                                   // Delete in batches to avoid memory issues
            $delete_batches = array_chunk($processed_orders, 100); // Delete 100 at a time
                                                                   // Create instance of AdminRest class
            $rest = new AdminRest();

            foreach ( $delete_batches as $order_ids_batch ) {
                // Check for cancellation during deletion
                if ( $this->is_cancelled() ) {
                    return false;
                }

                $rest->processed_unarchive_delete( $order_ids_batch );
            }

            // Clean up tracking
            delete_option('arcm_unarchive_processed_orders');
        }

        // Mark job as complete (will be handled in complete() method)
        $this->update_job_progress(100, 0, 'Unarchive process completed successfully');

        return false;
    }

    /**
     * Fixed process_unarchive_only method with granular cancellation checks
     */
    private function process_unarchive_only( $orders, $batch_order, $batch_number, $allow_duplicate_orders ) {
        // Check for cancellation before processing
        if ( $this->is_cancelled() ) {
            // error_log('Batch processing cancelled for batch ' . esc_html($batch_number));
            return;
        }

        $rest = new AdminRest();

        // error_log('Unarchiving ' . esc_html($batch_order) . ' orders from batch ' . esc_html($batch_number));

                                        // IMPORTANT: Process orders in smaller chunks with cancellation checks
        $chunk_size                = 5; // Process 5 orders at a time
        $order_chunks              = array_chunk($orders, $chunk_size);
        $total_unarchived          = 0;
        $all_archive_ids_to_delete = [];

        foreach ( $order_chunks as $chunk_index => $order_chunk ) {
            // Check for cancellation before each chunk
            if ( $this->is_cancelled() ) {
                // error_log('Batch ' . esc_html($batch_number) . ' cancelled during chunk ' . esc_html($chunk_index + 1) . ' - stopping further processing');

                // Still need to track what was already processed for cleanup
                if ( ! empty($all_archive_ids_to_delete) ) {
                    $existing_processed = get_option('arcm_unarchive_processed_orders', []);
                    $updated_processed  = array_merge($existing_processed, $all_archive_ids_to_delete);
                    update_option('arcm_unarchive_processed_orders', $updated_processed);
                    // error_log('Marked ' . count($all_archive_ids_to_delete) . ' archive records for cleanup on cancellation');
                }
                return;
            }

            // Process this chunk
            // error_log('Processing chunk ' . esc_html($chunk_index + 1) . ' with ' . esc_html(count($order_chunk)) . ' orders in batch ' . esc_html($batch_number));

            $unarchive_info = $rest->procesed_unarchived_order($order_chunk, 'bulk', $allow_duplicate_orders);
            $unarchive_data = $unarchive_info['data'];

            if ( ! empty($unarchive_data['unarchiveOrder']) ) {
                $unarchived_orders = $unarchive_data['unarchiveOrder'];
                $total_unarchived += count($unarchived_orders);

                // Find the archive table IDs for successfully unarchived orders in this chunk
                $chunk_archive_ids = array_map(
                    function ( $order ) {
                        return $order['id'];
                    },
                    array_filter($order_chunk, function ( $order ) use ( $unarchived_orders ) {
                        return in_array( (int) $order['archived_order_id'], $unarchived_orders);
                    })
                );

                $all_archive_ids_to_delete = array_merge($all_archive_ids_to_delete, $chunk_archive_ids);
            }

                            // Add a small delay to allow cancellation checks to be more responsive
            usleep(100000); // 0.1 second delay between chunks
        }

        // // Final check before storing results
        // if ($this->is_cancelled()) {
        //     error_log("Batch $batch_number cancelled after processing - storing results for cleanup");
        // }

        // Store all successfully processed IDs for deletion in Phase 2 (or cleanup if cancelled)
        if ( ! empty($all_archive_ids_to_delete) ) {
            $existing_processed = get_option('arcm_unarchive_processed_orders', []);
            $updated_processed  = array_merge($existing_processed, $all_archive_ids_to_delete);
            update_option('arcm_unarchive_processed_orders', $updated_processed);
        }
    }

    /**
     * Fetch orders batch from database
     */
    private function fetch_orders_batch( $batch_number ) {
        $offset = ( $batch_number - 1 ) * 20;
        $selected_storage = get_option('archm_selected_database', 'sqlite');

        if ( 'sqlite' === $selected_storage || 'google_drive' === $selected_storage ) {
            $sqlite = Sqlite::get_instance();
            return $sqlite->fetch_archived_orders(20, $offset, 'DESC');
        } elseif ( 'custom_mysql' === $selected_storage ) {
            $table_name = $this->wpdb->prefix . 'archived_orders';

            // Fetch archived orders batch
            $results = $this->remote_db->get_results(
                $this->remote_db->prepare(
                    "SELECT * FROM `{$table_name}` ORDER BY id DESC LIMIT %d OFFSET %d",
                    20,
                    $offset
                ),
                ARRAY_A
            );

            return $results ? $results : array();
        }

        return array();
    }

    /**
     * Complete processing with cleanup
     */
    protected function complete() {
        parent::complete();

        // Update job status to completed
        $jobs = get_option('arcm_unarchive_jobs', []);
        if ( ! empty($jobs) ) {
            $jobs['status']        = 'completed';
            $jobs['progress']      = 100;
            $jobs['current_phase'] = 'completed';
            $jobs['updated_at']    = current_time('mysql');
            update_option('arcm_unarchive_jobs', $jobs);
        }

        // error_log('Unarchive process completed successfully');

        if ( $this->is_cancelled() ) {
            $is_process_orderd = get_option('arcm_unarchive_processed_orders', []);
            if ( ! empty($is_process_orderd) ) {
                $this->cleanup_unarchived_orders_on_cancel();
            }
        }

        // Trigger bulk unarchive hook for cache clearing when multiple orders were unarchived
        $processed_orders = get_option('arcm_unarchive_processed_orders', []);
        if ( ! empty($processed_orders) && ! $this->is_cancelled() ) {
            $unarchived_count = count($processed_orders);
            do_action('archm_orders_bulk_unarchived', $unarchived_count);
        }

        // Sync SQLite database to Google Drive after all orders are archived
        $selected_database = get_option('archm_selected_database', 'sqlite');
        if ( 'google_drive' === $selected_database ) {
            // Use shutdown hook to ensure sync executes even if wp_die() is called
            do_action('archm_sqlite_changed');
        }

        // Sync unarchived orders to Google Sheets if order-sync plugin is active
        $this->sync_orders_to_google_sheets();

        // Clean up all tracking data
        delete_option('arcm_unarchive_cancelled');
        delete_option('arcm_bg_unarchive_running');
        delete_option('arcm_unarchive_processed_orders');
    }

    /**
     * Enhanced cancel_archiving with immediate flag setting and better cleanup
     */
    public function cancel_archiving() {
        try {
            // error_log('CANCEL REQUEST: Immediate cancellation flag set');

            // Set cancellation flag IMMEDIATELY - this is the most critical step
            update_option('arcm_unarchive_cancelled', true);

            // Give a moment for any running tasks to detect the cancellation
            sleep(1);

            // IMPORTANT: Clean up any already unarchived orders before cancelling
            $this->cleanup_unarchived_orders_on_cancel();

            // Cancel the background process
            $this->cancel_process();

            // Clear any scheduled events
            $this->clear_scheduled_event();

            // Clear the queue completely
            $this->clear_queue();

            // Update job status to cancelled
            $jobs = get_option('arcm_unarchive_jobs', []);
            if ( ! empty($jobs) ) {
                $jobs['status']     = 'cancelled';
                $jobs['progress']   = 0; // Reset progress
                $jobs['updated_at'] = current_time('mysql');
                update_option('arcm_unarchive_jobs', $jobs);
            }

            // Clean up ALL running flags and tracking data
            update_option('arcm_bg_unarchive_running', false);

            // error_log('CANCEL COMPLETE: Unarchive process cancelled successfully with cleanup');

            $this->io()->send_json(true, __('Unarchive canceled successfully', 'archive-master'), $jobs);

        } catch ( \Exception $e ) {
            // error_log('CANCEL ERROR: ' . $e->getMessage());

            // Ensure cleanup even if there's an error
            update_option('arcm_bg_unarchive_running', false);
            delete_option('arcm_unarchive_cancelled');

            $this->io()->send_json(false, __('Error cancelling unarchive process', 'archive-master'), []);
        }
    }

    /**
     * Clean up already unarchived orders when process is cancelled
     * This ensures data consistency by deleting successfully unarchived orders from archive table
     */
    private function cleanup_unarchived_orders_on_cancel() {
        try {
            // Get orders that were successfully unarchived but not yet deleted
            $processed_orders = get_option('arcm_unarchive_processed_orders', []);

            if ( ! empty($processed_orders) ) {
                // error_log('CANCEL CLEANUP: Found ' . count($processed_orders) . ' unarchived orders to delete from archive table');

                                                                       // Delete these orders from archive table to maintain consistency
                $delete_batches = array_chunk($processed_orders, 100); // Process in batches
                $total_deleted  = 0;
                $rest           = new AdminRest();

                foreach ( $delete_batches as $batch_index => $order_ids_batch ) {
                    $deleted = $rest->processed_unarchive_delete($order_ids_batch);
                    if ( $deleted ) {
                        $total_deleted += count($order_ids_batch);
                        // error_log('CANCEL CLEANUP: Deleted batch ' . ( $batch_index + 1 ) . ' with ' . count($order_ids_batch) . ' orders');
                    }
                }

                // error_log('CANCEL CLEANUP: Successfully deleted ' . esc_html($total_deleted) . ' unarchived orders from archive table');

            } else { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedElse
                // error_log('CANCEL CLEANUP: No unarchived orders found to clean up');
            }
		} catch ( \Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
            // error_log('CANCEL CLEANUP ERROR: ' . $e->getMessage());
        }
    }

    /**
     * Clear the entire queue - compatible with older WP Background Process versions
     */
    private function clear_queue() {
        global $wpdb;

        // Clear the queue from database
        $table  = $wpdb->options;
        $column = 'option_name';

        $key = $this->identifier . '_batch_%';

        $wpdb->query($wpdb->prepare("DELETE FROM {$table} WHERE {$column} LIKE %s", $key)); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter

        // Clear the queue data
        $this->data = [];

        // Delete the queue option
        delete_option($this->identifier . '_batch_1');
    }

    /**
     * Check if the process has been cancelled
     */
    private function is_cancelled() {
        return get_option('arcm_unarchive_cancelled', false);
    }

    /**
     * Check unarchive progress with cancelled status handling
     */
    public function check_progress() {
        try {
            $jobs = get_option('arcm_unarchive_jobs', []);

            // If cancelled, return cancelled status
            if ( get_option('arcm_unarchive_cancelled', false) ) {
                $jobs['status'] = 'cancelled';
            }

            if ( isset($jobs['progress']) && 100 === (int) $jobs['progress'] && 'completed' === $jobs['status'] ) {
                delete_option('arcm_unarchive_jobs');
            }

            $this->io()->send_json(true, '', $jobs);
        } catch ( \Exception $e ) {
            $this->io()->send_json(false, 'Failed to get the order status', []);
        }
    }

    /**
     * Check duplicate order
     */
    public function check_duplicate_orders() {
        try {
            $duplicate_orders = get_option('arcm_dublicate_order', []);
            if ( ! empty($duplicate_orders) ) {
                $this->io()->send_json(true, '', $duplicate_orders);
            } else {
                $this->io()->send_json(false, 'No duplicate order found');
            }
        } catch ( \Exception $e ) {
            $this->io()->send_json(false, 'Failed to get the order status', []);
        }
    }

    /**
     * Skip Duplicate Order
     */
    public function skip_duplicate_orders() {
        try {
            delete_option('arcm_dublicate_order');
            $this->io()->send_json(true, 'Duplicate orders are skiped', []);
        } catch ( \Exception $e ) {
            $this->io()->send_json(false, 'Failed to skip duplicate order', []);
        }
    }

    /**
     * Check Background exporting
     */
    public function check_bg_progress() {
        try {
            $is_bg_process_running = get_option('arcm_bg_unarchive_running', false);
            $this->io()->send_json(true, '', [ 'is_bg_process' => $is_bg_process_running ]);
        } catch ( \Exception $e ) {
            $this->io()->send_json(false, 'Failed to check export background process', []);
        }
    }

    /**
     * Update job progress with phase information
     */
    private function update_job_progress( $progress, $batch_order, $message ) {
        // Ensure progress never exceeds 100%
        $progress = min($progress, 100);

        // error_log('unarchive job progress: ' . esc_html($progress) . '% - ' . esc_html($message));

        $jobs = get_option('arcm_unarchive_jobs', []);
        if ( ! empty($jobs) ) {
            $jobs['progress']         = $progress;
            $jobs['unarchived_order'] = $jobs['unarchived_order'] + $batch_order;
            $jobs['updated_at']       = current_time('mysql');

            // Update phase when entering deletion (at 90% or higher)
            if ( $progress >= 90 ) {
                $jobs['current_phase'] = 'delete';
            }

            update_option('arcm_unarchive_jobs', $jobs);
        }
    }

    /**
     * Mark job as failed
     */
    private function mark_job_failed( $error_message ) {
        $jobs = get_option('arcm_unarchive_jobs', []);
        if ( ! empty($jobs) ) {
            $jobs['status']     = 'failed';
            $jobs['progress']   = 0;
            $jobs['error']      = $error_message;
            $jobs['updated_at'] = current_time('mysql');
            update_option('arcm_unarchive_jobs', $jobs);
        }

        // Clean up tracking data on failure
        delete_option('arcm_unarchive_processed_orders');
        update_option('arcm_bg_unarchive_running', false);
    }
}
