<?php

namespace BWDK\Woo;

use BWDK\Support\Constant;
use BWDK\Support\OrderNoteHelper;
use BWDK\Woo\Order\ReferenceCodeHelper;
use WC_Order;

class WooHooks
{
    use OrderNoteHelper;

    public $options;

    public $product_card_position;

    public $order;
    public $order_id;

    // Static guards to prevent double rendering
    private static $rendered_comp1 = false;
    private static $rendered_add_to_cart = false;

    public function register(): void
    {

        $this->options = get_option(Constant::BWDK_OPTION_NAME);

        // Handle cancel/back markers and redirect handler for single-item flow
        add_action('template_redirect', [$this, 'handleCancelLanding'], 1);
        add_action('template_redirect', [$this, 'handleReturnRedirect']);

        // Enqueue scripts for single product pages
        add_action('wp_enqueue_scripts', [$this, 'enqueueScripts']);

        add_action('wp_head', [$this, 'renderHead']);
        add_action('wp_footer', [$this, 'renderFooter']);


        $top_banner_status = $this->options["top-banner"]['status'] ?? [];

        if ($top_banner_status) {
            add_action('wp_body_open', [$this, 'renderTopBanner']);
        }


        // @bwdk-disabled-temp: کامپوننت کارت محصول - غیرفعال موقت
        /*
        $product_card_status = $this->options['product-card']['status'] ?? '1';
        $product_card_position = $this->options['product-card']['position'] ?? 'woocommerce_before_shop_loop_item';
        if ($product_card_status) {

            if ($product_card_position == "woocommerce_before_shop_loop_item") {
                $this->product_card_position = $product_card_position;
            }
            add_action($product_card_position, [$this, 'renderProductCardBadge'], 1);
        }
        */


        $product_single_status = $this->options['product-single']['status'] ?? '1';
        $product_single_position = $this->options['product-single']['position'] ?? 'woocommerce_after_add_to_cart_button';


        if ($product_single_status) {
            add_action($product_single_position, [$this, 'renderAddToCardButton']);
        }


        $checkout_status = $this->options['checkout']['status'] ?? '1';
        $checkout_position = $this->options['checkout']['position'] ?? 'woocommerce_before_checkout_form';
        if ($checkout_status) {
            add_action($checkout_position, [$this, 'renderCompCheckout']);
        }

        $cart_status = $this->options['cart']['status'] ?? '1';
        $cart_position = $this->options['cart']['position'] ?? 'woocommerce_before_cart_table';
        if ($cart_status) {
            add_action($cart_position, [$this, 'renderCompCart']);
        }




        // @bwdk-disabled-temp: پاپ آپ / ساید بار سبد خرید - غیرفعال موقت
        /*
        $minicart_status = $this->options['minicart']['status'] ?? '1';



        if ($minicart_status) {
            add_action('woocommerce_widget_shopping_cart_total', [$this, 'renderMiniCart']);
        }
        */




        // @bwdk-disabled-temp: لیبل صفحه نمایش محصول - غیرفعال موقت
        /*
        $product_single_badge_status = $this->options['product-single-badge']['status'] ?? '1';
        $product_single_badge_position = $this->options['product-single-badge']['position'] ?? 'woocommerce_before_single_product_summary';
        if ($product_single_badge_status) {
            add_action($product_single_badge_position, [$this, 'renderThumbnailSingleBadge']);
        }
        */







        add_action('woocommerce_before_thankyou', [$this,'renderFailedPayment']);
        add_action('woocommerce_order_details_after_order_table_items', [$this,'renderContentThankyou'] );
        add_action('woocommerce_order_details_after_order_table', [$this, 'renderViewOrderReferenceCode'], 20, 1);




        add_shortcode('bwdk_top_banner', [$this, 'shotcodeTopBanner']);
        add_shortcode('bwdk_add_to_cart_button', [$this, 'shotcodeAddToCardButton']);
        add_shortcode('bwdk_comp1', [$this, 'shotcodeComp1']);
        // @bwdk-disabled-temp: شورت‌کدهای غیرفعال موقت
        /*
        add_shortcode('bwdk_minicart', [$this, 'shotcodeMiniCart']);
        add_shortcode('bwdk_thumbnail_single_badge', [$this, 'shotcodeThumbnailSingleBadge']);
        add_shortcode('bwdk_product_card_badge', [$this, 'shotcodeProductCardBadge']);
        */

        add_shortcode('bwdk_thankyou', [$this, 'shotcodeThankyou']);

        // @bwdk-disabled-temp: دکمه خرید از دیجی‌کالا در صفحه محصول - غیرفعال موقت
        /*
        // Single buy button
        $single_buy_button_status = $this->options['single-buy-button']['status'] ?? '0';
        if ($single_buy_button_status) {
            add_action('woocommerce_single_product_summary', [$this, 'renderSingleBuyButton'], 29);
        }
        add_shortcode('bwdk_single_buy_button', [$this, 'shotcodeSingleBuyButton']);
        */

        add_filter('woocommerce_account_orders_columns', [$this, 'addAccountOrdersColumn'], 20);

        // 2-a) همیشه phone را به آرایه آدرسِ حمل‌ونقل سفارش اضافه کن
        add_filter('woocommerce_order_formatted_shipping_address', function($address, $order) {
            if (empty($address['phone'])) {
                $phone = method_exists($order, 'get_shipping_phone')
                    ? $order->get_shipping_phone()
                    : get_post_meta($order->get_id(), '_shipping_phone', true);
                if ($phone) {
                    $address['phone'] = $phone;
                }
            }
            return $address;
        }, 10, 2);

        // 2-b) جای‌نگهدار {phone} را به الگوی آدرس همه کشورها اضافه کن (اگر نبود)
        add_filter('woocommerce_localisation_address_formats', function($formats) {
            foreach ($formats as $country => $format) {
                if (strpos($format, '{phone}') === false) {
                    // یک خط جدید برای phone
                    $formats[$country] = rtrim($format) . "\n{phone}";
                }
            }
            return $formats;
        });

        // 2-c) مقدار {phone} را به جای‌نگهدار وصل کن
        add_filter('woocommerce_formatted_address_replacements', function($replacements, $args) {
            $replacements['{phone}'] = isset($args['phone']) && $args['phone'] !== '' ? $args['phone'] : '';
            return $replacements;
        }, 10, 2);

        // 3) نمایش Shipping phone در ادمین (BWDK receiver_name/receiver_phone در buy-with-digikala.php ثبت می‌شود)
        add_action('woocommerce_admin_order_data_after_shipping_address', function($order){
            $phone = method_exists($order, 'get_shipping_phone')
                ? $order->get_shipping_phone()
                : $order->get_meta('_shipping_phone');
            if ($phone) {
                echo '<p><strong>'.esc_html__('Shipping phone', 'bwdk').':</strong> '.esc_html($phone).'</p>';
            }
        }, 10, 1);

        // Ensure packing fee is always non-taxable (prevent VAT on packing amount from Digify)
        add_filter('woocommerce_order_item_get_tax_class', function($tax_class, $item) {
            // Check if this is a packing fee item
            if ($item instanceof \WC_Order_Item_Fee) {
                $name = $item->get_name();
                if (strpos($name, 'هزینه بسته بندی:') === 0) {
                    return ''; // Empty tax class = non-taxable
                }
            }
            return $tax_class;
        }, 10, 2);

        // Also ensure tax status is 'none' for packing fees
        add_filter('woocommerce_order_item_get_tax_status', function($tax_status, $item) {
            if ($item instanceof \WC_Order_Item_Fee) {
                $name = $item->get_name();
                if (strpos($name, 'هزینه بسته بندی:') === 0) {
                    return 'none'; // Non-taxable
                }
            }
            return $tax_status;
        }, 10, 2);

        // Fix BWDK promotion coupon tooltip: show promotion_data.discount_value + discount_type (percent/amount)
        // instead of discount_amount. discount_amount is unchanged for calculations/BWDK API.
        add_filter('woocommerce_order_item_get_formatted_meta_data', function($formatted_meta, $item) {
            if (!$item instanceof \WC_Order_Item_Coupon) {
                return $formatted_meta;
            }
            
            $is_bwdk_promotion = $item->get_meta('_bwdk_promo') === '1' || $item->get_meta('_bwdk_promotion_coupon') === '1';
            if (!$is_bwdk_promotion) {
                return $formatted_meta;
            }
            
            $discount_type = (int) $item->get_meta('_bwdk_discount_type');
            if ($discount_type === 0) {
                $discount_type = (int) $item->get_meta('_bwdk_promotion_discount_type');
            }
            $discount_value = (float) $item->get_meta('_bwdk_discount_value');
            if ($discount_value === 0.0 && $discount_type === 0) {
                $discount_value = (float) $item->get_meta('_bwdk_promotion_discount_value');
            }
            
            // Mapping: discount_type 1 = percent, 2 = amount (BWDK API convention)
            $tooltip_text = '';
            if ($discount_type === 1) {
                $tooltip_text = sprintf('%s%%', number_format($discount_value, 2));
            } elseif ($discount_type === 2) {
                $formatted = function_exists('wc_price') ? wp_strip_all_tags(wc_price($discount_value)) : number_format($discount_value, 0, '.', ',');
                $tooltip_text = $formatted . ' ' . __('تومان', 'bwdk');
            } else {
                // Fallback when promotion_data missing: show formatted discount_amount (current behavior)
                $discount_amount = (float) $item->get_discount();
                if ($discount_amount > 0) {
                    $tooltip_text = function_exists('wc_price') ? wp_strip_all_tags(wc_price($discount_amount)) : number_format($discount_amount, 0, '.', ',');
                    $tooltip_text = $tooltip_text . ' ' . __('تومان', 'bwdk');
                }
            }
            
            if ($tooltip_text !== '') {
                if (!isset($formatted_meta['_bwdk_promotion_tooltip'])) {
                    $formatted_meta['_bwdk_promotion_tooltip'] = (object) [
                        'key' => '_bwdk_promotion_tooltip',
                        'value' => $tooltip_text,
                        'display_key' => '',
                        'display_value' => $tooltip_text,
                    ];
                }
            }
            
            return $formatted_meta;
        }, 10, 2);

        // Filter coupon discount display for tooltip (WooCommerce uses this for hover tooltips)
        add_filter('woocommerce_order_item_coupon_get_discount', function($discount, $item, $context) {
            if (!$item instanceof \WC_Order_Item_Coupon) {
                return $discount;
            }
            
            // Check if this is a BWDK promotion coupon (try new meta key first, then legacy)
            $is_bwdk_promotion = $item->get_meta('_bwdk_promo') === '1' || $item->get_meta('_bwdk_promotion_coupon') === '1';
            if (!$is_bwdk_promotion) {
                return $discount;
            }
            
            // For view context (display), return the actual discount amount (not total_paid_amount)
            // The discount amount is already set correctly in the coupon item
            // This filter ensures WooCommerce uses the coupon's own discount, not order total
            return $discount;
        }, 10, 3);

        // Before calculating totals, ensure packing fees have zero tax
        add_action('woocommerce_order_before_calculate_totals', function($and_taxes, $order) {
            foreach ($order->get_fees() as $fee_item) {
                $name = $fee_item->get_name();
                if (strpos($name, 'هزینه بسته بندی:') === 0) {
                    // Force packing fee to be non-taxable
                    $fee_item->set_tax_class('');
                    if (method_exists($fee_item, 'set_tax_status')) {
                        $fee_item->set_tax_status('none');
                    }
                    $fee_item->set_total_tax(0);
                    // Note: set_subtotal_tax() doesn't exist for WC_Order_Item_Fee
                }
            }
        }, 10, 2);

        // After calculate_totals(), restore total_paid_amount if it exists
        // This ensures BWDK order total remains equal to total_paid_amount (amount paid by user)
        add_action('woocommerce_order_after_calculate_totals', function($and_taxes, $order) {
            if (!$order instanceof WC_Order) {
                return;
            }
            
            // Get total_paid_amount from order meta (stored during manager sync)
            $total_paid_amount = (float) $order->get_meta('_bwdk_total_paid_amount');
            if ($total_paid_amount > 0) {
                // Convert from BWDK currency to store currency
                $total_paid_amount_store = \BWDK\Support\WooCompatibility::convert_to_store_currency($total_paid_amount);
                
                // Restore order total to total_paid_amount
                $order->set_total($total_paid_amount_store);
            }
        }, 10, 2);

        // Display Digipay markup info in order totals (customer and admin)
        add_filter('woocommerce_get_order_item_totals', [$this, 'addMarkupInfoToOrderTotals'], 10, 3);
        // Display Digipay markup info in admin order details (optional, if not already visible via fee line)
        add_action('woocommerce_admin_order_data_after_order_details', [$this, 'displayMarkupInfoInAdmin'], 10, 1);
        add_action(
            'woocommerce_my_account_my_orders_column_bwdk_digikala_reference_code',
            [$this, 'renderAccountOrdersReferenceCode'],
            20,
            1
        );

        // FIX: Correct profit/saving percentage calculation in checkout
        // When coupon is applied, profit percentage should be calculated from coupon rate, not from discount / (goods + tax)
        // Hook into cart totals to provide correct profit calculation data
        add_action('woocommerce_cart_totals_before_order_total', [$this, 'maybeAddCorrectProfitInfo'], 10);
        add_action('woocommerce_review_order_before_order_total', [$this, 'maybeAddCorrectProfitInfo'], 10);
        
        // Provide filter for themes/plugins to get correct profit calculation
        add_filter('bwdk_calculate_profit_from_coupon', [$this, 'calculateCorrectProfitFromCoupon'], 10, 3);
        
        // FIX: Override profit percentage calculation via JavaScript injection
        add_action('wp_footer', [$this, 'injectProfitPercentageFix'], 999);
        
        // FIX: Filter checkout/cart HTML to fix profit percentage
        add_filter('woocommerce_cart_totals_html', [$this, 'fixProfitPercentageInHtml'], 10, 1);
        add_filter('woocommerce_review_order_html', [$this, 'fixProfitPercentageInHtml'], 10, 1);

        // Fix BWDK promotion coupon tooltip in admin order screen
        add_action('admin_footer', [$this, 'fixBwdkCouponTooltip'], 999);

        // Display shipping promotion (free shipping) in admin order screen (display-only)
        add_action('admin_footer', [$this, 'injectShippingPromotionAdminUi'], 999);


        /*
        list shortcodes



        [bwdk_top_banner]
        [bwdk_add_to_cart_button]
        [bwdk_comp1]
        [bwdk_thumbnail_single_badge]
        [bwdk_product_card_badge]
        [bwdk_minicart]



        */
    }

