<?php

namespace BWDK\Woo\Order;

use BWDK\Enums\BWDK_OrderStatus;
use BWDK\Support\Constant;
use Automattic\WooCommerce\Internal\Utilities\COTMigrationUtil;
use WC_Order;

if (!defined('ABSPATH')) exit;

/**
 * Bulk refresh+verify recent BWDK orders from WooCommerce Orders list screen.
 *
 * UI: Top actions area (above orders table).
 * Engine: Reuses OrderSyncService::refresh_from_bwdk().
 */
class BulkVerifyBwdkOrders
{
    const ACTION = 'bwdk_bulk_verify_orders';
    const NONCE_ACTION = 'bwdk_bulk_verify_orders';
    const NONCE_QUERY_ARG = 'bwdk_bulk_verify_nonce';

    const NOTICE_TRANSIENT_PREFIX = 'bwdk_bulk_verify_notice_u';
    const STATE_TRANSIENT_PREFIX  = 'bwdk_bulk_verify_state_u';

    /** Safety: max eligible IDs loaded per run. */
    const MAX_ELIGIBLE_IDS = 5000;

    /** Process size per request. */
    const BATCH_SIZE = 20;
    const DEFAULT_LIMIT = 20;
    const MIN_LIMIT = 1;
    const MAX_LIMIT = 200;
    const RETURN_URL_ARG = 'bwdk_bulk_verify_return_url';

    /** Prevent rendering toolbar twice on same screen. */
    private static bool $toolbar_rendered = false;
    /** Prevent rendering notice twice (admin_notices + all_admin_notices). */
    private static bool $notice_rendered = false;

    const RESULT_TRANSIENT_PREFIX = 'bwdk_bulk_verify_result_';

    public function register(): void
    {
        // Render a compact block above the orders table (top tablenav), not inside Woo filters.
        // Legacy posts table.
        add_action('manage_posts_extra_tablenav', [$this, 'renderToolbarLegacy'], 20, 1);
        // HPOS orders table.
        add_action('woocommerce_order_list_table_extra_tablenav', [$this, 'renderToolbarHpos'], 20, 1);

        add_action('admin_post_' . self::ACTION, [$this, 'handle']);
        // Fallback render for stores/Woo versions where extra_tablenav hooks don't run.
        add_action('all_admin_notices', [$this, 'renderToolbarFallback'], 5);
        // Notice on both hooks (HPOS screens may behave differently).
        add_action('all_admin_notices', [$this, 'renderNotice'], 20);
        add_action('admin_notices', [$this, 'renderNotice'], 20);

        // Small script to show loading state without preventing navigation.
        add_action('admin_enqueue_scripts', [$this, 'enqueueAssets']);
    }

    public function enqueueAssets(): void
    {
        $screen = function_exists('get_current_screen') ? get_current_screen() : null;
        if (!$screen || ($screen->id !== 'edit-shop_order' && $screen->id !== 'woocommerce_page_wc-orders')) {
            return;
        }

        if (!defined('BWDK_ADMIN_JS')) {
            return;
        }

        wp_enqueue_script(
            'bwdk-bulk-verify',
            BWDK_ADMIN_JS . 'bwdk-bulk-verify.js',
            [],
            '1.0.0',
            true
        );
    }

    public function renderToolbarLegacy(string $which = ''): void
    {
        $this->log_toolbar_attempt(current_filter());

        $screen = function_exists('get_current_screen') ? get_current_screen() : null;
        if (!$this->isOrdersListScreen($screen)) {
            $this->log_toolbar_return('unsupported_screen', current_filter());
            return;
        }
        if ($which !== '' && $which !== 'top') {
            $this->log_toolbar_return('not_top', current_filter());
            return;
        }
        $this->renderToolbar();
    }

