<?php
/**
 * Optimized Background Export Processor for Orders
 *
 * This version supports both WooCommerce orders from main database
 * and archived orders from archived database based on order source.
 * Now supports CSV, Excel, JSON, and XML formats.
 */

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

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

use ARCHM\Features\Sqlite; // phpcs:ignore Universal.UseStatements.DisallowUseClass.FromSameNamespace

class ARCM_Export_Background_Process extends \WP_Background_Process {


    use \ARCHM\Helpers\Utilities;

    /**
     * Background corn prefix
     *
     * @var string
     */
    protected $prefix = 'export';

    /**
     * Background corn action
     *
     * @var string
     */
    protected $action = 'arcm_export_orders';

    /**
     * Supported export formats
     *
     * @var array
     */
    private $supported_formats = [ 'csv', 'json', 'xml' ];

    /**
     * Supported order sources
     *
     * @var array
     */
    private $supported_sources = [ 'woocommerce', 'archived' ];

    public function __construct() {
        parent::__construct();
        // Hook into WordPress
        add_action('wp_ajax_start_export_orders', [ $this, 'start_export' ]);
        add_action('wp_ajax_check_export_progress', [ $this, 'check_progress' ]);
        add_action('wp_ajax_check_bg_exporting', [ $this, 'check_bg_progress' ]);
        add_action('wp_ajax_cancel_exporting', [ $this, 'cancel_exporting' ]);

        // Clean up old exports (run daily)
        add_action('arcm_cleanup_old_exports', [ $this, 'cleanup_old_exports' ]);
        if ( ! wp_next_scheduled('arcm_cleanup_old_exports') ) {
            wp_schedule_event(time(), 'daily', 'arcm_cleanup_old_exports');
        }
    }

    /**
     * Start export process
     */
    public function start_export() {
        // Clear any previous cancellation flag
        delete_option('arcm_export_cancelled');
        delete_option('arcm_export_jobs');

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

        // Generate unique job ID
        $job_id = uniqid('export_', true);

        $data = $this->io()->get_inputs();

        // Validate order source
        $order_source = strtolower($data['order_source'] ? $data['order_source'] : 'archived');
        if ( ! in_array($order_source, $this->supported_sources) ) {
            /* translators: order source validation error */
            $this->io()->send_json(false, __('Unsupported order source', 'archive-master'), [ 'jobId' => $job_id ]);
            return;
        }

        // Get total orders based on source
        $total_orders = $this->get_total_orders_count($order_source, $data);

        if ( 0 === $total_orders ) {
            $source_name = 'woocommerce' === $order_source ? 'WooCommerce' : 'archived';
            /* translators: %s: source name (WooCommerce or archived) */
            $this->io()->send_json(false, sprintf(__('No %s orders found to export', 'archive-master'), $source_name), [ 'jobId' => $job_id ]);
            // Ensure jobs are cleared when no orders found
            delete_option('arcm_export_jobs');
            delete_option('arcm_bg_export_running');
            return;
        }

        // Validate format
        $format = strtolower($data['export_format']);
        if ( ! in_array($format, $this->supported_formats) ) {
            /* translators: export format validation error */
            $this->io()->send_json(false, __('Unsupported export format', 'archive-master'), [ 'jobId' => $job_id ]);
            return;
        }

        // Calculate number of batches needed
        $total_batches = ceil($total_orders / 20);

        // Store job information
        $jobs          = get_option('arcm_export_jobs', []);
        $jobs[ $job_id ] = [
            'status'        => 'processing',
            'format'        => $format,
            'order_source'  => $order_source,
            'progress'      => 0,
            'sort'          => $data['sort_type'],
            'message'       => 'Starting export...',
            'total_orders'  => $total_orders,
            'total_batches' => $total_batches,
            'created_at'    => current_time('mysql'),
            'updated_at'    => current_time('mysql'),
        ];

        update_option('arcm_export_jobs', $jobs);
        update_option('arcm_bg_export_running', true);

        // Add batches to background process queue
        for ( $batch_number = 1; $batch_number <= $total_batches; $batch_number++ ) {
            $this->push_to_queue([
                'job_id'        => $job_id,
                'batch_number'  => $batch_number,
                'format'        => $format,
                'order_source'  => $order_source,
                'total_batches' => $total_batches,
                'sort'          => $data['sort_type'],
                'wc-export-dta' => $data,
            ]);
        }

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

        $source_name = 'woocommerce' === $order_source ? 'WooCommerce' : 'archived';
        /* translators: %s: source name (WooCommerce or archived) */
        $this->io()->send_json(true, sprintf(__('%s orders export started successfully', 'archive-master'), $source_name), [
            'jobId'       => $job_id,
            'total_order' => $total_orders,
        ]);
    }