    public function renderFailedPayment($order_id){
        $this->order =wc_get_order($order_id);
        $this->render('failed-payment');

    }

    public function renderContentThankyou( $order)
    {
        $this->order =$order;

        $this->render('content-thankyou');
    }

    public function renderFooter()
    {

        $this->render('footer');
    }

    // @bwdk-disabled-temp: لیبل صفحه نمایش محصول - غیرفعال موقت
    /*
    public function renderThumbnailSingleBadge()
    {
        $this->render('thumbnail-single-badge');
    }
    */

    // @bwdk-disabled-temp: کامپوننت کارت محصول - غیرفعال موقت
    /*
    public function renderProductCardBadge()
    {
        $this->render('product-card-badge');
    }
    */
    public function renderTopBanner()
    {
        $this->render('top-banner');
    }

    public function renderAddToCardButton()
    {
        // Guard: prevent double rendering if shortcode is also used
        if (self::$rendered_add_to_cart) {
            return;
        }
        self::$rendered_add_to_cart = true;
        $this->render('add-to-card-button');
    }
    // @bwdk-disabled-temp: پاپ آپ / ساید بار سبد خرید - غیرفعال موقت
    /*
    public function renderMiniCart()
    {

        $this->getBuffered('mini-cart');
    }
    */
    public function renderCompCart()
    {
        // Guard: prevent double rendering if shortcode is also used
        if (self::$rendered_comp1) {
            return;
        }
        self::$rendered_comp1 = true;
        $this->render('comp-1');
    }
    public function renderCompCheckout()
    {
        // Guard: prevent double rendering if shortcode is also used
        if (self::$rendered_comp1) {
            return;
        }
        self::$rendered_comp1 = true;
        $this->render('comp-1');
    }





    public function renderHead(): void
    {
        $this->render('head');
    }


    // @bwdk-disabled-temp: لیبل صفحه نمایش محصول - غیرفعال موقت
    /*
    public function shotcodeThumbnailSingleBadge()
    {
        $this->getBuffered('thumbnail-single-badge');
    }
    */

    // @bwdk-disabled-temp: کامپوننت کارت محصول - غیرفعال موقت
    /*
    public function shotcodeProductCardBadge()
    {
        $this->getBuffered('product-card-badge');
    }
    */
    public function shotcodeTopBanner()
    {
        $html = $this->getBuffered('top-banner');
        // Prevent wpautop from breaking shortcode output
        return shortcode_unautop($html);
    }

    public function shotcodeAddToCardButton()
    {
        // Guard: prevent double rendering if hook is also active
        if (self::$rendered_add_to_cart) {
            return '';
        }
        self::$rendered_add_to_cart = true;
        
        $html = $this->getBuffered('add-to-card-button');
        
        // Prevent wpautop from breaking shortcode output
        return shortcode_unautop($html);
    }
    // @bwdk-disabled-temp: پاپ آپ / ساید بار سبد خرید - غیرفعال موقت
    /*
    public function shotcodeMiniCart()
    {
        $this->getBuffered('mini-cart');
    }
    */
    public function shotcodeComp1()
    {
        // Guard: prevent double rendering if hook is also active
        if (self::$rendered_comp1) {
            return '';
        }
        self::$rendered_comp1 = true;
        
        $html = $this->getBuffered('comp-1');
        
        // Prevent wpautop from breaking shortcode output
        return shortcode_unautop($html);
    }
    public function shotcodeThankyou($atts = [])
    {
        if ( ! defined('DONOTCACHEPAGE') ) define('DONOTCACHEPAGE', true);
        nocache_headers();

        $atts = shortcode_atts([
            'order' => 0,
            'key'   => '',
        ], (array) $atts, 'bwdk_thankyou');

        $order_id = isset($_GET['order'])
            ? absint($_GET['order'])
            : absint($atts['order']);

        $key = isset($_GET['key'])
            ? wc_clean( wp_unslash($_GET['key']) )
            : wc_clean( (string) $atts['key'] );

        if ( ! $order_id ) {
            return $this->error_box('شناسهٔ سفارش مشخص نیست.');
        }

        $order = wc_get_order($order_id);
        if ( ! $order instanceof WC_Order ) {
            return $this->error_box('سفارش یافت نشد.');
        }

        if ( ! $this->viewer_is_allowed($order, $key) ) {
            return $this->error_box('دسترسی به این سفارش مجاز نیست.');
        }

        $this->order =$order;
        $html = $this->getBuffered('thankyou');
        // Prevent wpautop from breaking shortcode output
        return shortcode_unautop($html);
    }
    private function viewer_is_allowed(WC_Order $order, string $key): bool
    {
        // valid order key (guest-friendly)
        if ( $key && hash_equals($order->get_order_key(), $key) ) {
            return true;
        }

        // or owner/admin/shop-manager
        $uid = (int) get_current_user_id();
        if ( $uid && ( (int) $order->get_user_id() === $uid ) ) return true;
        if ( current_user_can('manage_woocommerce') || current_user_can('edit_shop_orders') ) return true;

        return false;
    }

