<?php
namespace ARCHM\Features;

use ARCHM\Helpers\Logger;

class BackgroundProcess extends \WP_Background_Process {


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

    /**
     * Backgoud corn prefix
     *
     * @var string
     */
    protected $prefix = 'master';

    /**
     * Background hook name
     *
     * @var string
     */
    protected $action = 'archive_background_process';

    /**
     * Batch size
     *
     * @var int
     */
    // phpcs:ignore PHPCompatibility.Classes.NewTypedProperties.Found
    protected int $batch_size = 1;

    /**
     * Timeout.
     *
     * @var int
     */
    // phpcs:ignore PHPCompatibility.Classes.NewTypedProperties.Found
    protected int $timeout = 40;

    /**
     * Class constructor
     */
    public function __construct() {
        parent::__construct();
        $this->set_remote_db_settings();
        $this->set_main_deb_settings();
    }

    /**
     * Task handler with cancellation check
     *
     * @param mixed $item
     * @return false
     */
    // phpcs:ignore PHPCompatibility.FunctionDeclarations.NewReturnTypeDeclarations.class_nameFound
    protected function task( $item ): mixed {
        // Check if cancellation was requested before processing
        if ( $this->is_cancelled() ) {
            // Logger::logMessage('Archive process cancelled - stopping task processing');
            return false; // Stop processing further tasks
        }

        if ( get_option('archm_background_process_stop') ) {
            return false; // Stop processing further tasks
        }

        $log_DB            = new ActivityLogDB(); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
        $post_id           = $item['post_id'];
        $is_archived_data  = false;
        $selected_database = get_option('archm_selected_database', 'sqlite');

        // Step 1: Retrieve the completed order from the main database
        $main_order = wc_get_order($post_id);
        if ( ! $main_order ) {
            // Logger::logMessage('Order ID #' . esc_html($post_id) . ' not found - skipping');
            return false; // Order not found, exit the function
        }

        // Check if subscription exclusion is enabled
        $exclude_subscriptions = get_option('archm_exclude_subscriptions', false);

        // Only check for subscription orders if exclusion is enabled
        if ( $exclude_subscriptions && class_exists('\ARCHM\Helpers\SubscriptionHelper') && \ARCHM\Helpers\SubscriptionHelper::is_subscription_order($main_order) ) {
            // Logger::logMessage('Order ID #' . esc_html($post_id) . ' excluded from archiving (subscription order)');

            // Update the total count to exclude this subscription order
            // $total_orders = get_option('archm_archive_orders_count', 0);
            // if ($total_orders > 0) {
            //     update_option('archm_archive_orders_count', $total_orders - 1);
            // }

            $archieved_order   = get_option('archm_queue_batch_ids', []);
            $archieved_order[] = $post_id;
            update_option('archm_queue_batch_ids', $archieved_order);

            return false; // Skip subscription orders
        }

        // Check if membership exclusion is enabled
        $exclude_memberships = get_option('archm_exclude_memberships', false);

        // Only check for membership orders if exclusion is enabled
        if ( $exclude_memberships && class_exists('\ARCHM\Helpers\MembershipHelper') && \ARCHM\Helpers\MembershipHelper::is_membership_order($main_order) ) {
            // Logger::logMessage('Order ID #' . esc_html($post_id) . ' excluded from archiving (membership order)');

            // Update the total count to exclude this membership order
            // $total_orders = get_option('archm_archive_orders_count', 0);
            // if ($total_orders > 0) {
            //     update_option('archm_archive_orders_count', $total_orders - 1);
            // }

            $archieved_order   = get_option('archm_queue_batch_ids', []);
            $archieved_order[] = $post_id;
            update_option('archm_queue_batch_ids', $archieved_order);

            return false; // Skip membership orders
        }

        // Check for cancellation before processing order
        if ( $this->is_cancelled() ) {
            // Logger::logMessage('Archive process cancelled during order ' . esc_html($post_id) . ' processing');
            return false;
        }

        // Check advanced order filtering (Pro feature)
        if ( function_exists('master_archive_pro') && class_exists('\ARCHM_PRO\Features\AdvancedOrderFilterEvaluator') ) {
            $filter_evaluator = \ARCHM_PRO\Features\AdvancedOrderFilterEvaluator::get_instance();
            if ( ! $filter_evaluator->should_archive_order($main_order) ) {
                // Order doesn't match advanced filter criteria, skip archiving
                $archieved_order   = get_option('archm_queue_batch_ids', []);
                $archieved_order[] = $post_id;
                update_option('archm_queue_batch_ids', $archieved_order);
                return false; // Skip this order
            }
        }

        // Check advanced order filtering (Pro feature)
        if ( function_exists('master_archive_pro') && class_exists('\ARCHM_PRO\Features\AdvancedOrderFilterEvaluator') ) {
            $filter_evaluator = \ARCHM_PRO\Features\AdvancedOrderFilterEvaluator::get_instance();
            if ( ! $filter_evaluator->should_archive_order($main_order) ) {
                // Order doesn't match advanced filter criteria, skip archiving
                $archieved_order   = get_option('archm_queue_batch_ids', []);
                $archieved_order[] = $post_id;
                update_option('archm_queue_batch_ids', $archieved_order);
                return false; // Skip this order
            }
        }

        $oder_products = [];

        // Copy items from the main order to the remote order
        foreach ( $main_order->get_items() as $item_id => $item ) {
            if ( is_a($item, 'WC_Order_Item_Product') ) {
                $oder_products[] = [
                    'product_id'   => $item->get_product_id(),
                    'variation_id' => $item->get_variation_id(),
                    'quantity'     => $item->get_quantity(),
                    'total'        => $item->get_total(),
                    'sub_total'    => $item->get_subtotal(),
                    'line_tax'     => $item->get_total_tax(),
                ];

            }
        }

        // Extract coupon data for proper archiving
        $coupon_data = [];
        foreach ( $main_order->get_items('coupon') as $item_id => $coupon_item ) {
            if ( is_a($coupon_item, 'WC_Order_Item_Coupon') ) {
                $coupon_meta_data = [];
                foreach ( $coupon_item->get_meta_data() as $meta ) {
                    $coupon_meta_data[] = [
                        'key'   => $meta->key,
                        'value' => $meta->value,
                    ];
                }
                $coupon_data[] = [
                    'code'         => $coupon_item->get_code(),
                    'discount'     => $coupon_item->get_discount(),
                    'discount_tax' => $coupon_item->get_discount_tax(),
                    'meta_data'    => $coupon_meta_data,
                ];
            }
        }

        // Extract tax data for proper archiving
        $tax_data = [];
        foreach ( $main_order->get_items('tax') as $item_id => $tax_item ) {
            if ( is_a($tax_item, 'WC_Order_Item_Tax') ) {
                $tax_meta_data = [];
                foreach ( $tax_item->get_meta_data() as $meta ) {
                    $tax_meta_data[] = [
                        'key'   => $meta->key,
                        'value' => $meta->value,
                    ];
                }
                $tax_data[] = [
                    'rate_code'          => $tax_item->get_rate_code(),
                    'rate_id'            => $tax_item->get_rate_id(),
                    'label'              => $tax_item->get_label(),
                    'compound'           => $tax_item->get_compound(),
                    'tax_total'          => $tax_item->get_tax_total(),
                    'shipping_tax_total' => $tax_item->get_shipping_tax_total(),
                    'meta_data'          => $tax_meta_data,
                ];
            }
        }

        // Check for cancellation before database operations
        if ( $this->is_cancelled() ) {
            // Logger::logMessage('Archive process cancelled before database operations for order ' . esc_html($post_id));
            return false;
        }

        // Step 1: Always store to SQLite first (primary storage)
        if ( 'sqlite' === $selected_database || 'google_drive' === $selected_database ) {
            $sqdb             = Sqlite::get_instance();
            $is_archived_data = $sqdb->insert_archived_order($main_order, $oder_products);

            if ( ! $is_archived_data ) {
                /*  Logger::logMessage('Failed to archive to SQLite (primary storage) for order ' . esc_html($post_id)); */
                return false; // If primary storage fails, don't proceed
            }

            /* Logger::logMessage('Successfully archived to SQLite (primary storage) for order ' . esc_html($post_id)); */
        }

        // Step 2: Store to secondary storage based on selected database
        if ( 'rds' === $selected_database || 'custom_mysql' === $selected_database ) {
            // Ensure remote db settings are loaded
            if ( empty($this->db_host) || empty($this->db_name) ) {
                $this->set_remote_db_settings();
            }

            // Set remote db instance
            $this->set_db_instance();

            // Check if remote_db was initialized before using it
            if ( null === $this->remote_db || ! isset($this->remote_db) ) {
                // Remote DB not initialized - skip this order if database connection failed
                return false;
            }

            $table_name = $this->wpdb->prefix . 'archived_orders';

            // Get order data and enhance it with complete coupon and tax information
            $order_data = $main_order->get_data();
            // Replace coupon_lines with complete coupon data
            if ( ! empty($coupon_data) ) {
                $order_data['coupon_lines'] = $coupon_data;
            }
            // Replace tax_lines with complete tax data
            if ( ! empty($tax_data) ) {
                $order_data['tax_lines'] = $tax_data;
            }

            // Include custom order meta keys if enabled and selected
            $enable_custom_meta = get_option('archm_enable_related_order_metadata_archiving', false);
            if ( $enable_custom_meta ) {
                $selected_meta_keys = get_option('archm_related_order_metadata_selected', []);
                if ( ! empty($selected_meta_keys) && is_array($selected_meta_keys) ) {
                    $custom_meta = [];
                    foreach ( $selected_meta_keys as $meta_key ) {
                        $meta_value = $main_order->get_meta($meta_key);
                        if ( '' !== $meta_value ) {
                            $custom_meta[ $meta_key ] = $meta_value;
                        }
                    }
                    if ( ! empty($custom_meta) ) {
                        $order_data['custom_meta'] = $custom_meta;
                    }
                }
            }

            $data = [
                'archived_order_id' => $main_order->get_id(),
                'order_data'        => wp_json_encode($order_data),
                'ordered_products'  => wp_json_encode($oder_products),
                'date'              => current_time('mysql'),
            ];

            $inserted = $this->remote_db->insert($table_name, $data);

            // Commented out empty IF/ELSE block to fix PHPCS error
            /*
            if ( false === $inserted ) {
                // Logger::logMessage('Order archive failed');
                // No action needed for failed insert
            } else {
                // Logger::logMessage('Successfully order archived for rds');
                $is_archived_data = true;
            }
            */

            // Simplified logic to avoid empty statements
            if ( false !== $inserted ) {
                // Logger::logMessage('Successfully order archived for rds');
                $is_archived_data = true;
            }
        }

        if ( $is_archived_data ) {
            // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
            $log_DB->insert_log([
                'activity' => 'Order ID #' . esc_html($post_id) . ' have been archived.',
            ]);

            // store the archived order
            $archieved_order   = get_option('archm_queue_batch_ids', []);
            $archieved_order[] = $post_id;
            update_option('archm_queue_batch_ids', $archieved_order);

            $wc_delteable_order = wc_get_order($post_id);

            // Aggregate analytics data before deleting order (Pro feature)
            $sync_enabled = get_option('archm_analytics_sync_enabled', false);
            if ( $sync_enabled && function_exists('master_archive_pro') && class_exists('\ARCHM_PRO\Features\AnalyticsAggregator') ) {
                try {
                    $aggregator = \ARCHM_PRO\Features\AnalyticsAggregator::get_instance();
                    $aggregator->aggregate_order($main_order, $oder_products);
                } catch ( \Exception $e ) {
                    // Log error but don't stop archiving process
                    \ARCHM\Helpers\Logger::logMessage('Failed to aggregate analytics for order #' . $post_id . ': ' . $e->getMessage());
                }
            }

            $wc_delteable_order->delete(true);

            // Trigger action hook for analytics cache clearing
            do_action('archm_order_archived', $post_id);
        }

        return false;
    }

