<?php
/**
 * Bulk Archive Handler
 * Handles bulk archive operations for WooCommerce orders
 *
 * @since 1.8.3
 * @package ArchiveMaster
 */

namespace ARCHM\Admin;

use ARCHM\Features\BackgroundProcess;
use ARCHM\Helpers\BGProcessHelper;
use ARCHM\Helpers\DBHelper;
use Automattic\WooCommerce\Utilities\OrderUtil;

// Exit if accessed directly.
defined('ABSPATH') || exit(1);

if ( ! class_exists(__NAMESPACE__ . '\BulkArchiveHandler') ) {
    /**
     * Bulk Archive Handler Class
     *
     * @since 1.8.3
     */
    class BulkArchiveHandler {

        // Use DBHelper trait for database operations
        use DBHelper;
        // Use BGProcessHelper trait for background processing
        use BGProcessHelper;

        /**
         * Class constructor
         */
        public function __construct() {
            // Set up database settings
            $this->set_remote_db_settings();
            $this->set_main_deb_settings();

            // Register bulk actions for classic orders (post type)
            add_filter('bulk_actions-edit-shop_order', [ $this, 'register_bulk_actions' ], 10, 1);

            // Register bulk actions for HPOS orders
            add_filter('bulk_actions-woocommerce_page_wc-orders', [ $this, 'register_bulk_actions' ], 10, 1);

            // Handle bulk action execution for classic orders
            add_filter('handle_bulk_actions-edit-shop_order', [ $this, 'handle_bulk_archive' ], 10, 3);

            // Handle bulk action execution for HPOS orders
            add_filter('handle_bulk_actions-woocommerce_page_wc-orders', [ $this, 'handle_bulk_archive' ], 10, 3);

            // Display admin notices
            add_action('admin_notices', [ $this, 'display_admin_notices' ]);
        }

        /**
         * Register bulk actions
         *
         * @param array $bulk_actions Existing bulk actions
         * @return array Modified bulk actions
         */
        public function register_bulk_actions( $bulk_actions ) {
            // Bulk archive is always enabled
            $bulk_actions['archm_archive_order'] = __('Archive Order', 'archive-master');

            return $bulk_actions;
        }

        /**
         * Handle bulk archive action
         *
         * @param string $redirect_to Redirect URL
         * @param string $action Action name
         * @param array  $order_ids Array of order IDs
         * @return string Modified redirect URL
         */
        public function handle_bulk_archive( $redirect_to, $action, $order_ids ) {
            // Check if this is our bulk action
            if ( 'archm_archive_order' !== $action ) {
                return $redirect_to;
            }

            // Check user permissions
            if ( ! current_user_can('manage_options') ) {
                wp_die(esc_html__('You do not have permission to perform this action.', 'archive-master'));
            }

            // Validate order IDs
            if ( empty($order_ids) || ! is_array($order_ids) ) {
                return add_query_arg(
                    [
                        'archm_bulk_archived' => 0,
                        'archm_bulk_failed'   => 0,
                        'archm_bulk_error'    => urlencode(__('No orders selected.', 'archive-master')),
                    ],
                    $redirect_to
                );
            }

            // Get selected database type
            $selected_database = get_option('archm_selected_database', 'sqlite');

            // Check database connection and setup
            $db_check = $this->validate_database_connection($selected_database);
            if ( ! $db_check['success'] ) {
                return add_query_arg(
                    [
                        'archm_bulk_archived' => 0,
                        'archm_bulk_failed'   => count($order_ids),
                        'archm_bulk_error'    => urlencode($db_check['message']),
                    ],
                    $redirect_to
                );
            }

            // Validate and sanitize order IDs
            $valid_order_ids = [];
            foreach ( $order_ids as $order_id ) {
                $order_id = absint($order_id);
                if ( $order_id > 0 ) {
                    // Verify order exists and is not already trashed
                    $order = wc_get_order($order_id);
                    if ( $order && 'trash' !== $order->get_status() ) {
                        // Check subscription exclusion
                        $exclude_subscriptions = get_option('archm_exclude_subscriptions', false);
                        if ( $exclude_subscriptions && class_exists('\ARCHM\Helpers\SubscriptionHelper') ) {
                            if ( \ARCHM\Helpers\SubscriptionHelper::is_subscription_order($order) ) {
                                continue; // Skip subscription orders
                            }
                        }

                        // Check membership exclusion
                        $exclude_memberships = get_option('archm_exclude_memberships', false);
                        if ( $exclude_memberships && class_exists('\ARCHM\Helpers\MembershipHelper') ) {
                            if ( \ARCHM\Helpers\MembershipHelper::is_membership_order($order) ) {
                                continue; // Skip membership orders
                            }
                        }

                        $valid_order_ids[] = $order_id;
                    }
                }
            }

            if ( empty($valid_order_ids) ) {
                return add_query_arg(
                    [
                        'archm_bulk_archived' => 0,
                        'archm_bulk_failed'   => count($order_ids),
                        'archm_bulk_error'    => urlencode(__('No valid orders to archive.', 'archive-master')),
                    ],
                    $redirect_to
                );
            }

            update_option('archm_bg_bulk_archive', true);

            // Initialize background process
            $background_process = new BackgroundProcess();

            // Start background process with valid order IDs
            // Note: The 'archm_orders_bulk_archived' hook will be triggered automatically
            // when the background process completes (see BackgroundProcess::complete())
            // This ensures the archived orders count cache is cleared after bulk archiving
            $process_started = $this->start_background_process($background_process, $valid_order_ids);

            if ( $process_started ) {
                // Build redirect URL with results
                $redirect_args = [
                    'archm_bulk_queued' => count($valid_order_ids),
                    'archm_bulk_total'  => count($order_ids),
                ];

                return add_query_arg($redirect_args, $redirect_to);
            } else {
                return add_query_arg(
                    [
                        'archm_bulk_archived' => 0,
                        'archm_bulk_failed'   => count($order_ids),
                        'archm_bulk_error'    => urlencode(__('Failed to start background archive process.', 'archive-master')),
                    ],
                    $redirect_to
                );
            }
        }


        /**
         * Validate database connection
         *
         * @param string $selected_database Database type
         * @return array Result array
         */
        private function validate_database_connection( $selected_database ) {
            if ( 'sqlite' === $selected_database || 'google_drive' === $selected_database ) {
                if ( ! extension_loaded('pdo_sqlite') ) {
                    return [
                        'success' => false,
                        'message' => __('SQLite PDO extension is not loaded. Please enable SQLite support.', 'archive-master'),
                    ];
                }

                // Create SQLite database file if it doesn't exist
                $sqlite = \ARCHM\Features\Sqlite::get_instance();
                if ( ! $sqlite->create_database_for_archiving() ) {
                    return [
                        'success' => false,
                        'message' => __('Failed to create SQLite database file for archiving. Please check file permissions.', 'archive-master'),
                    ];
                }
            } elseif ( 'rds' === $selected_database || 'custom_mysql' === $selected_database ) {
                if ( ! $this->is_bd_connected() ) {
                    return [
                        'success' => false,
                        'message' => __('Remote database is not connected. Please check your database settings.', 'archive-master'),
                    ];
                }
            }

            return [
                'success' => true,
                'message' => __('Database connection validated.', 'archive-master'),
            ];
        }

        /**
         * Display admin notices for bulk archive results
         */
        public function display_admin_notices() {
            // Only show on orders page
            $screen = get_current_screen();
            if ( ! $screen ) {
                return;
            }

            $is_orders_page = false;
            if ( OrderUtil::custom_orders_table_usage_is_enabled() ) {
                $is_orders_page = ( 'woocommerce_page_wc-orders' === $screen->id );
            } else {
                $is_orders_page = ( 'edit-shop_order' === $screen->id );
            }

            if ( ! $is_orders_page ) {
                return;
            }

            // Check for bulk archive queue results
            if ( ! isset($_GET['archm_bulk_queued']) && ! isset($_GET['archm_bulk_archived']) && ! isset($_GET['archm_bulk_failed']) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
                return;
            }

            // Handle background process queue notice
            if ( isset($_GET['archm_bulk_queued']) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
                $queued_count = absint($_GET['archm_bulk_queued']); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
                $total_count  = isset($_GET['archm_bulk_total']) ? absint($_GET['archm_bulk_total']) : $queued_count; // phpcs:ignore WordPress.Security.NonceVerification.Recommended

                if ( $queued_count > 0 ) {
                    $message = sprintf(
                        // translators: %1$d is queued count, %2$d is total count
                        _n(
                            '%1$d order has been queued for archiving in the background.',
                            '%1$d orders have been queued for archiving in the background.',
                            $queued_count,
                            'archive-master'
                        ),
                        $queued_count
                    );

                    if ( $queued_count < $total_count ) {
                        $skipped = $total_count - $queued_count;
                        $message .= ' ' . sprintf(
                            // translators: %d is the number of skipped orders
                            _n(
                                '%d order was skipped (invalid or excluded).',
                                '%d orders were skipped (invalid or excluded).',
                                $skipped,
                                'archive-master'
                            ),
                            $skipped
                        );
                    }

                    echo '<div class="notice notice-info is-dismissible"><p>' . esc_html($message) . '</p></div>';
                }
            }

            // Handle legacy archived/failed notices (for backward compatibility)
            $archived_count = isset($_GET['archm_bulk_archived']) ? absint($_GET['archm_bulk_archived']) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $failed_count   = isset($_GET['archm_bulk_failed']) ? absint($_GET['archm_bulk_failed']) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $error_message   = isset($_GET['archm_bulk_error']) ? sanitize_text_field(wp_unslash($_GET['archm_bulk_error'])) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended

            // Display error notice
            if ( $failed_count > 0 ) {
                $message = sprintf(
                    // translators: %d is the number of orders that failed
                    _n(
                        '%d order could not be queued for archiving.',
                        '%d orders could not be queued for archiving.',
                        $failed_count,
                        'archive-master'
                    ),
                    $failed_count
                );

                if ( ! empty($error_message) ) {
                    $message .= ' ' . esc_html($error_message);
                }

                echo '<div class="notice notice-error is-dismissible"><p>' . esc_html($message) . '</p></div>';
            }

            // Clean URL parameters after notices are displayed to prevent them from reappearing on reload
            $this->clean_bulk_notice_url_params();
        }

        /**
         * Clean URL parameters after bulk archive notices are displayed
         * Prevents notices from reappearing on page reload
         *
         * @return void
         */
        // phpcs:ignore PHPCompatibility.FunctionDeclarations.NewReturnTypeDeclarations.voidFound
        private function clean_bulk_notice_url_params(): void {
            // Only clean if we're on the orders page and have bulk notice parameters
            $has_bulk_params = isset($_GET['archm_bulk_queued']) ||
                             isset($_GET['archm_bulk_archived']) ||
                             isset($_GET['archm_bulk_failed']) ||
                             isset($_GET['archm_bulk_error']) ||
                             isset($_GET['archm_bulk_total']); // phpcs:ignore WordPress.Security.NonceVerification.Recommended

            if ( ! $has_bulk_params ) {
                return;
            }

            // Output JavaScript to clean URL parameters without page reload
            // Wait for DOM to be ready to ensure notices are displayed first
            ?>
            <script type="text/javascript">
            (function() {
                function cleanBulkNoticeParams() {
                    if (typeof window.history !== 'undefined' && window.history.replaceState) {
                        // Get current URL without bulk archive parameters
                        var url = new URL(window.location.href);
                        var paramsToRemove = ['archm_bulk_queued', 'archm_bulk_archived', 'archm_bulk_failed', 'archm_bulk_error', 'archm_bulk_total'];
                        
                        paramsToRemove.forEach(function(param) {
                            url.searchParams.delete(param);
                        });
                        
                        // Replace URL without reloading the page
                        window.history.replaceState({}, '', url.toString());
                    }
                }
                
                // Clean URL after DOM is ready
                if (document.readyState === 'loading') {
                    document.addEventListener('DOMContentLoaded', cleanBulkNoticeParams);
                } else {
                    // DOM is already ready
                    cleanBulkNoticeParams();
                }
            })();
            </script>
            <?php
        }
    }
}