    private function error_box(string $msg): string
    {
        $safe = esc_html($msg);
        return '<div class="woocommerce-notices-wrapper"><ul class="woocommerce-error" role="alert"><li>'.$safe.'</li></ul></div>';
    }


    protected function render(string $view): void
    {
        $path = BWDK_PATH . 'src/Woo/Views/' . $view . '.php';
        if (file_exists($path)) {
            include $path;
        }
    }

    /**
     * Get buffered HTML output with cleaning and wpautop protection
     * 
     * @param string $view View name
     * @return string Cleaned HTML output
     */
    protected function getBuffered(string $view): string
    {
        ob_start();
        $this->render($view);
        $html = ob_get_clean();

        // Clean HTML: remove newlines, tabs, and extra spaces to prevent wpautop issues
        $html = $this->cleanHtmlOutput($html);
        
        // Apply hotfix to remove empty tags
        $html = $this->removeEmptyTags($html);

        return $html;
    }

    /**
     * Clean HTML output by removing newlines, tabs, and extra whitespace
     * This prevents wpautop from breaking the HTML structure
     * 
     * @param string $html Raw HTML
     * @return string Cleaned HTML
     */
    private function cleanHtmlOutput(string $html): string
    {
        // Remove carriage returns and tabs
        $html = str_replace(["\r", "\t"], '', $html);
        
        // Replace multiple spaces with single space (but preserve space in text nodes)
        $html = preg_replace('/[ \t]+/', ' ', $html);
        
        // Remove spaces between HTML tags
        $html = preg_replace('/>\s+</', '><', $html);
        
        // Remove leading/trailing whitespace
        $html = trim($html);
        
        return $html;
    }

    /**
     * Remove empty tags from HTML output (hotfix)
     * Specifically targets empty <p></p>, <br>, and empty <a class="bwdk-button"></a> tags
     * Only processes content within .dk-content-before-ct container
     * 
     * @param string $html HTML content
     * @return string Cleaned HTML
     */
    private function removeEmptyTags(string $html): string
    {
        // Use DOMDocument for safe parsing
        if (!class_exists('DOMDocument')) {
            // Fallback to regex if DOMDocument not available (shouldn't happen in WP)
            return preg_replace([
                '/<p[^>]*>\s*<\/p>/i',
                '/<br\s*\/?>\s*/i',
                '/<a[^>]*class=["\'][^"\']*bwdk-button[^"\']*["\'][^>]*>\s*<\/a>/i'
            ], '', $html);
        }

        // Load HTML with proper encoding
        $dom = new \DOMDocument('1.0', 'UTF-8');
        @$dom->loadHTML('<?xml encoding="UTF-8">' . $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD | LIBXML_NOERROR | LIBXML_NOWARNING);
        
        $xpath = new \DOMXPath($dom);
        
        // Find .dk-content-before-ct container
        $containers = $xpath->query("//*[contains(concat(' ', normalize-space(@class), ' '), ' dk-content-before-ct ')]");
        
        if ($containers->length > 0) {
            foreach ($containers as $container) {
                // Remove empty <p> tags
                $emptyPs = $xpath->query(".//p[not(node()) or (count(node()) = 1 and normalize-space(text()) = '')]", $container);
                foreach ($emptyPs as $p) {
                    $p->parentNode->removeChild($p);
                }
                
                // Remove empty <br> tags (standalone)
                $brs = $xpath->query(".//br", $container);
                foreach ($brs as $br) {
                    // Check if br is empty or has no meaningful siblings
                    $parent = $br->parentNode;
                    if ($parent && $parent->nodeName !== 'br') {
                        // Only remove if it's a standalone br with no content around
                        $prevSibling = $br->previousSibling;
                        $nextSibling = $br->nextSibling;
                        $hasContent = false;
                        if ($prevSibling && ($prevSibling->nodeType === XML_TEXT_NODE && trim($prevSibling->textContent) !== '')) {
                            $hasContent = true;
                        }
                        if ($nextSibling && ($nextSibling->nodeType === XML_TEXT_NODE && trim($nextSibling->textContent) !== '')) {
                            $hasContent = true;
                        }
                        if (!$hasContent) {
                            $br->parentNode->removeChild($br);
                        }
                    }
                }
                
                // Remove empty <a class="bwdk-button"> tags
                $emptyButtons = $xpath->query(".//a[contains(concat(' ', normalize-space(@class), ' '), ' bwdk-button ') and (not(node()) or (count(node()) = 0) or (count(node()) = 1 and normalize-space(text()) = ''))]", $container);
                foreach ($emptyButtons as $button) {
                    $button->parentNode->removeChild($button);
                }
            }
        }
        
        // Get cleaned HTML
        $body = $dom->getElementsByTagName('body')->item(0);
        if ($body) {
            $cleaned = '';
            foreach ($body->childNodes as $node) {
                $cleaned .= $dom->saveHTML($node);
            }
            return $cleaned;
        }
        
        return $html;
    }

    // @bwdk-disabled-temp: دکمه خرید از دیجی‌کالا در صفحه محصول - غیرفعال موقت
    /*
    public function renderSingleBuyButton(): void
    {
        global $product;
        
        // Check toggle status
        $single_buy_button_status = $this->options['single-buy-button']['status'] ?? '0';
        if ($single_buy_button_status != '1') {
            return;
        }
        
        if (!$product || !is_a($product, 'WC_Product')) {
            return;
        }
        
        // Hide button for out-of-stock simple products
        if ($product->is_type('simple') && (!$product->is_purchasable() || !$product->is_in_stock())) {
            return;
        }
        
        // For variable products, still render (JS handles variation selection)
        if (!$product->is_purchasable()) {
            return;
        }
        
        $this->render('single-buy-button');
    }

    public function shotcodeSingleBuyButton(): string
    {
        // Shortcode always renders regardless of toggle
        global $product;
        
        if (!$product || !is_a($product, 'WC_Product')) {
            return '';
        }
        
        // Hide button for out-of-stock simple products
        if ($product->is_type('simple') && (!$product->is_purchasable() || !$product->is_in_stock())) {
            return '';
        }
        
        // For variable products, still render (JS handles variation selection)
        if (!$product->is_purchasable()) {
            return '';
        }
        
        return $this->getBufferedOutput('single-buy-button');
    }
    */

    protected function getBufferedOutput(string $view): string
    {
        ob_start();
        $this->render($view);
        $html = ob_get_clean();
        
        // Clean HTML output
        $html = $this->cleanHtmlOutput($html);
        $html = $this->removeEmptyTags($html);
        
        return $html;
    }

    public function addAccountOrdersColumn(array $columns): array
    {
        $new = [];
        $inserted = false;

        foreach ($columns as $key => $label) {
            $new[$key] = $label;

            if ($key === 'order-status' && !$inserted) {
                $new['bwdk_digikala_reference_code'] = 'کد پیگیری دیجی‌کالایی';
                $inserted = true;
            }
        }

        if (!$inserted) {
            $new['bwdk_digikala_reference_code'] = 'کد پیگیری دیجی‌کالایی';
        }

        return $new;
    }

    /**
     * @param int|\WC_Order $order
     */
    public function renderAccountOrdersReferenceCode($order): void
    {
        if (!$order instanceof WC_Order) {
            $order = wc_get_order(is_numeric($order) ? (int) $order : 0);
        }

        if (!$order instanceof WC_Order) {
            echo '—';
            return;
        }

        $reference_code = ReferenceCodeHelper::extractFromOrder($order);

        if ($reference_code === '') {
            echo '—';
            return;
        }

        echo esc_html($reference_code);
    }

    /**
     * Render Digikala reference code on the My Account → View Order page.
     *
     * @param int|\WC_Order $order
     */
    public function renderViewOrderReferenceCode($order): void
    {
        if (!$order instanceof WC_Order) {
            $order = wc_get_order(is_numeric($order) ? (int) $order : 0);
        }

        if (!$order instanceof WC_Order) {
            return;
        }

        $reference_code = ReferenceCodeHelper::extractFromOrder($order);
        if ($reference_code === '') {
            return;
        }

        echo '<section class="woocommerce-order-details bwdk-order-ref">';
        echo '	<h2 class="woocommerce-order-details__title">' . esc_html__('کد پیگیری دیجی‌کالایی', 'bwdk') . '</h2>';
        echo '	<p class="bwdk-order-ref__value">' . esc_html($reference_code) . '</p>';
        echo '</section>';
    }