    /**
     * Complete
     *
     * Override if applicable, but ensure that the below actions are
     * performed, or, call parent::complete().
     */
    // phpcs:ignore PHPCompatibility.FunctionDeclarations.NewReturnTypeDeclarations.voidFound
    protected function complete(): void {
        parent::complete();
        $archived_orders = count(get_option('archm_queue_batch_ids', []));
        update_option('archm_last_archive_order', current_time('mysql'));
        update_option('archm_background_process_running', false);
        // Logger::logMessage('Total archived orders: ' . $archived_orders);
            // Logger::logMessage('Background process finished');

            // Trigger bulk archive hook for cache clearing when multiple orders were archived
        if ( $archived_orders > 0 ) {
            do_action('archm_orders_bulk_archived', $archived_orders);

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

            // 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');
            }
        }

        // Update analytics cache version to invalidate WooCommerce cache
        $sync_enabled = get_option('archm_analytics_sync_enabled', false);
        if ( $sync_enabled && $archived_orders > 0 ) {
            update_option('archived_analytics_version', time());
        }

        if ( get_option('archm_corn_archive_running') || get_option('archm_bg_bulk_archive') ) {
            delete_option('archm_queue_batch_ids');
            delete_option('archm_corn_archive_running');
            delete_option('archm_bg_bulk_archive');
        }
    }

    // phpcs:ignore PHPCompatibility.FunctionDeclarations.NewReturnTypeDeclarations.voidFound
    private function insertBatch( $db, $table, $data ): void {
        if ( empty($data) ) {
            return;
        }

        $first_row    = current($data);
        $keys         = array_keys($first_row);
        $sql          = 'INSERT INTO ' . $table . ' (' . implode(', ', $keys) . ') VALUES ';
        $placeholders = '(' . rtrim(str_repeat('%s, ', count($keys)), ', ') . ')';

        $insert_values = [];
        $params        = [];
        foreach ( $data as $row ) {
            $insert_values[] = $db->prepare($placeholders, array_values($row));
            $params          = array_merge($params, array_values($row));
        }

        $sql .= implode(', ', $insert_values);
        $db->query($db->prepare($sql, $params));
    }

    // phpcs:ignore PHPCompatibility.FunctionDeclarations.NewReturnTypeDeclarations.boolFound
    private function post_exists_by_title( $title, $remote_db, $post_type = 'post' ): bool {
        global $wpdb;
        $post_table = $wpdb->prefix . 'posts';
        $query      = $remote_db->prepare(
            "SELECT ID
	         FROM `$post_table`
	         WHERE post_title = %s
	         AND post_type = %s
	         LIMIT 1", $title, $post_type
        );

        $post_id = $remote_db->get_var($query);
        return ! is_null($post_id);
    }

    /**
     * Improved stop background process with proper cleanup
     */
    public function stop_archive_process() {
        try {
            // Verify user permissions
            if ( ! current_user_can('manage_options') ) {
                wp_die('Unauthorized');
            }

            // Set cancellation flags
            update_option('archm_background_process_stop', true);
            update_option('archm_archive_cancelled', true);

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

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

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

            // Clean up running flags
            update_option('archm_background_process_running', false);
            delete_option('archm_corn_archive_running');

            // Logger::logMessage('Archive background process cancelled successfully');
        } catch ( \Exception $e ) {
            // Exception handled silently for background process
            Logger::logMessage('Error cancelling archive process: ' . $e->getMessage());
        }
    }

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

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

    // phpcs:ignore PHPCompatibility.FunctionDeclarations.NewReturnTypeDeclarations.boolFound
    public function is_processing(): bool {
        return ! $this->is_queue_empty();
    }

    public function stop_background_process() {
        $this->clear_scheduled_event();
    }
}