    public function renderToolbarHpos(string $which = ''): void
    {
        $this->log_toolbar_attempt(current_filter());

        $screen = function_exists('get_current_screen') ? get_current_screen() : null;
        if (!$this->isOrdersListScreen($screen)) {
            $this->log_toolbar_return('unsupported_screen', current_filter());
            return;
        }
        if ($which !== '' && $which !== 'top') {
            $this->log_toolbar_return('not_top', current_filter());
            return;
        }
        $this->renderToolbar();
    }

    /**
     * Fallback toolbar render: prints above content via admin_notices region
     * (outside WooCommerce filters/bulk-action forms).
     */
    public function renderToolbarFallback(): void
    {
        $this->log_toolbar_attempt(current_filter());

        if (self::$toolbar_rendered) {
            $this->log_toolbar_return('already_rendered', current_filter());
            return;
        }
        $screen = function_exists('get_current_screen') ? get_current_screen() : null;
        if (!$screen) {
            $this->log_toolbar_return('no_screen', current_filter());
            return;
        }
        if (!$this->isOrdersListScreen($screen)) {
            $this->log_toolbar_return('unsupported_screen', current_filter());
            return;
        }
        $this->renderToolbar();
    }

    protected function renderToolbar(): void
    {
        if (self::$toolbar_rendered) {
            $this->log_toolbar_return('already_rendered', current_filter());
            return;
        }
        if (!current_user_can('edit_shop_orders') && !current_user_can('manage_woocommerce')) {
            $this->log_toolbar_return('missing_capability', current_filter());
            return;
        }

        $action_url = admin_url('admin-post.php');
        $limit_default = self::DEFAULT_LIMIT;
        $return_url = $this->defaultReturnUrlForCurrentScreen();
        ?>
        <?php self::$toolbar_rendered = true; ?>
        <!-- BWDK bulk verify toolbar rendered via <?php echo esc_html(current_filter()); ?> -->
        <div class="notice notice-info bwdk-bulk-verify-toolbar-wrap" style="padding:10px 12px;">
        <div class="bwdk-bulk-verify-toolbar" style="display:flex;align-items:center;gap:10px;flex-wrap:wrap;">
            <form method="get" action="<?php echo esc_url($action_url); ?>" class="bwdk-bulk-verify-form">
                <input type="hidden" name="action" value="<?php echo esc_attr(self::ACTION); ?>" />
                <input type="hidden" name="<?php echo esc_attr(self::NONCE_QUERY_ARG); ?>" value="<?php echo esc_attr(wp_create_nonce(self::NONCE_ACTION)); ?>" />
                <input type="hidden" name="<?php echo esc_attr(self::RETURN_URL_ARG); ?>" value="<?php echo esc_attr($return_url); ?>" />

                <label for="bwdk_bulk_verify_limit">
                    <?php echo esc_html__('تعداد سفارش برای بررسی:', 'buy-with-digikala'); ?>
                </label>

                <input
                    type="number"
                    id="bwdk_bulk_verify_limit"
                    name="bwdk_bulk_verify_limit"
                    value="<?php echo esc_attr((string) $limit_default); ?>"
                    min="<?php echo esc_attr((string) self::MIN_LIMIT); ?>"
                    max="<?php echo esc_attr((string) self::MAX_LIMIT); ?>"
                    step="1"
                    style="width:70px;"
                />

                <button type="submit" class="button button-primary" data-bwdk-bulk-verify-button="1">
                    <?php echo esc_html__('بررسی سفارشات BWDK', 'buy-with-digikala'); ?>
                </button>
            </form>
        </div>
        </div>
        <?php
    }