    /**
     * Enqueue scripts for single product pages
     */
    public function enqueueScripts(): void
    {
        if (is_product()) {
            // Localize script for variation selection message
            wp_localize_script('bwdk-front-script', 'bwdk_i18n', [
                'select_variation' => esc_html__('لطفاً یک گزینه را انتخاب کنید', 'bwdk')
            ]);
        }
    }

    /**
     * Handle cancel landings for single-item flow and log note
     */
    public function handleCancelLanding(): void
    {
        $cancel_marker = isset($_GET['bwdk_cancel']) ? (int) $_GET['bwdk_cancel'] : 0;
        $is_back = false;
        if ($cancel_marker !== 1) {
            $cancel_marker = isset($_GET['bwdk_back']) ? (int) $_GET['bwdk_back'] : 0;
            $is_back = ($cancel_marker === 1);
        }
        if ($cancel_marker !== 1) {
            return;
        }

        // PART 1: HIGH-VISIBILITY diagnostic logging
        $logger = function_exists('wc_get_logger') ? wc_get_logger() : null;
        if ($logger) {
            $logger->info(
                sprintf(
                    'BWDK RETURN TRACE: HIT admin-ajax %s - REQUEST_URI=%s oid=%s referer=%s timestamp=%s',
                    $is_back ? 'bwdk_back' : 'bwdk_cancel',
                    $_SERVER['REQUEST_URI'] ?? 'N/A',
                    $_GET['oid'] ?? 'N/A',
                    wp_get_referer() ?: 'N/A',
                    current_time('mysql')
                ),
                ['source' => 'bwdk_return_trace']
            );
        }

        $order_id = isset($_GET['oid']) ? (int) $_GET['oid'] : 0;
        if ($order_id <= 0) {
            // Check origin parameter first (most reliable)
            $redirect_url = null;
            $origin_param = isset($_GET['origin']) ? sanitize_text_field($_GET['origin']) : null;
            
            if ($origin_param === 'checkout') {
                $redirect_url = function_exists('wc_get_checkout_url') ? wc_get_checkout_url() : home_url('/checkout/');
            } elseif ($origin_param === 'cart') {
                $redirect_url = function_exists('wc_get_cart_url') ? wc_get_cart_url() : home_url('/cart/');
            }
            
            // Fallback to session or cart contents
            if (empty($redirect_url)) {
                if (function_exists('WC') && WC()->session) {
                    $redirect_url = WC()->session->get('bwdk_return_to');
                    if ($redirect_url) {
                        WC()->session->__unset('bwdk_return_to');
                    }
                }
                if (empty($redirect_url)) {
                    if (function_exists('WC') && WC()->cart && !WC()->cart->is_empty()) {
                        $redirect_url = function_exists('wc_get_checkout_url') ? wc_get_checkout_url() : home_url('/checkout/');
                    } else {
                        $redirect_url = function_exists('wc_get_cart_url') ? wc_get_cart_url() : home_url('/cart/');
                    }
                }
            }
            
            if ($logger) {
                $logger->info(
                    sprintf(
                        'BWDK RETURN TRACE: admin-ajax %s redirecting to origin (no order_id) - origin_param=%s return_to=%s timestamp=%s',
                        $is_back ? 'bwdk_back' : 'bwdk_cancel',
                        $origin_param ?: 'N/A',
                        $redirect_url,
                        current_time('mysql')
                    ),
                    ['source' => 'bwdk_return_trace']
                );
            }
            nocache_headers();
            wp_safe_redirect($redirect_url);
            exit;
        }

        $order = wc_get_order($order_id);
        if (!$order instanceof WC_Order) {
            // Check origin parameter first (most reliable)
            $redirect_url = null;
            $origin_param = isset($_GET['origin']) ? sanitize_text_field($_GET['origin']) : null;
            
            if ($origin_param === 'checkout') {
                $redirect_url = function_exists('wc_get_checkout_url') ? wc_get_checkout_url() : home_url('/checkout/');
            } elseif ($origin_param === 'cart') {
                $redirect_url = function_exists('wc_get_cart_url') ? wc_get_cart_url() : home_url('/cart/');
            }
            
            // Fallback to session or cart contents
            if (empty($redirect_url)) {
                if (function_exists('WC') && WC()->session) {
                    $redirect_url = WC()->session->get('bwdk_return_to');
                    if ($redirect_url) {
                        WC()->session->__unset('bwdk_return_to');
                    }
                }
                if (empty($redirect_url)) {
                    if (function_exists('WC') && WC()->cart && !WC()->cart->is_empty()) {
                        $redirect_url = function_exists('wc_get_checkout_url') ? wc_get_checkout_url() : home_url('/checkout/');
                    } else {
                        $redirect_url = function_exists('wc_get_cart_url') ? wc_get_cart_url() : home_url('/cart/');
                    }
                }
            }
            
            if ($logger) {
                $logger->info(
                    sprintf(
                        'BWDK RETURN TRACE: admin-ajax %s redirecting to origin (order not found) - order_id=%d origin_param=%s return_to=%s timestamp=%s',
                        $is_back ? 'bwdk_back' : 'bwdk_cancel',
                        $order_id,
                        $origin_param ?: 'N/A',
                        $redirect_url,
                        current_time('mysql')
                    ),
                    ['source' => 'bwdk_return_trace']
                );
            }
            nocache_headers();
            wp_safe_redirect($redirect_url);
            exit;
        }

        // تفکیک انصراف قبل/بعد از لاگین
        if (is_user_logged_in()) {
            $this->bwdk_note_userCanceledAfterLogin($order);
        } else {
            $this->bwdk_note_userCanceledBeforeLogin($order);
        }

        // Resolve return_to URL - check origin parameter first (most reliable)
        $redirect_url = null;
        $origin_param = isset($_GET['origin']) ? sanitize_text_field($_GET['origin']) : null;
        
        if ($origin_param === 'checkout') {
            $redirect_url = function_exists('wc_get_checkout_url') ? wc_get_checkout_url() : home_url('/checkout/');
        } elseif ($origin_param === 'cart') {
            $redirect_url = function_exists('wc_get_cart_url') ? wc_get_cart_url() : home_url('/cart/');
        }
        
        // Fallback to order meta, then session, then cart contents
        if (empty($redirect_url)) {
            $redirect_url = $order->get_meta('_bwdk_return_to');
            if (empty($redirect_url) && function_exists('WC') && WC()->session) {
                $redirect_url = WC()->session->get('bwdk_return_to');
                if ($redirect_url) {
                    WC()->session->__unset('bwdk_return_to');
                }
            }
            if (empty($redirect_url)) {
                if (function_exists('WC') && WC()->cart && !WC()->cart->is_empty()) {
                    $redirect_url = function_exists('wc_get_checkout_url') ? wc_get_checkout_url() : home_url('/checkout/');
                } else {
                    $redirect_url = function_exists('wc_get_cart_url') ? wc_get_cart_url() : home_url('/cart/');
                }
            }
        }
        
        // Clear BWDK session flow keys
        if (function_exists('WC') && WC()->session) {
            WC()->session->__unset('order_awaiting_payment');
        }

        if ($logger) {
            $logger->info(
                sprintf(
                    'BWDK RETURN TRACE: admin-ajax %s redirecting to origin - order_id=%d origin_param=%s return_to=%s timestamp=%s',
                    $is_back ? 'bwdk_back' : 'bwdk_cancel',
                    $order->get_id(),
                    $origin_param ?: 'N/A',
                    $redirect_url,
                    current_time('mysql')
                ),
                ['source' => 'bwdk_return_trace']
            );
        }

        nocache_headers();
        wp_safe_redirect($redirect_url);
        exit;
    }