    /**
     * Improved cancel background exporting with proper cleanup
     */
    public function cancel_exporting() {
        try {
            // Set cancellation flag
            update_option('arcm_export_cancelled', true);

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

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

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

            // Update all processing jobs to cancelled
            $jobs = get_option('arcm_export_jobs', []);
            foreach ( $jobs as $job_id => $job_data ) {
                if ( 'processing' === $job_data['status'] ) {
                    $jobs[ $job_id ]['status']     = 'cancelled';
                    $jobs[ $job_id ]['message']    = 'Export cancelled by user';
                    $jobs[ $job_id ]['updated_at'] = current_time('mysql');

                    // Clean up temp files for this job
                    $this->cleanup_temp_files_for_job($job_id, isset($job_data['total_batches']) ? $job_data['total_batches'] : 0);
                }
            }
            update_option('arcm_export_jobs', $jobs);

            // Clean up running flag
            update_option('arcm_bg_export_running', false);

            // error_log('Export process cancelled successfully');

            /* translators: export cancellation success message */
            $this->io()->send_json(true, __('Export canceled successfully', 'archive-master'), $jobs);

        } catch ( \Exception $e ) {
            // error_log('Error cancelling export process: ' . $e->getMessage());
            /* translators: export cancellation error message */
            $this->io()->send_json(false, __('Error cancelling export process', 'archive-master'), []);
        }
    }

    /**
     * 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_export_cancelled', false);
    }

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

            // If cancelled, update status for all processing jobs
            if ( get_option('arcm_export_cancelled', false) ) {
                foreach ( $jobs as $job_id => $job_data ) {
                    if ( 'processing' === $job_data['status'] ) {
                        $jobs[ $job_id ]['status']  = 'cancelled';
                        $jobs[ $job_id ]['message'] = 'Export cancelled';
                    }
                }
                update_option('arcm_export_jobs', $jobs);
            }

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

    /**
     * Check Background exporting
     */
    public function check_bg_progress() {
        try {
            $is_bg_process_running = get_option('arcm_bg_export_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', []);
        }
    }

    /**
     * Get total orders count based on source
     */
    private function get_total_orders_count( $order_source, $data = [] ) {
        try {
            switch ( $order_source ) {
                case 'woocommerce':
                    $args = $this->get_wc_query_arguments($data);
                    return $this->get_total_woocommerce_orders_count($args);
                case 'archived':
                    return $this->get_total_archived_orders_count();
                default:
                    return 0;
            }
        } catch ( \Exception $e ) {
            // error_log('Failed to get orders count for source ' . esc_html($order_source) . ': ' . esc_html($e->getMessage()));
            return 0;
        }
    }

    /**
     * Get query argument foe WC orders
     */
    public function get_wc_query_arguments( $data = [] ) {
        if ( ! isset($data['order_start_date']) && ! isset($data['order_end_date']) ) {
            return [
                'limit'   => -1,
                'return'  => 'ids',
                'orderby' => 'date',
                'order'   => $data['sort_type'],
            ];
        }

        // Prepare date range filter using date_query
        $date_query = [];

        $start_date = $data['order_start_date'];
        $end_date   = $data['order_end_date'];

        // Verify date format and add to query
        if ( $start_date && gmdate('Y-m-d', strtotime($start_date)) === $start_date ) {
            $date_query['after'] = $start_date;
        }
        if ( $end_date && gmdate('Y-m-d', strtotime($end_date)) === $end_date ) {
            $date_query['before'] = $end_date;
        }

        if ( ! empty($date_query) ) {
            $date_query['inclusive'] = true;
        }

        // Fetch WooCommerce orders within the date range using date_query
        return [
            'limit'      => -1,
            'return'     => 'ids',
            'date_query' => [ $date_query ], // Pass date_query as an array of arrays
            'orderby'    => 'date',
            'order'      => $data['sort_type'],
        ];
    }

    /**
     * Get total WooCommerce orders count
     */
    private function get_total_woocommerce_orders_count( $args ) {
        $wc_orders = wc_get_orders($args);
        return count($wc_orders);
    }

    /**
     * Get total archived orders count
     */
    private function get_total_archived_orders_count() {
        $sqlite = Sqlite::get_instance();
        return $sqlite->count_total_archived_order();
    }