    /**
     * Detect WooCommerce orders LIST screens only (not single order edit).
     *
     * Supports:
     * - Legacy list: edit.php?post_type=shop_order  (screen id: edit-shop_order)
     * - HPOS list:   admin.php?page=wc-orders      (screen id: woocommerce_page_wc-orders)
     */
    protected function isOrdersListScreen($screen): bool
    {
        $screen_id = is_object($screen) ? (string) ($screen->id ?? '') : '';

        // Legacy CPT list.
        if ($screen_id === 'edit-shop_order') {
            return true;
        }

        $page = isset($_GET['page']) ? sanitize_key((string) $_GET['page']) : '';
        $action = isset($_GET['action']) ? sanitize_key((string) $_GET['action']) : '';

        // HPOS orders screen: ensure it's the LIST view (not action=edit).
        if ($screen_id === 'woocommerce_page_wc-orders' || $page === 'wc-orders') {
            if ($action === 'edit') {
                return false;
            }
            return true;
        }

        // Fallback for legacy: only treat as list when screen base is "edit" and post_type=shop_order.
        $post_type = isset($_GET['post_type']) ? sanitize_key((string) $_GET['post_type']) : '';
        $screen_base = is_object($screen) ? (string) ($screen->base ?? '') : '';
        if ($screen_base === 'edit' && $post_type === 'shop_order') {
            return true;
        }

        return false;
    }

    protected function log_toolbar_attempt(string $hook): void
    {
        $logger = function_exists('wc_get_logger') ? wc_get_logger() : null;
        if (!$logger) return;

        $screen = function_exists('get_current_screen') ? get_current_screen() : null;
        $logger->debug(
            'BWDK toolbar render attempt: screen=' . ($screen ? $screen->id : 'none') .
            ', hook=' . $hook .
            ', already_rendered=' . (self::$toolbar_rendered ? 'yes' : 'no') .
            ', page=' . (isset($_GET['page']) ? (string) $_GET['page'] : '') .
            ', post_type=' . (isset($_GET['post_type']) ? (string) $_GET['post_type'] : ''),
            ['source' => 'bwdk_bulk_verify']
        );
    }

    protected function log_toolbar_return(string $reason, string $hook): void
    {
        $logger = function_exists('wc_get_logger') ? wc_get_logger() : null;
        if (!$logger) return;

        $screen = function_exists('get_current_screen') ? get_current_screen() : null;
        $logger->debug(
            'BWDK toolbar render return: reason=' . $reason .
            ', screen=' . ($screen ? $screen->id : 'none') .
            ', hook=' . $hook .
            ', already_rendered=' . (self::$toolbar_rendered ? 'yes' : 'no') .
            ', page=' . (isset($_GET['page']) ? (string) $_GET['page'] : '') .
            ', post_type=' . (isset($_GET['post_type']) ? (string) $_GET['post_type'] : ''),
            ['source' => 'bwdk_bulk_verify']
        );
    }