    /**
     * Handle return redirect for single-item flow
     * PART 2: Now redirects to checkout instead of product page
     */
    public function handleReturnRedirect(): void
    {
        if (empty($_GET['bwdk_back'])) {
            return;
        }

        // PART 1: HIGH-VISIBILITY diagnostic logging
        $logger = function_exists('wc_get_logger') ? wc_get_logger() : null;
        if ($logger) {
            $logger->info(
                sprintf(
                    'BWDK RETURN TRACE: HIT admin-ajax bwdk_back (single flow) - REQUEST_URI=%s pid=%s oid=%s referer=%s timestamp=%s',
                    $_SERVER['REQUEST_URI'] ?? 'N/A',
                    $_GET['pid'] ?? 'N/A',
                    $_GET['oid'] ?? 'N/A',
                    wp_get_referer() ?: 'N/A',
                    current_time('mysql')
                ),
                ['source' => 'bwdk_return_trace']
            );
        }

        // Check origin parameter first (most reliable)
        $redirect_url = null;
        $origin_param = isset($_GET['origin']) ? sanitize_text_field($_GET['origin']) : null;
        
        if ($origin_param === 'checkout') {
            $redirect_url = function_exists('wc_get_checkout_url') ? wc_get_checkout_url() : home_url('/checkout/');
        } elseif ($origin_param === 'cart') {
            $redirect_url = function_exists('wc_get_cart_url') ? wc_get_cart_url() : home_url('/cart/');
        }
        
        // Fallback to order meta, then session, then cart contents
        if (empty($redirect_url)) {
            $order_id = isset($_GET['oid']) ? (int) $_GET['oid'] : 0;
            if ($order_id > 0) {
                $order = wc_get_order($order_id);
                if ($order instanceof WC_Order) {
                    $redirect_url = $order->get_meta('_bwdk_return_to');
                }
            }
            if (empty($redirect_url) && function_exists('WC') && WC()->session) {
                $redirect_url = WC()->session->get('bwdk_return_to');
                if ($redirect_url) {
                    WC()->session->__unset('bwdk_return_to');
                }
            }
            if (empty($redirect_url)) {
                if (function_exists('WC') && WC()->cart && !WC()->cart->is_empty()) {
                    $redirect_url = function_exists('wc_get_checkout_url') ? wc_get_checkout_url() : home_url('/checkout/');
                } else {
                    $redirect_url = function_exists('wc_get_cart_url') ? wc_get_cart_url() : home_url('/cart/');
                }
            }
        }
        
        // Clear BWDK session flow keys
        if (function_exists('WC') && WC()->session) {
            WC()->session->__unset('order_awaiting_payment');
            WC()->session->__unset('bwdk_last_single_pid');
        }

        if ($logger) {
            $logger->info(
                sprintf(
                    'BWDK RETURN TRACE: admin-ajax bwdk_back redirecting to origin - origin_param=%s return_to=%s timestamp=%s',
                    $origin_param ?: 'N/A',
                    $redirect_url,
                    current_time('mysql')
                ),
                ['source' => 'bwdk_return_trace']
            );
        }

        nocache_headers();
        wp_safe_redirect($redirect_url);
        exit;
    }

    /**
     * Add Digipay markup info to order totals display
     *
     * @param array $total_rows
     * @param WC_Order $order
     * @param bool $tax_display
     * @return array
     */
    public function addMarkupInfoToOrderTotals(array $total_rows, WC_Order $order, bool $tax_display): array
    {
        if (!$order instanceof WC_Order) {
            return $total_rows;
        }

        // Shipping promotion tooltip (separate from goods promotion_data)
        $shipping_promotion_discount_amount = (float) $order->get_meta('_bwdk_shipping_promotion_discount_amount', true);
        $shipping_promotion_data = $order->get_meta('_bwdk_shipping_promotion_data', true);
        if (is_string($shipping_promotion_data)) {
            $decoded = json_decode($shipping_promotion_data, true);
            $shipping_promotion_data = is_array($decoded) ? $decoded : [];
        }
        if (!is_array($shipping_promotion_data)) {
            $shipping_promotion_data = [];
        }

        // Fallback: if shipping promotion meta isn't extracted yet, read from raw callback JSON (display-only).
        if (($shipping_promotion_discount_amount <= 0 || empty($shipping_promotion_data))) {
            $raw = $order->get_meta(\BWDK\Support\Constant::META_BWDK_JSON_CB);
            if (is_string($raw)) {
                $raw = json_decode($raw, true);
            }
            if (is_array($raw)) {
                if ($shipping_promotion_discount_amount <= 0 && isset($raw['shipping_promotion_discount_amount'])) {
                    $shipping_promotion_discount_amount = (float) $raw['shipping_promotion_discount_amount'];
                }
                if (empty($shipping_promotion_data) && isset($raw['shipping_promotion_data']) && is_array($raw['shipping_promotion_data'])) {
                    $shipping_promotion_data = $raw['shipping_promotion_data'];
                }
            }
        }

        if ($shipping_promotion_discount_amount > 0 && !empty($shipping_promotion_data) && isset($total_rows['shipping'])) {
            $code = isset($shipping_promotion_data['code']) ? (string) $shipping_promotion_data['code'] : '';
            $discount_type = isset($shipping_promotion_data['discount_type']) ? (int) $shipping_promotion_data['discount_type'] : 0;
            $discount_value = isset($shipping_promotion_data['discount_value']) ? (float) $shipping_promotion_data['discount_value'] : 0.0;

            $value_display = '';
            if ($discount_type === 1) {
                $value_display = rtrim(rtrim(number_format($discount_value, 2, '.', ''), '0'), '.') . '%';
            } elseif ($discount_type === 2) {
                $value_display = number_format($discount_value, 0, '.', ',') . ' ' . __('تومان', 'bwdk');
            }

            if ($code !== '' && $value_display !== '') {
                $prefix = ($discount_type === 1) ? __('ارسال رایگان', 'bwdk') : __('تخفیف ارسال', 'bwdk');
                $tooltip_text = sprintf('%s: %s (%s)', $prefix, $code, $value_display);
                $tooltip_attr = esc_attr($tooltip_text);

                $label = $total_rows['shipping']['label'] ?? '';
                $total_rows['shipping']['label'] = $label . ' <span class="bwdk-shipping-promotion-tooltip" title="' . $tooltip_attr . '" style="cursor:help; text-decoration: underline dotted;">(?)</span>';

                // Show strike-through original shipping and final shipping (display-only; do not alter order totals).
                $raw = $order->get_meta(\BWDK\Support\Constant::META_BWDK_JSON_CB);
                if (is_string($raw)) {
                    $raw = json_decode($raw, true);
                }
                $original_shipping_bwdk = null;
                if (is_array($raw)) {
                    if (isset($raw['shipping_amount'])) {
                        $original_shipping_bwdk = (float) $raw['shipping_amount'];
                    } elseif (isset($raw['selected_shipping_method']['cost'])) {
                        $original_shipping_bwdk = (float) $raw['selected_shipping_method']['cost'];
                    }
                }
                $original_shipping = null;
                if (is_numeric($original_shipping_bwdk)) {
                    $original_shipping = \BWDK\Support\WooCompatibility::convert_to_store_currency((float) $original_shipping_bwdk);
                }
                if (!is_numeric($original_shipping)) {
                    // Fallback to Woo shipping total (may already be final; still better than nothing).
                    $original_shipping = (float) $order->get_shipping_total();
                }
                $discount_store = \BWDK\Support\WooCompatibility::convert_to_store_currency((float) $shipping_promotion_discount_amount);
                $final_shipping = max(0.0, (float) $original_shipping - (float) $discount_store);

                $fmt = static function (float $amount) use ($order): string {
                    if (function_exists('wc_price')) {
                        return wp_strip_all_tags(wc_price($amount, ['currency' => $order->get_currency()]));
                    }
                    return number_format($amount, 0, '.', ',') . ' ' . __('تومان', 'bwdk');
                };

                $orig_html = '<del>' . esc_html($fmt((float) $original_shipping)) . '</del>';
                $final_html = ($final_shipping <= 0.0)
                    ? '<span class="bwdk-shipping-free">' . esc_html__('رایگان', 'bwdk') . '</span>'
                    : '<span class="bwdk-shipping-final">' . esc_html($fmt((float) $final_shipping)) . '</span>';

                // Add promo text under shipping value (display-only).
                $promo_line_label = ($discount_type === 1) ? __('کد ارسال رایگان', 'bwdk') : __('کد تخفیف ارسال', 'bwdk');
                $promo_line = '<br><small class="bwdk-shipping-promo-line">' . esc_html($promo_line_label . ': ' . $code . ' (' . $value_display . ')') . '</small>';

                $total_rows['shipping']['value'] = $orig_html . ' ' . $final_html . $promo_line;

                // Add an explicit shipping discount line for clarity (display-only).
                if ($discount_store > 0) {
                    $discount_line = [
                        'label' => __('تخفیف ارسال', 'bwdk') . ':',
                        'value' => esc_html($fmt((float) $discount_store)),
                    ];
                    // Insert right after shipping row if possible.
                    $new_rows = [];
                    $inserted = false;
                    foreach ($total_rows as $key => $row) {
                        $new_rows[$key] = $row;
                        if ($key === 'shipping' && !$inserted) {
                            $new_rows['bwdk_shipping_discount'] = $discount_line;
                            $inserted = true;
                        }
                    }
                    if ($inserted) {
                        $total_rows = $new_rows;
                    }
                }
            }
        }

        // CRITICAL: Only display markup for Digipay orders
        $order_payment_method = $order->get_payment_method();
        $is_digipay_by_method = (stripos($order_payment_method, 'digipay') !== false);
        
        // Also check gateway_name from stored callback data as fallback
        $is_digipay_by_gateway = false;
        $raw_json = $order->get_meta(\BWDK\Support\Constant::META_BWDK_JSON_CB);
        if (!empty($raw_json)) {
            if (is_string($raw_json)) {
                $raw_json = json_decode($raw_json, true);
            }
            if (is_array($raw_json) && isset($raw_json['payment']['gateway_name'])) {
                $gateway_name = strtolower((string) $raw_json['payment']['gateway_name']);
                $is_digipay_by_gateway = ($gateway_name === 'digipay');
            }
        }
        
        // Must be Digipay by either method or gateway check (only for markup row)
        if (!$is_digipay_by_method && !$is_digipay_by_gateway) {
            return $total_rows;
        }

        $markup_percentage = (float) $order->get_meta('_markup_commission_percentage', true);
        $markup_amount_backend = (float) $order->get_meta('_digipay_markup_amount', true);

        // Only show if markup info exists and amount > 0
        if ($markup_amount_backend <= 0) {
            return $total_rows;
        }

        // Convert markup amount from backend currency (Toman) to store currency for display
        $markup_amount_display = \BWDK\Support\WooCompatibility::convert_to_store_currency($markup_amount_backend);

        // Format markup percentage for display
        $percentage_display = $markup_percentage > 0 ? sprintf('%.2f%%', $markup_percentage) : '';

        // Build label with percentage if available
        $label = 'مارک‌آپ دیجی‌پی';
        if ($percentage_display !== '') {
            $label .= ' (' . $percentage_display . ')';
        }

        // Insert before 'order_total' if it exists, otherwise append
        $new_rows = [];
        $inserted = false;

        foreach ($total_rows as $key => $row) {
            if ($key === 'order_total' && !$inserted) {
                // Insert markup info before order_total
                $new_rows['bwdk_digipay_markup'] = [
                    'label' => $label . ':',
                    'value' => wc_price($markup_amount_display, ['currency' => $order->get_currency()]),
                ];
                $inserted = true;
            }
            $new_rows[$key] = $row;
        }

        // If order_total not found, append at the end
        if (!$inserted) {
            $new_rows['bwdk_digipay_markup'] = [
                'label' => $label . ':',
                'value' => wc_price($markup_amount_display, ['currency' => $order->get_currency()]),
            ];
        }

        return $new_rows;
    }