    /**
     * Task handler with 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('Export process cancelled - stopping batch processing');
            return false;
        }

        $job_id         = $item['job_id'];
        $batch_number   = $item['batch_number'];
        $format         = $item['format'];
        $order_source   = $item['order_source'];
        $total_batches  = $item['total_batches'];
        $sort           = $item['sort'];
        $wc_export_data = $item['wc-export-dta'];

        try {
            // Fetch this batch of orders from appropriate source
            $orders      = $this->fetch_orders_batch($batch_number, $sort, $order_source, $wc_export_data);
            $batch_order = count($orders);

            // error_log('fetch orders batch: ' . esc_html($batch_number) . ' from source: ' . esc_html($order_source) . ' batch order: ' . esc_html($batch_order));

            if ( ! empty($orders) ) {
                // Check for cancellation before processing batch
                if ( $this->is_cancelled() ) {
                    // error_log('Export process cancelled during batch ' . esc_html($batch_number));
                    return false;
                }

                // Process this batch
                $this->process_batch($job_id, $orders, $format, $batch_number, $total_batches);
            }

            // Check for cancellation before updating progress
            if ( $this->is_cancelled() ) {
                // error_log('Export process cancelled after batch ' . esc_html($batch_number));
                return false;
            }

            // Update progress
            $progress = round(( $batch_number / $total_batches ) * 100);
            // error_log('export progress: ' . esc_html($progress));

            $source_name = 'woocommerce' === $order_source ? 'WooCommerce' : 'archived';
            $this->update_job_progress($job_id, $progress, 'Processing ' . esc_html($source_name) . ' batch ' . esc_html($batch_number) . ' of ' . esc_html($total_batches));

        } catch ( \Exception $e ) {
            // Log error and mark job as failed
            // error_log('Export batch failed: ' . esc_html($e->getMessage()));
            $this->mark_job_failed($job_id, $e->getMessage());
            return false;
        }

        return false; // Remove item from queue
    }

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

        // Clean up cancellation flag
        delete_option('arcm_export_cancelled');

        // Get the job ID from the last processed item
        $jobs = get_option('arcm_export_jobs', []);
        foreach ( $jobs as $job_id => $job_data ) {
            if ( 'processing' === $job_data['status'] ) {
                $this->finalize_export($job_id);
                break;
            }
        }

        update_option('arcm_bg_export_running', false);

        // error_log('Export process completed successfully');
    }

    /**
     * Fetch orders batch from appropriate source
     */
    private function fetch_orders_batch( $batch_number, $sort, $order_source, $wc_export_data = [] ) {
        switch ( $order_source ) {
            case 'woocommerce':
                return $this->fetch_woocommerce_orders_batch($batch_number, $wc_export_data);
            case 'archived':
                return $this->fetch_archived_orders_batch($batch_number, $sort);
            default:
                throw new \Exception('Unsupported order source: ' . esc_html($order_source));
        }
    }

    /**
     * Fetch WooCommerce orders batch from database
     */
    private function fetch_woocommerce_orders_batch( $batch_number, $wc_export_data = [] ) {
        $args           = $this->get_wc_query_arguments($wc_export_data);
        $args['limit']  = 20;
        $args['offset'] = ( $batch_number - 1 ) * 20;
        $order_ids      = wc_get_orders($args);

        $orders = [];
        foreach ( $order_ids as $order_id ) {
            $wc_order = wc_get_order($order_id);

            if ( 'shop_order_refund' === $wc_order->get_type() ) {
                continue;
            }

            if ( $wc_order ) {
                $orders[] = [
                    'order_id'   => $order_id,
                    'order_data' => json_encode($this->format_woocommerce_order_data($wc_order)),
                    'source'     => 'woocommerce',
                ];
            }
        }

        return $orders;
    }

    /**
     * Fetch archived orders batch from SQLite database
     */
    private function fetch_archived_orders_batch( $batch_number, $sort ) {
        $sqlite = Sqlite::get_instance();
        $offset = ( $batch_number - 1 ) * 20;
        $orders = $sqlite->fetch_archived_orders(20, $offset, $sort);

        // Add source identifier to each order
        foreach ( $orders as &$order ) {
            $order['source'] = 'archived';
        }

        return $orders;
    }