    public function handle(): void
    {
        $logger = function_exists('wc_get_logger') ? wc_get_logger() : null;

        if ($logger) {
            $logger->info('BWDK bulk verify handler reached', ['source' => 'bwdk_bulk_verify']);
        }

        try {
            if (!current_user_can('edit_shop_orders') && !current_user_can('manage_woocommerce')) {
                wp_die(esc_html__('دسترسی غیرمجاز است.', 'buy-with-digikala'), 403);
            }

            $nonce_val = isset($_GET[self::NONCE_QUERY_ARG]) ? (string) $_GET[self::NONCE_QUERY_ARG] : '';
            $nonce_ok = $nonce_val !== '' && wp_verify_nonce($nonce_val, self::NONCE_ACTION);
            if (!$nonce_ok) {
                wp_die(esc_html__('درخواست نامعتبر است. لطفاً صفحه را رفرش کنید و دوباره تلاش کنید.', 'buy-with-digikala'), 403);
            }

            $limit = isset($_GET['bwdk_bulk_verify_limit'])
                ? absint(wp_unslash($_GET['bwdk_bulk_verify_limit']))
                : self::DEFAULT_LIMIT;
            $limit = max(self::MIN_LIMIT, min(self::MAX_LIMIT, $limit));

            $return_url_raw = isset($_GET[self::RETURN_URL_ARG]) ? (string) wp_unslash($_GET[self::RETURN_URL_ARG]) : '';
            $return_url = $this->validateReturnUrl($return_url_raw);

            $user_id = get_current_user_id();
            $state_key  = self::STATE_TRANSIENT_PREFIX . $user_id;

            $step = isset($_GET['bwdk_step']) ? sanitize_text_field((string) $_GET['bwdk_step']) : '';

            if ($step !== 'run') {
                delete_transient($state_key);

                $candidate_ids = $this->collectCandidateOrderIds($limit);
                if (empty($candidate_ids)) {
                    $this->redirectToOrdersListSummary($return_url, [
                        'bwdk_bulk_verify_done' => 1,
                        'bwdk_bulk_verify_checked' => 0,
                        'bwdk_bulk_verify_verified' => 0,
                        'bwdk_bulk_verify_existing' => 0,
                        'bwdk_bulk_verify_skipped' => 0,
                        'bwdk_bulk_verify_failed' => 0,
                        'bwdk_bulk_verify_limit' => $limit,
                    ]);
                    return;
                }

                set_transient($state_key, [
                    'ids' => $candidate_ids,
                    'offset' => 0,
                    'checked' => 0,
                    'verified' => 0,
                    'already_verified' => 0,
                    'skipped' => 0,
                    'failed' => 0,
                    'limit' => $limit,
                    'return_url' => $return_url,
                ], 15 * MINUTE_IN_SECONDS);

                $this->redirectToRunStep();
                return;
            }
            
            $state = get_transient($state_key);
            if (!is_array($state) || empty($state['ids']) || !is_array($state['ids'])) {
                $this->redirectToOrdersListSummary($return_url, [
                    'bwdk_bulk_verify_done' => 1,
                    'bwdk_bulk_verify_checked' => 0,
                    'bwdk_bulk_verify_verified' => 0,
                    'bwdk_bulk_verify_existing' => 0,
                    'bwdk_bulk_verify_skipped' => 0,
                    'bwdk_bulk_verify_failed' => 0,
                    'bwdk_bulk_verify_limit' => $limit,
                ]);
                return;
            }

            $ids = array_values(array_filter($state['ids'], 'is_numeric'));
            $offset = isset($state['offset']) ? max(0, (int) $state['offset']) : 0;

            $batch_ids = array_slice($ids, $offset, self::BATCH_SIZE);
            if (empty($batch_ids)) {
                $checked = (int) ($state['checked'] ?? 0);
                $verified = (int) ($state['verified'] ?? 0);
                $already_verified = (int) ($state['already_verified'] ?? 0);
                $skipped = (int) ($state['skipped'] ?? 0);
                $failed = (int) ($state['failed'] ?? 0);
                $final_limit = isset($state['limit']) ? (int) $state['limit'] : $limit;

                delete_transient($state_key);

                if ($logger) {
                    $logger->info(
                        sprintf(
                            'BWDK bulk summary: checked=%d verified=%d existing=%d skipped=%d failed=%d limit=%d',
                            $checked,
                            $verified,
                            $already_verified,
                            $skipped,
                            $failed,
                            $final_limit
                        ),
                        ['source' => 'bwdk_bulk_verify']
                    );
                }

                $state_return = isset($state['return_url']) ? (string) $state['return_url'] : $return_url;
                $this->redirectToOrdersListSummary($state_return, [
                    'bwdk_bulk_verify_done' => 1,
                    'bwdk_bulk_verify_checked' => $checked,
                    'bwdk_bulk_verify_verified' => $verified,
                    'bwdk_bulk_verify_existing' => $already_verified,
                    'bwdk_bulk_verify_skipped' => $skipped,
                    'bwdk_bulk_verify_failed' => $failed,
                    'bwdk_bulk_verify_limit' => $final_limit,
                ]);
                return;
            }

            $log_ctx = [
                'source' => 'bwdk_bulk_verify',
                'screen_hpos' => $this->isHposEnabled() ? 'yes' : 'no',
            ];

            foreach ($batch_ids as $order_id_raw) {
            $order_id = (int) $order_id_raw;
            if ($order_id <= 0) {
                continue;
            }

            $order = wc_get_order($order_id);
            if (!$order instanceof WC_Order) {
                $state['failed'] = (int) ($state['failed'] ?? 0) + 1;
                if ($logger) {
                    $logger->warning(sprintf('BWDK bulk: order not found | order_id=%d', $order_id), $log_ctx);
                }
                continue;
            }

            $uuid = (string) $order->get_meta(Constant::META_BWDK_UUID);
            if ($uuid === '') {
                $state['skipped'] = (int) ($state['skipped'] ?? 0) + 1;
                if ($logger) {
                    $logger->info(sprintf('BWDK bulk: skipped (not BWDK, no uuid) | order_id=%d', $order_id), $log_ctx);
                }
                continue;
            }
            
            $state['checked'] = (int) ($state['checked'] ?? 0) + 1;

            // Prevent duplicate verification attempts with the same lock meta used elsewhere in the plugin.
            $lock_time = (int) $order->get_meta(OrderCancelSync::META_SYNC_LOCK);
            if ($lock_time > 0 && (time() - $lock_time) < 300) {
                $state['skipped'] = (int) ($state['skipped'] ?? 0) + 1;
                if ($logger) {
                    $logger->info(
                        sprintf('BWDK bulk: skipped (sync lock active) | order_id=%d uuid=%s lock_age=%d', $order_id, $uuid, time() - $lock_time),
                        $log_ctx
                    );
                }
                continue;
            }

            $order->update_meta_data(OrderCancelSync::META_SYNC_LOCK, time());
            $order->save();

            try {
                $merchant_unique_id = (string) $order->get_meta('_bwdk_merchant_unique_id');
                $local_status = (string) $order->get_meta('_bwdk_api_status');
                $local_status_display = (string) $order->get_meta('_bwdk_api_status_display');

                // Always refresh from remote; OrderSyncService will verify if remote status is PAID_BY_USER (7).
                $result = OrderSyncService::refresh_from_bwdk($order_id, [
                    'source' => 'admin_bulk',
                    'skip_address_sync' => true,
                ]);

                if (empty($result['ok'])) {
                    $state['failed'] = (int) ($state['failed'] ?? 0) + 1;
                    if ($logger) {
                        $logger->warning(
                            sprintf(
                                'BWDK bulk: failed | order_id=%d uuid=%s merchant_unique_id=%s local_status=%s local_status_display=%s message=%s',
                                $order_id,
                                $uuid ?: 'N/A',
                                $merchant_unique_id !== '' ? 'yes' : 'no',
                                $local_status !== '' ? $local_status : 'N/A',
                                $local_status_display !== '' ? $local_status_display : 'N/A',
                                (string) ($result['message'] ?? 'unknown')
                            ),
                            $log_ctx
                        );
                    }
                    continue;
                }

                $remote_status = (int) ($result['bwdk_status'] ?? 0);
                $verify_called = !empty($result['verify_called']);
                $verify_ok = !empty($result['verify_ok']);
                $was_verified = !empty($result['was_verified']);

                if ($verify_called && $verify_ok && $remote_status === BWDK_OrderStatus::VERIFIED_BY_MERCHANT) {
                    $state['verified'] = (int) ($state['verified'] ?? 0) + 1;
                    if ($logger) {
                        $logger->info(sprintf('BWDK bulk: verified | order_id=%d uuid=%s', $order_id, $uuid), $log_ctx);
                    }
                } elseif ($remote_status === BWDK_OrderStatus::VERIFIED_BY_MERCHANT || $was_verified) {
                    $state['already_verified'] = (int) ($state['already_verified'] ?? 0) + 1;
                    if ($logger) {
                        $logger->info(sprintf('BWDK bulk: already verified remotely | order_id=%d uuid=%s', $order_id, $uuid), $log_ctx);
                    }
                } elseif ($remote_status === BWDK_OrderStatus::PAID_BY_USER) {
                    // Still paid-by-user after refresh+verify attempt => treat as failed and log why.
                    $state['failed'] = (int) ($state['failed'] ?? 0) + 1;
                    if ($logger) {
                        $logger->warning(
                            sprintf(
                                'BWDK bulk: verify attempted but not verified | order_id=%d uuid=%s merchant_unique_id=%s verify_called=%s verify_ok=%s',
                                $order_id,
                                $uuid,
                                $merchant_unique_id !== '' ? 'yes' : 'no',
                                $verify_called ? 'yes' : 'no',
                                $verify_ok ? 'yes' : 'no'
                            ),
                            $log_ctx
                        );
                    }
                } else {
                    $state['skipped'] = (int) ($state['skipped'] ?? 0) + 1;
                    if ($logger) {
                        $logger->info(
                            sprintf(
                                'BWDK bulk: skipped (remote status not eligible) | order_id=%d uuid=%s remote_status=%d',
                                $order_id,
                                $uuid,
                                $remote_status
                            ),
                            $log_ctx
                        );
                    }
                }
            } catch (\Throwable $e) {
                $state['failed'] = (int) ($state['failed'] ?? 0) + 1;
                if ($logger) {
                    $logger->error(
                        sprintf('BWDK bulk verify exception: order_id=%d error=%s', $order_id, $e->getMessage()),
                        $log_ctx
                    );
                }
            } finally {
                $order = wc_get_order($order_id);
                if ($order instanceof WC_Order) {
                    $order->delete_meta_data(OrderCancelSync::META_SYNC_LOCK);
                    $order->save();
                }
            }
        }

            $state['offset'] = $offset + count($batch_ids);
            set_transient($state_key, $state, 15 * MINUTE_IN_SECONDS);

            $this->redirectToRunStep();
            return;
        } catch (\Throwable $e) {
            if ($logger) {
                $logger->error(
                    sprintf('BWDK bulk handler exception: %s', $e->getMessage()),
                    ['source' => 'bwdk_bulk_verify']
                );
            }
            $fallback_return = $this->defaultReturnUrlForCurrentScreen();
            $this->redirectToOrdersListSummary($fallback_return, [
                'bwdk_bulk_verify_done' => 1,
                'bwdk_bulk_verify_checked' => 0,
                'bwdk_bulk_verify_verified' => 0,
                'bwdk_bulk_verify_existing' => 0,
                'bwdk_bulk_verify_skipped' => 0,
                'bwdk_bulk_verify_failed' => 1,
                'bwdk_bulk_verify_error' => 'exception',
            ]);
            return;
        }
    }