    /**
     * Display-only admin UI for shipping promotion (free shipping / shipping discount).
     * - Adds a synthetic "shipping promotion" discount row in the order items table.
     * - Updates shipping row display to show "~original~ رایگان" or "~original~ final".
     * Never changes totals stored in the order.
     */
    public function injectShippingPromotionAdminUi(): void
    {
        $screen = function_exists('get_current_screen') ? get_current_screen() : null;
        if (!$screen || !in_array($screen->id, ['shop_order', 'woocommerce_page_wc-orders'], true)) {
            return;
        }

        $order_id = isset($_GET['id']) ? absint($_GET['id']) : (isset($_GET['post']) ? absint($_GET['post']) : 0);
        if (!$order_id) {
            return;
        }
        $order = wc_get_order($order_id);
        if (!$order instanceof WC_Order) {
            return;
        }

        $raw = $order->get_meta(\BWDK\Support\Constant::META_BWDK_JSON_CB);
        if (is_string($raw)) {
            $raw = json_decode($raw, true);
        }
        if (!is_array($raw)) {
            $raw = [];
        }

        $discount_bwdk = (float) ($raw['shipping_promotion_discount_amount'] ?? (float) $order->get_meta('_bwdk_shipping_promotion_discount_amount', true));
        $promo = $raw['shipping_promotion_data'] ?? $order->get_meta('_bwdk_shipping_promotion_data', true);
        if (is_string($promo)) {
            $promo = json_decode($promo, true);
        }
        if (!is_array($promo)) {
            $promo = [];
        }

        if ($discount_bwdk <= 0 || empty($promo)) {
            return;
        }

        $code = isset($promo['code']) ? (string) $promo['code'] : '';
        $discount_type = isset($promo['discount_type']) ? (int) $promo['discount_type'] : 0;
        $discount_value = isset($promo['discount_value']) ? (float) $promo['discount_value'] : 0.0;

        if ($code === '' || !in_array($discount_type, [1, 2], true)) {
            return;
        }

        $original_bwdk = null;
        if (isset($raw['shipping_amount'])) {
            $original_bwdk = (float) $raw['shipping_amount'];
        } elseif (isset($raw['selected_shipping_method']['cost'])) {
            $original_bwdk = (float) $raw['selected_shipping_method']['cost'];
        }

        $original_store = is_numeric($original_bwdk)
            ? \BWDK\Support\WooCompatibility::convert_to_store_currency((float) $original_bwdk)
            : (float) $order->get_shipping_total();

        $discount_store = \BWDK\Support\WooCompatibility::convert_to_store_currency((float) $discount_bwdk);
        $final_store = max(0.0, (float) $original_store - (float) $discount_store);

        $value_text = ($discount_type === 1)
            ? (rtrim(rtrim(number_format($discount_value, 2, '.', ''), '0'), '.') . '%')
            : (number_format($discount_value, 0, '.', ',') . ' ' . __('تومان', 'bwdk'));

        $promo_text = ($discount_type === 1)
            ? sprintf('ارسال رایگان: %s (%s)', $code, $value_text)
            : sprintf('تخفیف ارسال: %s (%s)', $code, $value_text);

        $format_money = function (float $amount) use ($order): string {
            if (function_exists('wc_price')) {
                return wp_strip_all_tags(wc_price($amount, ['currency' => $order->get_currency()]));
            }
            return number_format($amount, 0, '.', ',') . ' ' . __('تومان', 'bwdk');
        };

        $orig_disp = $format_money((float) $original_store);
        $final_disp = ($final_store <= 0.0) ? 'رایگان' : $format_money((float) $final_store);

        $js = [
            'promoText' => $promo_text,
            'orig' => $orig_disp,
            'final' => $final_disp,
        ];

        ?>
        <script type="text/javascript">
        (function($){
            var data = <?php echo wp_json_encode($js, JSON_UNESCAPED_UNICODE); ?>;
            function applyShippingPromotionUi() {
                // 1) Update shipping line display: "~original~ رایگان" or "~original~ final"
                var $table = $('#woocommerce-order-items, .woocommerce_order_items, .wc-order-items, table.woocommerce_order_items').first();
                if (!$table.length) return;
                var strikeHtml = '<del>' + $('<div>').text(data.orig).html() + '</del> ' + $('<div>').text(data.final).html();
                // Try common selectors for shipping rows
                var $shipRow = $table.find('tr.item.shipping, tr.shipping, tr.order_item.shipping').first();
                if ($shipRow.length) {
                    var $cost = $shipRow.find('td.line_cost .view, td.line_cost, td.total .view, td.total').first();
                    if ($cost.length) {
                        // Preserve possible extra nodes by only changing the first .view or cell HTML
                        $cost.html(strikeHtml);
                    }

                    // Add promo text under shipping row (display-only; not a Woo coupon item).
                    if ($shipRow.find('.bwdk-admin-shipping-promo').length === 0) {
                        var promoHtml = '<div class="bwdk-admin-shipping-promo" style="margin-top:6px; color:#555; font-size:12px;">'
                            + $('<div>').text(data.promoText).html()
                            + '</div>';
                        // Prefer putting it in the name column
                        var $name = $shipRow.find('td.name .view, td.name').first();
                        if ($name.length) {
                            $name.append(promoHtml);
                        } else {
                            $shipRow.append('<td class="bwdk-admin-shipping-promo-cell" colspan="1">' + promoHtml + '</td>');
                        }
                    }
                }
            }
            $(document).ready(function(){
                applyShippingPromotionUi();
                setTimeout(applyShippingPromotionUi, 100);
                setTimeout(applyShippingPromotionUi, 500);
                setTimeout(applyShippingPromotionUi, 1500);
            });
        })(jQuery);
        </script>
        <?php
    }

    /**
     * Display Digipay markup info in admin order details page
     * 
     * @param WC_Order $order
     */
    public function displayMarkupInfoInAdmin(WC_Order $order): void
    {
        if (!$order instanceof WC_Order) {
            return;
        }

        // CRITICAL: Only display markup for Digipay orders
        $order_payment_method = $order->get_payment_method();
        $is_digipay_by_method = (stripos($order_payment_method, 'digipay') !== false);
        
        // Also check gateway_name from stored callback data as fallback
        $is_digipay_by_gateway = false;
        $raw_json = $order->get_meta(\BWDK\Support\Constant::META_BWDK_JSON_CB);
        if (!empty($raw_json)) {
            if (is_string($raw_json)) {
                $raw_json = json_decode($raw_json, true);
            }
            if (is_array($raw_json) && isset($raw_json['payment']['gateway_name'])) {
                $gateway_name = strtolower((string) $raw_json['payment']['gateway_name']);
                $is_digipay_by_gateway = ($gateway_name === 'digipay');
            }
        }
        
        // Must be Digipay by either method or gateway check
        if (!$is_digipay_by_method && !$is_digipay_by_gateway) {
            // Not Digipay - do not display markup
            return;
        }

        $markup_percentage = (float) $order->get_meta('_markup_commission_percentage', true);
        $markup_amount_backend = (float) $order->get_meta('_digipay_markup_amount', true);

        // Only show if markup info exists and amount > 0
        if ($markup_amount_backend <= 0) {
            return;
        }

        // Convert markup amount from backend currency to store currency for display
        $markup_amount_display = \BWDK\Support\WooCompatibility::convert_to_store_currency($markup_amount_backend);

        // Format markup percentage for display
        $percentage_display = $markup_percentage > 0 ? sprintf('%.2f%%', $markup_percentage) : '';
        
        // Build label with percentage if available
        $label = 'مارک‌آپ دیجی‌پی';
        if ($percentage_display !== '') {
            $label .= ' (' . $percentage_display . ')';
        }

        ?>
        <div class="order_data_column">
            <h3><?php esc_html_e('کارمزد دیجی‌پی', 'bwdk'); ?></h3>
            <p>
                <strong><?php echo esc_html($label); ?>:</strong>
                <?php echo wc_price($markup_amount_display, ['currency' => $order->get_currency()]); ?>
            </p>
        </div>
        <?php
    }