    /**
     * Format WooCommerce order data to match the archived order structure
     */
    private function format_woocommerce_order_data( $wc_order ) {
        // Format line items
        $line_items = [];
        foreach ( $wc_order->get_items() as $item_id => $item ) {
            $line_items[] = [
                'product_id'   => $item->get_product_id(),
                'variation_id' => $item->get_variation_id(),
                'name'         => $item->get_name(),
                'quantity'     => $item->get_quantity(),
                'price'        => $item->get_total() / $item->get_quantity(),
                'total'        => $item->get_total(),
                'subtotal'     => $item->get_subtotal(),
                'meta_data'    => $item->get_meta_data(),
            ];
        }

        return [
            'id'                   => $wc_order->get_id(),
            'date_created'         => [
                'date' => $wc_order->get_date_created()->format('Y-m-d H:i:s'),
            ],
            'date_modified'        => [
                'date' => $wc_order->get_date_modified() ? $wc_order->get_date_modified()->format('Y-m-d H:i:s') : '',
            ],
            'status'               => $wc_order->get_status(),
            'currency'             => $wc_order->get_currency(),
            'total'                => $wc_order->get_total(),
            'subtotal'             => $wc_order->get_subtotal(),
            'tax_total'            => $wc_order->get_total_tax(),
            'shipping_total'       => $wc_order->get_shipping_total(),
            'discount_total'       => $wc_order->get_discount_total(),
            'payment_method'       => $wc_order->get_payment_method(),
            'payment_method_title' => $wc_order->get_payment_method_title(),
            'transaction_id'       => $wc_order->get_transaction_id(),
            'customer_id'          => $wc_order->get_customer_id(),
            'customer_note'        => $wc_order->get_customer_note(),
            'billing'              => [
                'first_name' => $wc_order->get_billing_first_name(),
                'last_name'  => $wc_order->get_billing_last_name(),
                'company'    => $wc_order->get_billing_company(),
                'address_1'  => $wc_order->get_billing_address_1(),
                'address_2'  => $wc_order->get_billing_address_2(),
                'city'       => $wc_order->get_billing_city(),
                'state'      => $wc_order->get_billing_state(),
                'postcode'   => $wc_order->get_billing_postcode(),
                'country'    => $wc_order->get_billing_country(),
                'email'      => $wc_order->get_billing_email(),
                'phone'      => $wc_order->get_billing_phone(),
            ],
            'shipping'             => [
                'first_name' => $wc_order->get_shipping_first_name(),
                'last_name'  => $wc_order->get_shipping_last_name(),
                'company'    => $wc_order->get_shipping_company(),
                'address_1'  => $wc_order->get_shipping_address_1(),
                'address_2'  => $wc_order->get_shipping_address_2(),
                'city'       => $wc_order->get_shipping_city(),
                'state'      => $wc_order->get_shipping_state(),
                'postcode'   => $wc_order->get_shipping_postcode(),
                'country'    => $wc_order->get_shipping_country(),
            ],
            'line_items'           => $line_items,
            'shipping_lines'       => $this->format_shipping_lines($wc_order),
            'tax_lines'            => $this->format_tax_lines($wc_order),
            'fee_lines'            => $this->format_fee_lines($wc_order),
            'coupon_lines'         => $this->format_coupon_lines($wc_order),
            'meta_data'            => $this->format_meta_data($wc_order->get_meta_data()),
        ];
    }

    /**
     * Format shipping lines
     */
    private function format_shipping_lines( $wc_order ) {
        $shipping_lines = [];
        foreach ( $wc_order->get_items('shipping') as $item_id => $item ) {
            $shipping_lines[] = [
                'method_title' => $item->get_method_title(),
                'method_id'    => $item->get_method_id(),
                'total'        => $item->get_total(),
                'total_tax'    => $item->get_total_tax(),
                'meta_data'    => $item->get_meta_data(),
            ];
        }
        return $shipping_lines;
    }

    /**
     * Format tax lines
     */
    private function format_tax_lines( $wc_order ) {
        $tax_lines = [];
        foreach ( $wc_order->get_items('tax') as $item_id => $item ) {
            $tax_lines[] = [
                'rate_code'          => $item->get_rate_code(),
                'rate_id'            => $item->get_rate_id(),
                'label'              => $item->get_label(),
                'compound'           => $item->get_compound(),
                'tax_total'          => $item->get_tax_total(),
                'shipping_tax_total' => $item->get_shipping_tax_total(),
            ];
        }
        return $tax_lines;
    }

    /**
     * Format fee lines
     */
    private function format_fee_lines( $wc_order ) {
        $fee_lines = [];
        foreach ( $wc_order->get_items('fee') as $item_id => $item ) {
            $fee_lines[] = [
                'name'      => $item->get_name(),
                'total'     => $item->get_total(),
                'total_tax' => $item->get_total_tax(),
                'tax_class' => $item->get_tax_class(),
                'meta_data' => $item->get_meta_data(),
            ];
        }
        return $fee_lines;
    }

    /**
     * Format coupon lines
     */
    private function format_coupon_lines( $wc_order ) {
        $coupon_lines = [];
        foreach ( $wc_order->get_items('coupon') as $item_id => $item ) {
            $coupon_lines[] = [
                'code'         => $item->get_code(),
                'discount'     => $item->get_discount(),
                'discount_tax' => $item->get_discount_tax(),
                'meta_data'    => $item->get_meta_data(),
            ];
        }
        return $coupon_lines;
    }

    /**
     * Format meta data
     */
    private function format_meta_data( $meta_data ) {
        $formatted_meta = [];
        foreach ( $meta_data as $meta ) {
            $formatted_meta[] = [
                'key'   => $meta->key,
                'value' => $meta->value,
            ];
        }
        return $formatted_meta;
    }