    protected function collectCandidateOrderIds(int $limit): array
    {
        $since = time() - (2 * DAY_IN_SECONDS);

        // Collect all BWDK orders (uuid exists) in last 2 days; remote refresh decides eligibility.
        $ids = wc_get_orders([
            'limit' => max(self::MIN_LIMIT, min(self::MAX_LIMIT, $limit)),
            'return' => 'ids',
            'orderby' => 'date',
            'order' => 'DESC',
            'date_created' => '>' . $since,
            'meta_query' => [
                [
                    'key' => Constant::META_BWDK_UUID,
                    'compare' => 'EXISTS',
                ],
            ],
        ]);

        if (!is_array($ids) || empty($ids)) {
            return [];
        }

        $candidates = [];
        foreach ($ids as $id) {
            $order = wc_get_order((int) $id);
            if (!$order instanceof WC_Order) continue;

            $uuid = (string) $order->get_meta(Constant::META_BWDK_UUID);
            if ($uuid === '') continue;

            $candidates[] = (int) $id;
        }

        return array_values(array_unique($candidates));
    }

    protected function isHposEnabled(): bool
    {
        if (!function_exists('wc_get_container')) {
            return false;
        }
        try {
            $util = wc_get_container()->get(COTMigrationUtil::class);
            if (is_object($util) && method_exists($util, 'is_custom_orders_table_usage_enabled')) {
                return (bool) $util->is_custom_orders_table_usage_enabled();
            }
        } catch (\Throwable $e) {
            return false;
        }
        return false;
    }