    /**
     * FIX: Add correct profit info before order total in checkout/cart
     * This provides a hook point for themes/plugins to display correct profit percentage
     */
    public function maybeAddCorrectProfitInfo(): void
    {
        if (!function_exists('WC') || !WC()->cart) {
            return;
        }

        $cart = WC()->cart;
        $subtotal = (float) $cart->get_subtotal();
        $tax_total = (float) $cart->get_total_tax();
        $discount_total = (float) $cart->get_discount_total();

        // Only show if there's a discount
        if ($discount_total <= 0 || $subtotal <= 0) {
            return;
        }

        $profit_data = $this->calculateCorrectProfit($subtotal, $tax_total);
        if ($profit_data === null) {
            return;
        }

        // Store profit data in cart session for use by themes/plugins
        if (function_exists('WC') && WC()->session) {
            WC()->session->set('bwdk_correct_profit', $profit_data);
        }

        // Also make it available via filter
        do_action('bwdk_profit_calculated', $profit_data, $subtotal, $tax_total, $discount_total);
    }

    /**
     * FIX: Calculate correct profit from coupon rate
     * Filter: bwdk_calculate_profit_from_coupon
     * 
     * @param array|null $profit_data Existing profit data or null
     * @param float $goods_amount Subtotal (goods amount)
     * @param float $tax_amount Tax amount
     * @return array|null ['amount' => float, 'percent' => float] or null
     */
    public function calculateCorrectProfitFromCoupon(?array $profit_data, float $goods_amount, float $tax_amount): ?array
    {
        return $this->calculateCorrectProfit($goods_amount, $tax_amount);
    }

    /**
     * Calculate coupon rate from cart
     * Returns the discount rate (0-1) if coupon is percentage-based
     * 
     * @return float|null Coupon rate (0-1) or null if not applicable
     */
    protected function getCouponRateFromCart(): ?float
    {
        if (!function_exists('WC') || !WC()->cart) {
            return null;
        }

        $cart = WC()->cart;
        $applied_coupons = $cart->get_applied_coupons();
        
        if (empty($applied_coupons)) {
            return null;
        }

        $subtotal = (float) $cart->get_subtotal();
        if ($subtotal <= 0) {
            return null;
        }

        $discount_total = (float) $cart->get_discount_total();
        if ($discount_total <= 0) {
            return null;
        }

        // Check if any coupon is percentage-based
        foreach ($applied_coupons as $coupon_code) {
            $coupon = new \WC_Coupon($coupon_code);
            $discount_type = $coupon->get_discount_type();
            
            // If it's a percentage coupon, calculate the rate
            if ($discount_type === 'percent' || $discount_type === 'percent_product') {
                $coupon_amount = (float) $coupon->get_amount();
                if ($coupon_amount > 0 && $coupon_amount <= 100) {
                    // Return the coupon rate (0-1)
                    return $coupon_amount / 100.0;
                }
            }
        }

        // If no percentage coupon found, calculate rate from discount amount
        // This handles fixed-amount coupons that should be treated as percentage for profit display
        $calculated_rate = $discount_total / $subtotal;
        if ($calculated_rate > 0 && $calculated_rate <= 1) {
            return $calculated_rate;
        }

        return null;
    }

    /**
     * Calculate correct profit amount and percentage for display
     * 
     * @param float $goods_amount Subtotal (goods amount)
     * @param float $tax_amount Tax amount
     * @return array ['amount' => float, 'percent' => float] or null
     */
    protected function calculateCorrectProfit(float $goods_amount, float $tax_amount): ?array
    {
        $coupon_rate = $this->getCouponRateFromCart();
        
        if ($coupon_rate === null || $coupon_rate <= 0) {
            return null;
        }

        $profit_base = $goods_amount + $tax_amount;
        $profit_amount = round($coupon_rate * $profit_base, 2);
        $profit_percent = round($coupon_rate * 100, 2);

        return [
            'amount' => $profit_amount,
            'percent' => $profit_percent,
        ];
    }

    /**
     * FIX: Inject JavaScript to fix profit percentage display in checkout
     * This directly modifies the displayed percentage and amount in the DOM
     */
    public function injectProfitPercentageFix(): void
    {
        // Only run on checkout/cart pages
        if (!function_exists('is_checkout') || (!is_checkout() && !is_cart())) {
            return;
        }

        if (!function_exists('WC') || !WC()->cart) {
            return;
        }

        $cart = WC()->cart;
        $subtotal = (float) $cart->get_subtotal();
        $tax_total = (float) $cart->get_total_tax();
        $discount_total = (float) $cart->get_discount_total();

        // Only fix if there's a discount
        if ($discount_total <= 0 || $subtotal <= 0) {
            return;
        }

        $profit_data = $this->calculateCorrectProfit($subtotal, $tax_total);
        if ($profit_data === null) {
            return;
        }

        $correct_percent = $profit_data['percent'];
        $correct_amount = $profit_data['amount'];

        // Calculate incorrect values for comparison
        $incorrect_base = $subtotal + $tax_total;
        $incorrect_percent = $incorrect_base > 0 ? round(($discount_total / $incorrect_base) * 100, 2) : 0;

        // Only inject if there's a difference
        if (abs($correct_percent - $incorrect_percent) < 0.01) {
            return;
        }

        ?>
        <script type="text/javascript">
        (function($) {
            function fixProfitPercentage() {
                // Look for profit/saving text in various possible formats
                var profitSelectors = [
                    '*:contains("سود شما از خرید")',
                    '*:contains("سود شما")',
                    '*:contains("profit")',
                    '*:contains("saving")'
                ];

                var found = false;
                var correctPercent = <?php echo esc_js($correct_percent); ?>;
                var correctAmount = <?php echo esc_js($correct_amount); ?>;
                var incorrectPercent = <?php echo esc_js($incorrect_percent); ?>;

                // Try to find and fix profit percentage display
                $('body').find('*').each(function() {
                    var $el = $(this);
                    var text = $el.text() || '';
                    
                    // Check if this element contains profit percentage
                    if (text.indexOf('سود شما') !== -1 || text.indexOf('profit') !== -1 || text.indexOf('saving') !== -1) {
                        // Look for percentage pattern like (83%) or 83%
                        var percentMatch = text.match(/\(?\s*(\d+(?:\.\d+)?)\s*%?\s*\)?/);
                        if (percentMatch) {
                            var displayedPercent = parseFloat(percentMatch[1]);
                            
                            // If displayed percent matches incorrect calculation, fix it
                            if (Math.abs(displayedPercent - incorrectPercent) < 0.1) {
                                // Replace with correct percentage
                                var newText = text.replace(
                                    /\(?\s*\d+(?:\.\d+)?\s*%?\s*\)?/,
                                    '(' + correctPercent + '%)'
                                );
                                
                                // Also try to fix amount if it's displayed
                                var amountMatch = text.match(/(\d{1,3}(?:,\d{3})*(?:\.\d+)?)\s*تومان/);
                                if (amountMatch && Math.abs(parseFloat(amountMatch[1].replace(/,/g, '')) - <?php echo esc_js($discount_total); ?>) < 0.1) {
                                    var formattedAmount = correctAmount.toLocaleString('fa-IR');
                                    newText = newText.replace(
                                        /(\d{1,3}(?:,\d{3})*(?:\.\d+)?)\s*تومان/,
                                        formattedAmount + ' تومان'
                                    );
                                }
                                
                                $el.text(newText);
                                found = true;
                            }
                        }
                    }
                });

                // Alternative: Direct DOM manipulation for common WooCommerce structures
                if (!found) {
                    $('.woocommerce-checkout-review-order-table, .shop_table, .cart_totals').find('tr, .order-total, .cart-discount').each(function() {
                        var $row = $(this);
                        var text = $row.text() || '';
                        
                        if (text.indexOf('سود') !== -1 || text.indexOf('profit') !== -1 || text.indexOf('saving') !== -1) {
                            var percentMatch = text.match(/(\d+(?:\.\d+)?)\s*%/);
                            if (percentMatch) {
                                var displayedPercent = parseFloat(percentMatch[1]);
                                if (Math.abs(displayedPercent - incorrectPercent) < 0.1) {
                                    var newText = text.replace(
                                        /(\d+(?:\.\d+)?)\s*%/,
                                        correctPercent + '%'
                                    );
                                    $row.html($row.html().replace(text, newText));
                                    found = true;
                                }
                            }
                        }
                    });
                }
            }

            // Run on page load
            $(document).ready(function() {
                fixProfitPercentage();
            });

            // Run after WooCommerce updates
            $(document.body).on('updated_checkout updated_cart_totals wc_fragments_refreshed', function() {
                setTimeout(fixProfitPercentage, 100);
            });
        })(jQuery);
        </script>
        <?php
    }