    /**
     * Process a batch of orders with cancellation check
     */
    private function process_batch( $job_id, $orders, $format, $batch_number, $total_batches ) {
        // Check for cancellation before processing
        if ( $this->is_cancelled() ) {
            // error_log('Batch processing cancelled for batch ' . esc_html($batch_number));
            return;
        }

        $temp_file = $this->get_temp_file_path($job_id, $batch_number);

        switch ( $format ) {
            case 'csv':
                $this->write_csv_batch($temp_file, $orders, 1 === $batch_number);
                break;
            case 'json':
                $this->write_json_batch($temp_file, $orders);
                break;
            case 'xml':
                $this->write_xml_batch($temp_file, $orders);
                break;
            default:
                throw new \Exception('Unsupported format: ' . esc_html($format));
        }
    }

    /**
     * Write CSV batch
     */
    private function write_csv_batch( $file_path, $orders, $include_header = false ) {
        $handle = fopen($file_path, 'w'); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen

        if ( $include_header ) {
            $headers = [
                'Order ID',
                'Order Source',
                'Date Created',
                'Status',
                'Customer Name',
                'Customer Email',
                'Phone',
                'Billing Address',
                'Shipping Address',
                'Total',
                'Currency',
                'Payment Method',
                'Items',
            ];
            fputcsv($handle, $headers);
        }

        foreach ( $orders as $order ) {
            $order_data   = json_decode($order['order_data'], true);
            $order_source = isset($order['source']) ? $order['source'] : 'unknown';

            $row = [
                $order_data['id'],
                ucfirst($order_source),
                $order_data['date_created']['date'],
                $order_data['status'],
                $order_data['billing']['first_name'] . ' ' . $order_data['billing']['last_name'],
                $order_data['billing']['email'],
                $order_data['billing']['phone'] = isset($order_data['billing']['phone']) ? $order_data['billing']['phone'] : '',
                $this->format_address($order_data['billing']),
                $this->format_address(isset($order_data['shipping']) ? $order_data['shipping'] : $order_data['billing']),
                $order_data['total'] = isset($order_data['total']) ? $order_data['total'] : '',
                $order_data['currency'] = isset($order_data['currency']) ? $order_data['currency'] : '',
                $order_data['payment_method_title'] = isset($order_data['payment_method_title']) ? $order_data['payment_method_title'] : '',
                $this->format_line_items(isset($order_data['line_items']) ? $order_data['line_items'] : []),
            ];

            fputcsv($handle, $row);
        }

        fclose($handle); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
    }