    public function renderNotice(): void
    {
        if (self::$notice_rendered) {
            return;
        }

        $logger = function_exists('wc_get_logger') ? wc_get_logger() : null;
        if ($logger) {
            $screen = function_exists('get_current_screen') ? get_current_screen() : null;
            $logger->debug(
                'BWDK notice render attempt: screen=' . ($screen ? $screen->id : 'none') .
                ', done=' . (isset($_GET['bwdk_bulk_verify_done']) ? sanitize_text_field(wp_unslash($_GET['bwdk_bulk_verify_done'])) : 'missing'),
                ['source' => 'bwdk_bulk_verify']
            );
        }

        if (!isset($_GET['bwdk_bulk_verify_done']) || absint(wp_unslash($_GET['bwdk_bulk_verify_done'])) !== 1) {
            return;
        }

        // If you want a screen check, it must support both screen ids and query fallbacks.
        $screen = function_exists('get_current_screen') ? get_current_screen() : null;
        if ($screen && !$this->isOrdersListScreen($screen)) {
            // If we are not on an orders screen, don't render the notice.
            return;
        }

        $checked  = isset($_GET['bwdk_bulk_verify_checked']) ? absint(wp_unslash($_GET['bwdk_bulk_verify_checked'])) : 0;
        $verified = isset($_GET['bwdk_bulk_verify_verified']) ? absint(wp_unslash($_GET['bwdk_bulk_verify_verified'])) : 0;
        $existing = isset($_GET['bwdk_bulk_verify_existing']) ? absint(wp_unslash($_GET['bwdk_bulk_verify_existing'])) : 0;
        $skipped  = isset($_GET['bwdk_bulk_verify_skipped']) ? absint(wp_unslash($_GET['bwdk_bulk_verify_skipped'])) : 0;
        $failed   = isset($_GET['bwdk_bulk_verify_failed']) ? absint(wp_unslash($_GET['bwdk_bulk_verify_failed'])) : 0;

        // If counters are missing (e.g. stripped by HPOS routing), fallback to transient.
        $has_any_counter_arg =
            isset($_GET['bwdk_bulk_verify_checked']) ||
            isset($_GET['bwdk_bulk_verify_verified']) ||
            isset($_GET['bwdk_bulk_verify_existing']) ||
            isset($_GET['bwdk_bulk_verify_skipped']) ||
            isset($_GET['bwdk_bulk_verify_failed']);

        if (!$has_any_counter_arg) {
            $t_key = self::RESULT_TRANSIENT_PREFIX . get_current_user_id();
            $t_val = get_transient($t_key);
            if (is_array($t_val)) {
                $checked  = isset($t_val['checked']) ? absint($t_val['checked']) : $checked;
                $verified = isset($t_val['verified']) ? absint($t_val['verified']) : $verified;
                $existing = isset($t_val['existing']) ? absint($t_val['existing']) : $existing;
                $skipped  = isset($t_val['skipped']) ? absint($t_val['skipped']) : $skipped;
                $failed   = isset($t_val['failed']) ? absint($t_val['failed']) : $failed;
                delete_transient($t_key);
            }
        }

        $error = isset($_GET['bwdk_bulk_verify_error']) ? sanitize_key((string) $_GET['bwdk_bulk_verify_error']) : '';

        if ($error !== '') {
            if ($error === 'nonce' || $error === 'cap') {
                $message = __('درخواست نامعتبر یا دسترسی غیرمجاز بود. لطفاً صفحه را رفرش کنید و دوباره تلاش کنید.', 'buy-with-digikala');
            } else {
                $message = __('بررسی سفارشات BWDK با خطا مواجه شد. لطفاً لاگ‌ها را بررسی کنید.', 'buy-with-digikala');
            }
        } elseif ($checked <= 0) {
            $message = __('هیچ سفارش BWDK قابل بررسی در بازه انتخاب‌شده یافت نشد.', 'buy-with-digikala');
        } else {
            $message = sprintf(
                /* translators: 1: checked, 2: verified, 3: existing, 4: skipped, 5: failed */
                __('بررسی سفارشات BWDK انجام شد. %1$s سفارش بررسی شد، %2$s سفارش تایید شد، %3$s سفارش قبلاً تایید شده بود، %4$s سفارش رد شد، %5$s سفارش با خطا مواجه شد.', 'buy-with-digikala'),
                number_format_i18n($checked),
                number_format_i18n($verified),
                number_format_i18n($existing),
                number_format_i18n($skipped),
                number_format_i18n($failed)
            );
        }

        $class = ($error !== '' || $failed > 0) ? 'notice notice-warning is-dismissible' : 'notice notice-success is-dismissible';
        self::$notice_rendered = true;
        printf('<div class="%1$s"><p>%2$s</p></div>', esc_attr($class), esc_html($message));
    }