    /**
     * FIX: Fix profit percentage in HTML output
     * 
     * @param string $html
     * @return string
     */
    public function fixProfitPercentageInHtml(string $html): string
    {
        if (!function_exists('WC') || !WC()->cart) {
            return $html;
        }

        $cart = WC()->cart;
        $subtotal = (float) $cart->get_subtotal();
        $tax_total = (float) $cart->get_total_tax();
        $discount_total = (float) $cart->get_discount_total();

        if ($discount_total <= 0 || $subtotal <= 0) {
            return $html;
        }

        $profit_data = $this->calculateCorrectProfit($subtotal, $tax_total);
        if ($profit_data === null) {
            return $html;
        }

        $correct_percent = $profit_data['percent'];
        $correct_amount = $profit_data['amount'];
        $incorrect_base = $subtotal + $tax_total;
        $incorrect_percent = $incorrect_base > 0 ? round(($discount_total / $incorrect_base) * 100, 2) : 0;

        // Only fix if there's a difference
        if (abs($correct_percent - $incorrect_percent) < 0.01) {
            return $html;
        }

        // Replace incorrect percentage with correct one
        $html = preg_replace(
            '/\(?\s*' . preg_quote($incorrect_percent, '/') . '\s*%?\s*\)?/',
            '(' . $correct_percent . '%)',
            $html
        );

        // Also try to fix amount if displayed
        $formatted_correct_amount = number_format($correct_amount, 0, '.', ',');
        $formatted_incorrect_amount = number_format($discount_total, 0, '.', ',');
        
        if ($formatted_correct_amount !== $formatted_incorrect_amount) {
            $html = str_replace($formatted_incorrect_amount . ' تومان', $formatted_correct_amount . ' تومان', $html);
        }

        return $html;
    }

    /**
     * Fix BWDK promotion coupon tooltip in admin order screen
     * Replaces incorrect tooltip (showing total_paid_amount) with correct discount type/value
     */
    public function fixBwdkCouponTooltip(): void
    {
        // Only run on order edit screen
        $screen = get_current_screen();
        if (!$screen || !in_array($screen->id, ['shop_order', 'woocommerce_page_wc-orders'], true)) {
            return;
        }
        
        // Get order ID
        $order_id = isset($_GET['id']) ? absint($_GET['id']) : (isset($_GET['post']) ? absint($_GET['post']) : 0);
        if (!$order_id) {
            return;
        }
        
        $order = wc_get_order($order_id);
        if (!$order instanceof WC_Order) {
            return;
        }
        
        // Find BWDK promotion coupon items
        $bwdk_coupons = [];
        foreach ($order->get_items('coupon') as $item_id => $item) {
            if (!$item instanceof \WC_Order_Item_Coupon) {
                continue;
            }
            
            // Check for BWDK promotion coupon (try new meta key first, then legacy)
            $is_bwdk_promotion = $item->get_meta('_bwdk_promo') === '1' || $item->get_meta('_bwdk_promotion_coupon') === '1';
            if (!$is_bwdk_promotion) {
                continue;
            }
            
            // Get discount_type and discount_value (meta first, then from promotion_data JSON)
            $discount_type = (int) $item->get_meta('_bwdk_discount_type');
            if ($discount_type === 0) {
                $discount_type = (int) $item->get_meta('_bwdk_promotion_discount_type');
            }
            $discount_value = (float) $item->get_meta('_bwdk_discount_value');
            if ($discount_value === 0.0) {
                $discount_value = (float) $item->get_meta('_bwdk_promotion_discount_value');
            }
            // Fallback: read from _bwdk_promotion_data JSON on item, or from order-level promotion_data
            if ($discount_type === 0 || $discount_value === 0.0) {
                $promotion_data_json = $item->get_meta('_bwdk_promotion_data');
                if (is_string($promotion_data_json)) {
                    $promotion_data = json_decode($promotion_data_json, true);
                    if (is_array($promotion_data)) {
                        if ($discount_type === 0 && isset($promotion_data['discount_type'])) {
                            $discount_type = (int) $promotion_data['discount_type'];
                        }
                        if ($discount_value === 0.0 && isset($promotion_data['discount_value'])) {
                            $discount_value = (float) $promotion_data['discount_value'];
                        }
                    }
                }
                // Order-level fallback: raw callback JSON has promotion_data
                if (($discount_type === 0 || $discount_value === 0.0) && $order) {
                    $raw = $order->get_meta(\BWDK\Support\Constant::META_BWDK_JSON_CB);
                    if (is_string($raw)) {
                        $raw = json_decode($raw, true);
                    }
                    if (is_array($raw) && !empty($raw['promotion_data']) && is_array($raw['promotion_data'])) {
                        $code = $item->get_code();
                        $orig = $item->get_meta('_bwdk_promotion_original_code');
                        $match = (isset($raw['promotion_data']['code']) && (string) $raw['promotion_data']['code'] === $code)
                            || (string) $orig === (string) ($raw['promotion_data']['code'] ?? '');
                        if ($match) {
                            if ($discount_type === 0 && isset($raw['promotion_data']['discount_type'])) {
                                $discount_type = (int) $raw['promotion_data']['discount_type'];
                            }
                            if ($discount_value === 0.0 && isset($raw['promotion_data']['discount_value'])) {
                                $discount_value = (float) $raw['promotion_data']['discount_value'];
                            }
                        }
                    }
                }
            }
            
            // Include when we have discount_type 1 (percent) or 2 (amount); discount_value can be 0
            if ($discount_type === 1 || $discount_type === 2) {
                $bwdk_coupons[] = [
                    'item_id' => $item_id,
                    'code' => $item->get_code(),
                    'discount_type' => $discount_type,
                    'discount_value' => $discount_value,
                ];
            }
        }
        
        if (empty($bwdk_coupons)) {
            return;
        }
        
        $toman_label = esc_js(__('تومان', 'bwdk'));
        ?>
        <script type="text/javascript">
        (function($) {
            $(document).ready(function() {
                <?php foreach ($bwdk_coupons as $coupon): ?>
                    (function() {
                        var itemId = <?php echo esc_js($coupon['item_id']); ?>;
                        var discountType = <?php echo esc_js($coupon['discount_type']); ?>;
                        var discountValue = <?php echo esc_js($coupon['discount_value']); ?>;
                        var couponCode = <?php echo json_encode($coupon['code'], JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT); ?>;
                        
                        // Tooltip from promotion_data.discount_type + discount_value (not discount_amount)
                        var tooltipText = '';
                        if (discountType === 1) {
                            tooltipText = discountValue.toFixed(2) + '%';
                        } else if (discountType === 2) {
                            var formattedValue = discountValue.toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
                            tooltipText = formattedValue + ' <?php echo $toman_label; ?>';
                        }
                        
                        if (!tooltipText) {
                            return;
                        }
                        
                        // Normalize code for matching (e.g. "mar50" matches "mar۵۰" in Persian)
                        var codeNorm = (couponCode + '').replace(/\d/g, function(d) {
                            var persian = '۰۱۲۳۴۵۶۷۸۹';
                            return persian.charAt(parseInt(d, 10));
                        });
                        function applyTooltipFix() {
                            // 1) Table row: replace discount column and set tooltips
                            var $couponRow = $('tr[data-order_item_id="' + itemId + '"]');
                            if ($couponRow.length === 0) {
                                $couponRow = $('tr').filter(function() {
                                    var t = $(this).find('td.name').text();
                                    return t.indexOf(couponCode) !== -1 || t.indexOf(codeNorm) !== -1;
                                });
                            }
                            if ($couponRow.length > 0) {
                                var $discountCell = $couponRow.find('td.discount');
                                if ($discountCell.length > 0) {
                                    $discountCell.attr({ 'title': tooltipText, 'data-tip': tooltipText });
                                    $discountCell.find('[title], [data-tip]').attr({ 'title': tooltipText, 'data-tip': tooltipText });
                                    $discountCell.find('span, .amount, .view, div').each(function() { $(this).text(tooltipText); });
                                    if ($discountCell.text().replace(/\s/g, '').replace(/٬|,/g, '') !== tooltipText.replace(/\s/g, '')) {
                                        $discountCell.html('<span class="amount">' + tooltipText + '</span>');
                                    }
                                }
                                $couponRow.find('td.name').attr({ 'title': tooltipText, 'data-tip': tooltipText });
                                $couponRow.find('[title], [data-tip], .tips').each(function() {
                                    var $el = $(this);
                                    if ($el.attr('title')) { $el.attr('title', tooltipText); }
                                    if ($el.attr('data-tip')) { $el.attr('data-tip', tooltipText); }
                                    if ($el.hasClass('tips')) { $el.text(tooltipText); }
                                });
                            }
                            // 2) Coupons section / badges: any node whose text is exactly the coupon code (e.g. mar50 / mar۵۰)
                            var $scope = $('#post-body, #poststuff, .woocommerce-order, .order_data_column, [id^="order_"]').first();
                            if ($scope.length === 0) { $scope = $(document.body); }
                            $scope.find('*').addBack().filter(function() {
                                var $n = $(this);
                                var text = $n.text().trim();
                                if (text !== couponCode && text !== codeNorm) { return false; }
                                return true;
                            }).attr({ 'title': tooltipText, 'data-tip': tooltipText });
                            // 3) Common selectors for coupon badges
                            $scope.find('.coupon code, .order-item-coupon .code, [data-code="' + couponCode + '"]').attr({ 'title': tooltipText, 'data-tip': tooltipText });
                        }
                        
                        applyTooltipFix();
                        setTimeout(applyTooltipFix, 100);
                        setTimeout(applyTooltipFix, 500);
                        setTimeout(applyTooltipFix, 1500);
                    })();
                <?php endforeach; ?>
            });
        })(jQuery);
        </script>
        <?php
    }

}