    /**
     * Write JSON batch
     */
    private function write_json_batch( $file_path, $orders ) {
        $formatted_orders = [];

        foreach ( $orders as $order ) {
            $order_data   = json_decode($order['order_data'], true);
            $order_source = isset($order['source']) ? $order['source'] : 'unknown';

            $formatted_order = [
                'id'               => $order_data['id'],
                'order_source'     => ucfirst($order_source),
                'date_created'     => $order_data['date_created']['date'],
                'status'           => $order_data['status'],
                'customer'         => [
                    'name'  => $order_data['billing']['first_name'] . ' ' . $order_data['billing']['last_name'],
                    'email' => $order_data['billing']['email'],
                    'phone' => $order_data['billing']['phone'] = isset($order_data['billing']['phone']) ? $order_data['billing']['phone'] : '',
                ],
                'billing_address'  => $this->format_address_array($order_data['billing']),
                'shipping_address' => $this->format_address_array(isset($order_data['shipping']) ? $order_data['shipping'] : $order_data['billing']),
                'total'            => $order_data['total'] = isset($order_data['total']) ? $order_data['total'] : '',
                'currency'         => $order_data['currency'] = isset($order_data['currency']) ? $order_data['currency'] : '',
                'payment_method'   => $order_data['payment_method_title'] = isset($order_data['payment_method_title']) ? $order_data['payment_method_title'] : '',
                'line_items'       => $this->format_line_items_array(isset($order_data['line_items']) ? $order_data['line_items'] : []),
                'order_notes'      => $order_data['customer_note'] = isset($order_data['customer_note']) ? $order_data['customer_note'] : '',
                'meta_data'        => $order_data['meta_data'] = isset($order_data['meta_data']) ? $order_data['meta_data'] : [],
            ];

            $formatted_orders[] = $formatted_order;
        }

        file_put_contents($file_path, json_encode($formatted_orders, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
    }

    /**
     * Write XML batch
     */
    /**
     * Write XML batch
     *
     * @phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
     */
    private function write_xml_batch( $file_path, $orders ) {
        $dom                = new \DOMDocument('1.0', 'UTF-8');
        $dom->formatOutput = true; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase

        $root = $dom->createElement('orders');
        $dom->appendChild($root);

        foreach ( $orders as $order ) {
            $order_data   = json_decode($order['order_data'], true);
            $order_source = isset($order['source']) ? $order['source'] : 'unknown';

            $order_element = $dom->createElement('order');
            $root->appendChild($order_element);

            // Add order attributes
            $order_element->setAttribute('id', $order_data['id']);
            $order_element->setAttribute('status', $order_data['status']);
            $order_element->setAttribute('source', ucfirst($order_source));

            // Basic order info
            $this->add_xml_element($dom, $order_element, 'date_created', $order_data['date_created']['date']);
            $this->add_xml_element($dom, $order_element, 'total', $order_data['total'] = isset($order_data['total']) ? $order_data['total'] : '');
            $this->add_xml_element($dom, $order_element, 'currency', $order_data['currency'] = isset($order_data['currency']) ? $order_data['currency'] : '');
            $this->add_xml_element($dom, $order_element, 'payment_method', $order_data['payment_method_title'] = isset($order_data['payment_method_title']) ? $order_data['payment_method_title'] : '');

            // Customer info
            $customer_element = $dom->createElement('customer');
            $order_element->appendChild($customer_element);

            $this->add_xml_element($dom, $customer_element, 'name',
                $order_data['billing']['first_name'] . ' ' . $order_data['billing']['last_name']);
            $this->add_xml_element($dom, $customer_element, 'email', $order_data['billing']['email']);
            $this->add_xml_element($dom, $customer_element, 'phone', $order_data['billing']['phone'] = isset($order_data['billing']['phone']) ? $order_data['billing']['phone'] : '');

            // Billing address
            $billing_element = $dom->createElement('billing_address');
            $order_element->appendChild($billing_element);
            $this->add_address_to_xml($dom, $billing_element, $order_data['billing']);

            // Shipping address
            $shipping_element = $dom->createElement('shipping_address');
            $order_element->appendChild($shipping_element);
            $this->add_address_to_xml($dom, $shipping_element, isset($order_data['shipping']) ? $order_data['shipping'] : $order_data['billing']);

            // Line items
            $items_element = $dom->createElement('line_items');
            $order_element->appendChild($items_element);

            $line_items = isset($order_data['line_items']) ? $order_data['line_items'] : [];
            foreach ( $line_items as $item ) {
                $item_element = $dom->createElement('item');
                $items_element->appendChild($item_element);

                $this->add_xml_element($dom, $item_element, 'product_id', $item['product_id'] = isset($item['product_id']) ? $item['product_id'] : '');
                $this->add_xml_element($dom, $item_element, 'name', $item['name'] = isset($item['name']) ? $item['name'] : '');
                $this->add_xml_element($dom, $item_element, 'quantity', $item['quantity'] = isset($item['quantity']) ? $item['quantity'] : '');
                $this->add_xml_element($dom, $item_element, 'price', $item['price'] = isset($item['price']) ? $item['price'] : '');
                $this->add_xml_element($dom, $item_element, 'total', $item['total'] = isset($item['total']) ? $item['total'] : '');
            }

            // Order notes
            if ( ! empty($order_data['customer_note']) ) {
                $this->add_xml_element($dom, $order_element, 'customer_note', $order_data['customer_note']);
            }
        }

        $dom->save($file_path);
    }

    /**
     * Helper method to add XML element
     */
    private function add_xml_element( $dom, $parent, $name, $value ) {
        $element = $dom->createElement($name);
        $element->appendChild($dom->createTextNode($value));
        $parent->appendChild($element);
    }

    /**
     * Helper method to add address to XML
     */
    private function add_address_to_xml( $dom, $parent, $address ) {
        $fields = [ 'address_1', 'address_2', 'city', 'state', 'postcode', 'country' ];

        foreach ( $fields as $field ) {
            if ( ! empty($address[ $field ]) ) {
                $this->add_xml_element($dom, $parent, $field, $address[ $field ]);
            }
        }
    }

    /**
     * Format address for export
     */
    private function format_address( $address ) {
        if ( ! $address ) {
            return '';
        }

        $parts = [];
        if ( ! empty($address['address_1']) ) {
            $parts[] = $address['address_1'];
        }

        if ( ! empty($address['address_2']) ) {
            $parts[] = $address['address_2'];
        }

        if ( ! empty($address['city']) ) {
            $parts[] = $address['city'];
        }

        if ( ! empty($address['state']) ) {
            $parts[] = $address['state'];
        }

        if ( ! empty($address['postcode']) ) {
            $parts[] = $address['postcode'];
        }

        if ( ! empty($address['country']) ) {
            $parts[] = $address['country'];
        }

        return implode(', ', $parts);
    }

    /**
     * Format address as array for JSON export
     */
    private function format_address_array( $address ) {
        if ( ! $address ) {
            return [];
        }

        return [
            'address_1' => $address['address_1'] = isset($address['address_1']) ? $address['address_1'] : '',
            'address_2' => $address['address_2'] = isset($address['address_2']) ? $address['address_2'] : '',
            'city'      => $address['city'] = isset($address['city']) ? $address['city'] : '',
            'state'     => $address['state'] = isset($address['state']) ? $address['state'] : '',
            'postcode'  => $address['postcode'] = isset($address['postcode']) ? $address['postcode'] : '',
            'country'   => $address['country'] = isset($address['country']) ? $address['country'] : '',
        ];
    }

    /**
     * Format line items for export
     */
    private function format_line_items( $line_items ) {
        if ( ! $line_items ) {
            return '';
        }

        $items = [];
        foreach ( $line_items as $item ) {
            $items[] = ( isset($item['name']) ? $item['name'] : 'Unknown Product' ) . ' (x' . ( isset($item['quantity']) ? $item['quantity'] : 1 ) . ')';
        }

        return implode('; ', $items);
    }

    /**
     * Format line items as array for JSON export
     */
    private function format_line_items_array( $line_items ) {
        if ( ! $line_items ) {
            return [];
        }

        $items = [];
        foreach ( $line_items as $item ) {
            $items[] = [
                'product_id' => $item['product_id'] = isset($item['product_id']) ? $item['product_id'] : '',
                'name'       => $item['name'] = isset($item['name']) ? $item['name'] : '',
                'quantity'   => $item['quantity'] = isset($item['quantity']) ? $item['quantity'] : 1,
                'price'      => $item['price'] = isset($item['price']) ? $item['price'] : '',
                'total'      => $item['total'] = isset($item['total']) ? $item['total'] : '',
            ];
        }

        return $items;
    }

    /**
     * Get temporary file path for batch
     */
    private function get_temp_file_path( $job_id, $batch_number ) {
        $upload_dir = wp_upload_dir();
        $temp_dir   = $upload_dir['basedir'] . '/arcm-exports/temp/';

        if ( ! file_exists($temp_dir) ) {
            wp_mkdir_p($temp_dir);
        }

        return $temp_dir . $job_id . '_batch_' . $batch_number . '.tmp';
    }

    /**
     * Update job progress
     */
    private function update_job_progress( $job_id, $progress, $message ) {
        $jobs = get_option('arcm_export_jobs', []);
        if ( isset($jobs[ $job_id ]) ) {
            $jobs[ $job_id ]['progress']   = $progress;
            $jobs[ $job_id ]['message']    = $message;
            $jobs[ $job_id ]['updated_at'] = current_time('mysql');
            update_option('arcm_export_jobs', $jobs);
        }
    }

    /**
     * Mark job as failed
     */
    private function mark_job_failed( $job_id, $error_message ) {
        $jobs = get_option('arcm_export_jobs', []);
        if ( isset($jobs[ $job_id ]) ) {
            $jobs[ $job_id ]['status']     = 'failed';
            $jobs[ $job_id ]['message']    = $error_message;
            $jobs[ $job_id ]['progress']   = 0;
            $jobs[ $job_id ]['updated_at'] = current_time('mysql');
            update_option('arcm_export_jobs', $jobs);
        }
    }

    /**
     * Clean up temp files for a specific job
     */
    private function cleanup_temp_files_for_job( $job_id, $total_batches ) {
        $upload_dir = wp_upload_dir();
        $temp_dir   = $upload_dir['basedir'] . '/arcm-exports/temp/';

        for ( $i = 1; $i <= $total_batches; $i++ ) {
            $batch_file = $temp_dir . $job_id . '_batch_' . $i . '.tmp';
            if ( file_exists($batch_file) ) {
                wp_delete_file($batch_file);
            }
        }
    }

    /**
     * Finalize export by combining all batches
     */
    private function finalize_export( $job_id ) {
        $jobs     = get_option('arcm_export_jobs', []);
        $job_data = $jobs[ $job_id ];

        $upload_dir = wp_upload_dir();
        $temp_dir   = $upload_dir['basedir'] . '/arcm-exports/temp/';
        $final_dir  = $upload_dir['basedir'] . '/arcm-exports/';

        if ( ! file_exists($final_dir) ) {
            wp_mkdir_p($final_dir);
        }

        $source_name = 'woocommerce' === $job_data['order_source'] ? 'woocommerce' : 'archived';
        $final_file  = $final_dir . $source_name . '-orders-' . current_time('Y-m-d-H-i-s') . '.' . $job_data['format'];

        switch ( $job_data['format'] ) {
            case 'csv':
                $this->combine_csv_batches($job_id, $temp_dir, $final_file, $job_data['total_batches']);
                break;
            case 'json':
                $this->combine_json_batches($job_id, $temp_dir, $final_file, $job_data['total_batches']);
                break;
            case 'xml':
                $this->combine_xml_batches($job_id, $temp_dir, $final_file, $job_data['total_batches']);
                break;
        }

        // Clean up temp files
        $this->cleanup_temp_files($job_id, $temp_dir, $job_data['total_batches']);

        // Update job status
        $jobs[ $job_id ]['status']       = 'completed';
        $jobs[ $job_id ]['progress']     = 100;
        $jobs[ $job_id ]['message']      = 'Export completed successfully';
        $jobs[ $job_id ]['file_path']    = $final_file;
        $jobs[ $job_id ]['file_name']    = $source_name . '-orders-' . current_time('Y-m-d-H-i-s') . '.' . $job_data['format'];
        $jobs[ $job_id ]['download_url'] = $upload_dir['baseurl'] . '/arcm-exports/' . basename($final_file);
        $jobs[ $job_id ]['completed_at'] = current_time('mysql');

        update_option('arcm_export_jobs', $jobs);
    }

    /**
     * Combine CSV batches into final file
     */
    private function combine_csv_batches( $job_id, $temp_dir, $final_file, $total_batches ) {
        $final_handle = fopen($final_file, 'w'); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen

        for ( $i = 1; $i <= $total_batches; $i++ ) {
            $batch_file = $temp_dir . $job_id . '_batch_' . $i . '.tmp';
            if ( file_exists($batch_file) ) {
                $batch_handle = fopen($batch_file, 'r'); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen

                // Skip header for batches after the first one
                if ( $i > 1 ) {
                    fgetcsv($batch_handle);
                }

                while ( ( $data = fgetcsv($batch_handle) ) !== false ) {
                    fputcsv($final_handle, $data);
                }

                fclose($batch_handle); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
            }
        }

        fclose($final_handle); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
    }

    /**
     * Combine JSON batches into final file
     */
    private function combine_json_batches( $job_id, $temp_dir, $final_file, $total_batches ) {
        $all_orders = [];

        for ( $i = 1; $i <= $total_batches; $i++ ) {
            $batch_file = $temp_dir . $job_id . '_batch_' . $i . '.tmp';
            if ( file_exists($batch_file) ) {
                $batch_data = json_decode(file_get_contents($batch_file), true);
                if ( is_array($batch_data) ) {
                    $all_orders = array_merge($all_orders, $batch_data);
                }
            }
        }

        file_put_contents($final_file, json_encode($all_orders, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
    }

    /**
     * Combine XML batches into final file
     */
    private function combine_xml_batches( $job_id, $temp_dir, $final_file, $total_batches ) {
        $final_dom               = new \DOMDocument('1.0', 'UTF-8');
        $final_dom->formatOutput = true; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase

        $final_root = $final_dom->createElement('orders');
        $final_dom->appendChild($final_root);

        for ( $i = 1; $i <= $total_batches; $i++ ) {
            $batch_file = $temp_dir . $job_id . '_batch_' . $i . '.tmp';
            if ( file_exists($batch_file) ) {
                $batch_dom = new \DOMDocument();
                $batch_dom->load($batch_file);

                $batch_orders = $batch_dom->getElementsByTagName('order');

                foreach ( $batch_orders as $order ) {
                    $imported_order = $final_dom->importNode($order, true);
                    $final_root->appendChild($imported_order);
                }
            }
        }

        $final_dom->save($final_file);
    }

    /**
     * Clean up temporary files
     */
    private function cleanup_temp_files( $job_id, $temp_dir, $total_batches ) {
        for ( $i = 1; $i <= $total_batches; $i++ ) {
            $batch_file = $temp_dir . $job_id . '_batch_' . $i . '.tmp';
            if ( file_exists($batch_file) ) {
                wp_delete_file($batch_file);
            }
        }
    }

    /**
     * Clean up old export files
     */
    public function cleanup_old_exports() {
        $upload_dir = wp_upload_dir();
        $export_dir = $upload_dir['basedir'] . '/arcm-exports/';

        if ( ! file_exists($export_dir) ) {
            return;
        }

        $files       = glob($export_dir . '*');
        $cutoff_time = time() - ( 2 * 24 * 60 * 60 ); // 2 days ago

        foreach ( $files as $file ) {
            if ( is_file($file) && filemtime($file) < $cutoff_time ) {
                wp_delete_file($file);
            }
        }

        // Clean up old job records
        $jobs = get_option('arcm_export_jobs', []);
        foreach ( $jobs as $job_id => $job_data ) {
            $created_time = strtotime($job_data['created_at']);
            if ( $created_time < $cutoff_time ) {
                unset($jobs[ $job_id ]);
            }
        }
        update_option('arcm_export_jobs', $jobs);
    }
}