    protected function redirectToRunStep(): void
    {
        $nonce_val = isset($_GET[self::NONCE_QUERY_ARG]) ? (string) $_GET[self::NONCE_QUERY_ARG] : '';
        $limit = isset($_GET['bwdk_bulk_verify_limit']) ? absint(wp_unslash($_GET['bwdk_bulk_verify_limit'])) : self::DEFAULT_LIMIT;
        $limit = max(self::MIN_LIMIT, min(self::MAX_LIMIT, $limit));
        $url = add_query_arg(
            [
                'action' => self::ACTION,
                'bwdk_step' => 'run',
                self::NONCE_QUERY_ARG => $nonce_val,
                'bwdk_bulk_verify_limit' => $limit,
            ],
            admin_url('admin-post.php')
        );
        wp_safe_redirect($url);
        exit;
    }

    protected function redirectToOrdersListSummary(string $return_url, array $args): void
    {
        $base = $this->validateReturnUrl($return_url);
        $redirect_url = add_query_arg($args, $base);

        // Store counters for HPOS screens that may strip unknown args.
        $t_key = self::RESULT_TRANSIENT_PREFIX . get_current_user_id();
        $t_val = [
            'checked' => isset($args['bwdk_bulk_verify_checked']) ? absint($args['bwdk_bulk_verify_checked']) : 0,
            'verified' => isset($args['bwdk_bulk_verify_verified']) ? absint($args['bwdk_bulk_verify_verified']) : 0,
            'existing' => isset($args['bwdk_bulk_verify_existing']) ? absint($args['bwdk_bulk_verify_existing']) : 0,
            'skipped' => isset($args['bwdk_bulk_verify_skipped']) ? absint($args['bwdk_bulk_verify_skipped']) : 0,
            'failed' => isset($args['bwdk_bulk_verify_failed']) ? absint($args['bwdk_bulk_verify_failed']) : 0,
        ];
        set_transient($t_key, $t_val, 5 * MINUTE_IN_SECONDS);

        $logger = function_exists('wc_get_logger') ? wc_get_logger() : null;
        if ($logger) {
            $logger->debug(
                'BWDK bulk verify redirect URL: ' . $redirect_url,
                ['source' => 'bwdk_bulk_verify']
            );
        }

        wp_safe_redirect($redirect_url);
        exit;
    }

    protected function defaultReturnUrlForCurrentScreen(): string
    {
        $screen = function_exists('get_current_screen') ? get_current_screen() : null;
        if ($screen && $screen->id === 'woocommerce_page_wc-orders') {
            return admin_url('admin.php?page=wc-orders');
        }
        return admin_url('edit.php?post_type=shop_order');
    }

    protected function validateReturnUrl(string $url): string
    {
        $url = trim($url);
        if ($url !== '') {
            $validated = wp_validate_redirect($url, '');
            if (is_string($validated) && $validated !== '') {
                return $validated;
            }
        }

        // Fallbacks: prefer explicit Woo screens, not current request.
        return $this->defaultReturnUrlForCurrentScreen();
    }
}

