<?php
namespace WalletUpPro\Core\Display;

use WalletUpPro\Services\QRCodeService;
use WalletUpPro\Core\Error\ErrorHandler;
use Exception;

if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly.
}

class DisplayHandler
{
    /** @var DisplayHandler|null */
    private static $instance = null;

    /** @var QRCodeService */
    private $qrService;

    /** @var ErrorHandler */
    private $errorHandler;

    /** @var array QR size dimensions */
    private const QR_DIMENSIONS = [
        'small' => 150,
        'medium' => 180,
        'large' => 250
    ];

    /** @var array Error messages */
    private const ERROR_MESSAGES = [
        'qr_generation' => 'Error: QR Code generation failed. %s',
        'display_error' => 'Error generating display: %s'
    ];

    public static function getInstance(): self
    {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Private constructor
     */
    private function __construct()
    {
        $this->errorHandler = ErrorHandler::getInstance();
        $this->initializeServices();
    }

    private function initializeServices(): void
    {
        try {
            $this->qrService = QRCodeService::getInstance();
            if (!$this->qrService) {
                throw new Exception(esc_html('Failed to initialize QR service'));
            }

            $status = $this->qrService->getStatus();
            if (!$status['library_loaded']) {
                throw new Exception(esc_html('QR Code library not loaded'));
            }

        } catch (Exception $e) {
            $this->errorHandler->log('Display Handler initialization error: ' . $e->getMessage());
            throw $e;
        }
    }

    public function generateDisplay(
        string $mode,
        string $url,
        string $method,
        array $settings,
        array $data = []
    ): string {
        try {

            $post_id = $data['post_id'] ?? get_the_ID() ?: 0;
            $tracking_attr = sprintf('data-wallet-up-method="%s" data-wallet-up-post="%d"', esc_attr($method), intval($post_id));

            // Click tracking strategy:
            // - <a href> uses DIRECT payment URL (no redirect) to avoid Cloudflare challenge blocking
            // - Clicks are tracked via inline JS sendBeacon to admin-ajax.php (user already on page, has CF cookies)
            // - QR image data wraps URL via QRCodeService::generateQR() for scan tracking (phone browsers solve CF challenge)
            // A merchant-uploaded QR image (e.g. a bank's own Zelle code) is the only
            // reliable artifact for methods we can't deep-link into. When one is on file
            // it fully replaces the generated QR/link — there's no working scheme to wrap.
            $customQrImage = $this->getCustomQRImage($method);
            if ($customQrImage !== '') {
                $html = $this->generateCustomQRImage($method, $customQrImage, $settings);
            } else {
                switch ($mode) {
                    case 'qr':
                        $html = $this->generateQRCode($url, $data['amount'] ?? '', $settings, $method, $tracking_attr);
                        break;
                    case 'button':
                        $html = $this->generateButton($url, $data['amount'] ?? '', $method, $settings, $tracking_attr);
                        break;
                    default:
                        $html = $this->generateLink($url, $data['amount'] ?? '', $method, $settings, $tracking_attr);
                        break;
                }

                // Crypto: surface the receiving address as copyable text. A QR or a
                // wallet: deeplink assumes a second device to scan or a default wallet
                // app registered for the scheme. A payer on the same device showing the
                // QR — or using a wallet that isn't the scheme's default handler — needs
                // the raw address to paste manually. Appended as a sibling of the
                // deeplink anchor so the copy button can't trigger the wallet: jump.
                $html .= $this->generateCryptoAddress($method);
            }

            // Click tracking JS is enqueued globally by AssetManager::enqueueFrontendQRProtect()
            // on all pages with WC checkout or WalletUp shortcodes. It listens for clicks on
            // [data-wallet-up-method] elements and fires sendBeacon to admin-ajax.php.

            // Order reference: on the order-received page, show the real order number so the
            // payer can put it in their payment note and we can match the payment to the order.
            // Gated by a merchant toggle (default on); skipped for crypto (those reconcile by
            // transaction hash, not a note).
            $html .= $this->generateOrderReferenceNote($method, $data);

            // Zelle is scanned from inside a bank app — not every bank offers that, so always
            // show the handle with a Copy button and a plain how-to as the reliable fallback.
            $html .= $this->generateZelleHelper($method);

            // Unified tracking: record impression server-side (premium only)
            if (class_exists(\WalletUpPro\Core\Analytics\AnalyticsHandler::class)) {
                try {
                    $analytics = \WalletUpPro\Core\Analytics\AnalyticsHandler::getInstance();
                    $analytics->recordImpression($method, intval($post_id), $mode, $data['post_title'] ?? '');
                } catch (\Exception $e) {
                    // Don't break display if tracking fails
                }
            }

            // Append "I've Sent My Payment" confirmation form for P2P methods
            // ONLY on thank-you / order-received pages — NEVER on checkout or AJAX checkout display
            $isCheckout = ($data['skip_confirmation'] ?? false)
                || (function_exists('is_checkout') && is_checkout() && !is_wc_endpoint_url('order-received'))
                || (wp_doing_ajax() && isset($_POST['action']) && in_array(sanitize_text_field(wp_unslash($_POST['action'])), ['wallet_up_wc_payment_display', 'wallet_up_checkout_display'], true));
            // Only show on thank-you pages (must have order_id in data)
            $hasOrderId = !empty($data['order_id']) && intval($data['order_id']) > 0;
            if (!empty($data['amount']) && !$isCheckout && $hasOrderId) {
                $wcOrderId = intval($data['order_id'] ?? 0);
                $formHtml = $this->generateConfirmationForm($method, $data['amount'] ?? '', intval($post_id), $wcOrderId);
                $html .= $formHtml['html'];
                // Enqueue the JS via wp_footer to avoid script stripping by wp_kses
                if (!empty($formHtml['js'])) {
                    $js = $formHtml['js'];
                    add_action('wp_footer', function () use ($js) {
                        echo '<script>' . $js . '</script>';
                    }, 99);
                }
            }

            return $html;
        } catch (Exception $e) {
            $this->errorHandler->log('Display generation error: ' . $e->getMessage());
            return $this->formatError('display_error', $e->getMessage());
        }
    }

    private function generateQRCode($url, $amount, $settings, $method, $tracking_attr)
    {
        try {
            // Support both formats of settings
            $border_style = $settings['qrBorder'] ?? $settings['border'] ?? false;
            $bg_color = $settings['qrBackground'] ?? $settings['background'] ?? '#FFFFFF';
            $qr_style_type = $settings['qrStyle'] ?? $settings['style'] ?? 'square';
            $qr_size = $settings['qrSize'] ?? $settings['size'] ?? 'medium';
            $qr_size_px = self::QR_DIMENSIONS[$qr_size] ?? 180;

            // Extract post_id from tracking attribute for scan tracking
            $post_id = 0;
            if (preg_match('/data-wallet-up-post="(\d+)"/', $tracking_attr, $m)) {
                $post_id = (int)$m[1];
            }

            // Pass payment_method + post_id in settings so QRCodeService
            // auto-wraps with scan tracking redirect (centralized in QRCodeService)
            $vsrc = $this->generateQRSource($url, [
                'qrSize' => $qr_size,
                'size' => $qr_size,
                'qrColor' => $settings['qrColor'] ?? $settings['color'] ?? '#674FBF',
                'color' => $settings['qrColor'] ?? $settings['color'] ?? '#674FBF',
                'qrBackground' => $bg_color,
                'background' => $bg_color,
                'qrBorder' => $border_style,
                'border' => $border_style,
                'qrStyle' => $qr_style_type,
                'style' => $qr_style_type,
                'payment_method' => $method,
                'post_id' => $post_id,
            ]);

            if (empty($vsrc)) {
                throw new Exception(esc_html('Failed to generate QR code source'));
            }

            // Container styles
            $container_style = sprintf(
                "padding: 10px; max-width: %spx; text-align: center;",
                $qr_size_px + 40
            );

            // Style determination with both formats support
            $container_radius = $image_radius = $border_css = '';
            switch ($qr_style_type) {
                case 'rounded':
                    $container_radius = '26px';
                    $image_radius = '12px';
                    $border_css = $border_style ? 'border: 1px solid #ddd;' : '';
                    break;
                case 'dot':
                    $container_radius = '16px';
                    $image_radius = '8px';
                    $border_css = $border_style ? 'border: 2px dotted #ddd; border-spacing: 2px;' : '';
                    break;
                default:
                    $container_radius = '4px';
                    $image_radius = '2px';
                    $border_css = $border_style ? 'border: 1px solid #ddd;' : '';
                    break;
            }

            // QR container styles with dual format support
            $qr_container_style = sprintf(
                "background: %s; border-radius: %s; padding: 16px; %s box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); display: inline-block; overflow: hidden; %s",
                $settings['showBackground'] ?? true ? esc_attr($bg_color) : 'transparent',
                $container_radius,
                $qr_style_type === 'dot' ? 'position: relative;' : '',
                $border_css
            );

            // Dot style with dual format support
            $dot_style = '';
            if ($qr_style_type === 'dot' && $border_style) {
                $dot_style = sprintf(
                    '<style>
                        .walletup-content::before {
                            content: "";
                            position: absolute;
                            top: 8px;
                            left: 8px;
                            right: 8px;
                            bottom: 8px;
                            border: 2px dotted #ddd;
                            border-radius: 8px;
                            pointer-events: none;
                        }
                    </style>'
                );
            }

            // QR image styles - with !important and min dimensions to resist theme CSS overrides
            $qr_style = sprintf(
                "display: block !important; margin: 10px auto !important; height: %spx !important; width: %spx !important; min-width: %spx !important; min-height: %spx !important; max-width: none !important; border-radius: %s; %s",
                $qr_size_px,
                $qr_size_px,
                $qr_size_px,
                $qr_size_px,
                $image_radius,
                $qr_style_type === 'dot' ? 'position: relative; z-index: 1;' : ''
            );

            // Message generation with dual format support
            $message = $this->generateMessage($amount, $method, [
                'hideMessage' => $settings['hideMessage'] ?? $settings['hide_message'] ?? false,
                'showDefaultMessage' => $settings['showDefaultMessage'] ?? $settings['show_default_message'] ?? true,
                'customMessage' => $settings['customMessage'] ?? $settings['custom_message'] ?? '',
                'qrSize' => $qr_size,
                'size' => $qr_size,
                'holder' => $settings['holder'] ?? ''
            ], 'qr');

            // Branding settings (user-controllable from admin)
            $show_method_logo = $settings['showMethodLogo'] ?? $settings['show_method_logo'] ?? true;
            $show_accent_bar = $settings['showAccentBar'] ?? $settings['show_accent_bar'] ?? true;
            $show_powered_by = $settings['showPoweredBy'] ?? $settings['show_powered_by'] ?? true;

            // Method branding: logo + accent color
            $method_colors = [
                'cashapp' => '#00D632', 'venmo' => '#3D95CE', 'paypal' => '#003087',
                'zelle' => '#6C1CD3', 'fbpay' => '#0866FF', 'waluppay' => '#674FBF',
                'bitcoin' => '#F7931A', 'ethereum' => '#627EEA', 'usdt' => '#26A17B',
                'usdc' => '#2775CA', 'bnb' => '#F3BA2F', 'dogecoin' => '#C2A633',
            ];
            $accent_color = $method_colors[$method] ?? '#674FBF';
            $plugin_url = defined('WALLET_UP_PRO_URL') ? WALLET_UP_PRO_URL : plugin_dir_url(dirname(__DIR__, 2) . '/wallet-up.php');
            $logo_file = $plugin_url . 'assets/images/' . $method . '-walup.png';
            $method_name = ucfirst($method);
            $method_names = [
                'cashapp' => 'Cash App', 'venmo' => 'Venmo', 'paypal' => 'PayPal.me',
                'zelle' => 'Zelle', 'fbpay' => 'Meta Pay', 'waluppay' => 'WalUp Pay',
                'bitcoin' => 'Bitcoin', 'ethereum' => 'Ethereum', 'usdt' => 'USDT',
                'usdc' => 'USDC', 'bnb' => 'BNB', 'dogecoin' => 'Dogecoin',
            ];
            $method_name = $method_names[$method] ?? ucfirst($method);

            // Method logo HTML (conditional)
            $logo_html = '';
            if ($show_method_logo) {
                $logo_html = sprintf(
                    '<div style="text-align:center;margin-bottom:8px;"><img src="%s" alt="%s" style="height:28px;width:auto;display:inline-block;border-radius:6px;" onerror="this.style.display=\'none\'"></div>',
                    esc_url($logo_file),
                    esc_attr($method_name)
                );
            }

            // Accent bar at top (conditional) — parent overflow:hidden clips to container radius
            $accent_bar = '';
            if ($show_accent_bar) {
                $accent_bar = sprintf(
                    '<div style="height:4px;background:%s;margin:-16px -16px 12px -16px;"></div>',
                    esc_attr($accent_color)
                );
            }

            // Powered by footer (conditional)
            $powered_by = '';
            if ($show_powered_by) {
                $powered_by = '<div style="text-align:center;margin-top:10px;padding-top:8px;border-top:1px solid rgba(0,0,0,0.06);"><a href="https://walletup.app" target="_blank" rel="noopener" style="font-size:10px;color:#9CA3AF;text-decoration:none;font-family:-apple-system,BlinkMacSystemFont,sans-serif;letter-spacing:0.02em;">Powered by <span style="color:#674FBF;font-weight:600;">WalletUp</span></a></div>';
            }

            return sprintf(
                '%s
                <a href="%s" target="_blank" rel="noopener" class="walletup-qr-link" data-walletup-link="%s" %s style="text-decoration:none !important;">
                    <div class="walletup-container" style="%s">
                        <div class="walletup-content" style="%s">
                            %s
                            %s
                            %s
                            <img style="%s"
                                alt="%s QR Code" src="%s" data-walletup-qr="%s">
                            %s
                        </div>
                    </div>
                </a>',
                $dot_style,
                $url,
                $method,
                $tracking_attr,
                $container_style,
                $qr_container_style,
                $accent_bar,
                $logo_html,
                $message,
                $qr_style,
                esc_attr($method_name),
                $vsrc,
                $method,
                $powered_by
            );

        } catch (Exception $e) {
            $this->errorHandler->log('QR Generation Error: ' . $e->getMessage());
            return $this->formatError('qr_generation', $e->getMessage());
        }
    }

    private function generateQRSource($payment_url, $display_settings)
    {
        try {
            // Get QR size from either format of settings
            $qr_size = self::QR_DIMENSIONS[$display_settings['qrSize'] ?? $display_settings['size'] ?? 'medium'] ?? 180;

            // Support both formats of settings (with and without 'qr' prefix)
            $qr_settings = [
                'qrSize' => $qr_size,
                'qrColor' => $display_settings['qrColor'] ?? $display_settings['color'] ?? '#674FBF',
                'qrBackground' => $display_settings['qrBackground'] ?? $display_settings['background'] ?? '#FFFFFF',
            ];

            // Forward scan tracking context to QRCodeService
            if (!empty($display_settings['payment_method'])) {
                $qr_settings['payment_method'] = $display_settings['payment_method'];
            }
            if (!empty($display_settings['post_id'])) {
                $qr_settings['post_id'] = $display_settings['post_id'];
            }

            $this->errorHandler->log("QR Code generation starting for URL: " . $payment_url);

            $qrDataUri = $this->qrService->generateQR($payment_url, $qr_settings);
            
            if (empty($qrDataUri)) {
                $this->errorHandler->log("ERROR: QR service returned empty data URI");
            } else {
            }
            
            return $qrDataUri;
        } catch (Exception $e) {
            $this->errorHandler->log('QR Source Generation Error: ' . $e->getMessage());
            throw $e;
        }
    }

    private function generateButton($url, $amount, $method, $settings, $tracking_attr)
    {
        try {
            $imgsrc = esc_url(WALLET_UP_URL . 'assets/images/' . $method . '-walup.png');
            $border_style = $settings['qrBorder'] ?? false;
            $bg_color = $settings['qrBackground'] ?? '#FFFFFF';
            $style_type = $settings['qrStyle'] ?? 'square';

            $container_radius = $image_radius = $border_css = '';
            switch ($style_type) {
                case 'rounded':
                    $container_radius = '26px';
                    $image_radius = '12px';
                    $border_css = $border_style ? 'border: 1px solid #ddd;' : '';
                    break;

                case 'dot':
                    $container_radius = '16px';
                    $image_radius = '8px';
                    $border_css = $border_style ? 'border: 2px dotted #ddd; border-spacing: 2px;' : '';
                    break;

                default: // square style
                    $container_radius = '4px';
                    $image_radius = '2px';
                    $border_css = $border_style ? 'border: 1px solid #ddd;' : '';
                    break;
            }

            // Container styles
            $container_style = "padding: 10px; max-width: 200px; text-align: center;";

            // Button container styles
            $button_container_style = sprintf(
                "background: %s; border-radius: %s; padding: 16px; %s box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); display: inline-block; %s",
                esc_attr($bg_color),
                $container_radius,
                $style_type === 'dot' ? 'position: relative;' : '',
                $border_css
            );

            // Additional dotted border style for dot type
            $dot_style = '';
            if ($style_type === 'dot' && $border_style) {
                $dot_style = sprintf(
                    '<style>
                    .walletup-button-content::before {
                        content: "";
                        position: absolute;
                        top: 8px;
                        left: 8px;
                        right: 8px;
                        bottom: 8px;
                        border: 2px dotted #ddd;
                        border-radius: 8px;
                        pointer-events: none;
                    }
                </style>'
                );
            }

            // Button image styles
            $button_style = sprintf(
                "display: block; margin: 10px auto; max-width: 150px; height: auto; border-radius: %s; %s",
                $image_radius,
                $style_type === 'dot' ? 'position: relative; z-index: 1;' : ''
            );

            return sprintf(
                '%s
                <a href="%s" target="_blank" rel="noopener" class="walletup-button-link" data-walletup-link="%s" %s>
                    <div class="walletup-button-container" style="%s">
                        <div class="walletup-button-content" style="%s">
                            %s
                            <img style="%s" alt="Pay with %s" src="%s">
                        </div>
                    </div>
                </a>',
                $dot_style,
                $url,
                $method,
                $tracking_attr, // For the link element
                $container_style,
                $button_container_style,
                $this->generateMessage($amount, $method, array_merge($settings, ['holder' => $settings['holder'] ?? '']), 'button'),
                $button_style,
                ucfirst($method),
                $imgsrc
            );
        } catch (Exception $e) {
            $this->errorHandler->log('Button Generation Error: ' . $e->getMessage());
            return $this->formatError('display_error', $e->getMessage());
        }
    }

    private function generateLink($url, $amount, $method, $settings, $tracking_attr)
    {
        try {
            $link_color = $settings['qrColor'] ?? '#674FBF';
            $bg_color = $settings['qrBackground'] ?? '#FFFFFF';
            $border_style = $settings['qrBorder'] ?? false;
            $style_type = $settings['qrStyle'] ?? 'square';

            $container_radius = $border_css = '';
            switch ($style_type) {
                case 'rounded':
                    $container_radius = '26px';
                    $border_css = $border_style ? 'border: 1px solid #ddd;' : '';
                    break;

                case 'dot':
                    $container_radius = '16px';
                    $border_css = $border_style ? 'border: 2px dotted #ddd; border-spacing: 2px;' : '';
                    break;

                default: // square style
                    $container_radius = '4px';
                    $border_css = $border_style ? 'border: 1px solid #ddd;' : '';
                    break;
            }

            // Container styles
            $container_style = "text-align: center;";

            // Link container styles
            $link_container_style = sprintf(
                "background: %s; border-radius: %s; padding: 16px; %s box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); display: inline-block; %s",
                esc_attr($bg_color),
                $container_radius,
                $style_type === 'dot' ? 'position: relative;' : '',
                $border_css
            );

            // Additional dotted border style for dot type
            $dot_style = '';
            if ($style_type === 'dot' && $border_style) {
                $dot_style = sprintf(
                    '<style>
                        .walletup-link-content::before {
                            content: "";
                            position: absolute;
                            top: 8px;
                            left: 8px;
                            right: 8px;
                            bottom: 8px;
                            border: 2px dotted #ddd;
                            border-radius: 8px;
                            pointer-events: none;
                        }
                    </style>'
                );
            }

            return sprintf(
                '%s
                <a href="%s" target="_blank" rel="noopener" class="walletup-link-wrapper"
                    data-walletup-link="%s" %s style="color: %s; text-decoration: none;">
                    <div class="walletup-link-container" style="%s">
                        <div class="walletup-link-content" style="%s">
                            %s
                            <div style="margin-top: 8px;">Pay with %s</div>
                        </div>
                    </div>
                </a>',
                $dot_style,
                $url,
                $method,
                $tracking_attr, // For the link element
                $link_color,
                $link_container_style,
                $container_style,
                $this->generateMessage($amount, $method, array_merge($settings, ['holder' => $settings['holder'] ?? '']), 'link'),
                ucfirst($method)
            );
        } catch (Exception $e) {
            $this->errorHandler->log('Link Generation Error: ' . $e->getMessage());
            return $this->formatError('display_error', $e->getMessage());
        }
    }

    /**
     * Generate "I've Sent My Payment" confirmation form.
     * For WC orders: auto-fills from billing, hides name/email, passes order_id.
     * For non-WC: shows input fields for customer info.
     *
     * @return array{html: string, js: string}
     */
    private function generateConfirmationForm(string $method, string $amount, int $postId, int $wcOrderId = 0): array
    {
        $nonce = wp_create_nonce('walletup_confirm_payment');
        $ajaxUrl = admin_url('admin-ajax.php');
        $methodName = ucfirst(str_replace('_', ' ', $method));
        $formId = 'walletup-confirm-' . wp_rand(1000, 9999);

        // For WC orders: hide name/email (auto-pulled from billing), only ask for reference
        $isWcOrder = $wcOrderId > 0;
        $nameEmailFields = '';
        if (!$isWcOrder) {
            $nameEmailFields = sprintf(
                '<input type="text" id="%1$s-name" placeholder="%2$s" style="width:100%%;padding:8px 12px;border:1px solid #d1d5db;border-radius:6px;font-size:13px;margin-bottom:8px;box-sizing:border-box" />
                 <input type="email" id="%1$s-email" placeholder="%3$s" style="width:100%%;padding:8px 12px;border:1px solid #d1d5db;border-radius:6px;font-size:13px;margin-bottom:8px;box-sizing:border-box" />',
                esc_attr($formId),
                esc_attr__('Your Name', 'walletup'),
                esc_attr__('Your Email', 'walletup')
            );
        }

        $html = sprintf(
            '<div class="walletup-confirm-wrapper" style="margin-top:16px;text-align:center">
                <button type="button" id="%1$s-toggle"
                    style="background:none;border:1px solid #d1d5db;border-radius:8px;padding:8px 20px;font-size:13px;color:#4b5563;cursor:pointer;font-weight:500">
                    %2$s
                </button>
                <div id="%1$s" style="display:none;margin-top:12px;text-align:left;max-width:360px;margin-left:auto;margin-right:auto;padding:16px;border:1px solid #e5e7eb;border-radius:12px;background:#fafafa">
                    <p style="font-size:13px;color:#374151;margin:0 0 12px;font-weight:600">%3$s</p>
                    %8$s
                    <input type="text" id="%1$s-ref" placeholder="%4$s" style="width:100%%;padding:8px 12px;border:1px solid #d1d5db;border-radius:6px;font-size:13px;margin-bottom:12px;box-sizing:border-box" />
                    <button type="button" id="%1$s-btn" style="width:100%%;padding:10px;background:#6366f1;color:#fff;border:none;border-radius:8px;font-size:13px;font-weight:600;cursor:pointer">
                        %5$s
                    </button>
                    <div id="%1$s-msg" style="margin-top:8px;font-size:12px;display:none"></div>
                </div>
            </div>',
            esc_attr($formId),
            esc_html__("I've Sent My Payment", 'walletup'),
            esc_html(sprintf(__('Confirm your %s payment', 'walletup'), $methodName)),
            esc_attr(sprintf(__('Transaction ID / Reference (%s)', 'walletup'), $methodName)),
            esc_html__('Confirm Payment Sent', 'walletup'),
            '', '', '',
            $nameEmailFields
        );

        // JS is output separately via wp_footer to avoid wp_kses stripping <script> and onclick
        $confirmLabel = esc_js(__('Confirm Payment Sent', 'walletup'));
        $js = sprintf(
            '(function(){var f="%1$s";var isWc=%8$s;var tgl=document.getElementById(f+"-toggle");var frm=document.getElementById(f);if(tgl&&frm){tgl.addEventListener("click",function(){frm.style.display=frm.style.display==="none"?"block":"none"})}var btn=document.getElementById(f+"-btn");if(!btn)return;btn.addEventListener("click",function(){var b=this,m=document.getElementById(f+"-msg");var nEl=document.getElementById(f+"-name");var eEl=document.getElementById(f+"-email");var n=nEl?nEl.value:"";var e=eEl?eEl.value:"";var r=document.getElementById(f+"-ref")?document.getElementById(f+"-ref").value:"";if(!isWc&&nEl&&eEl&&!n&&!e){m.style.display="block";m.style.color="#dc2626";m.textContent="Please enter your name or email.";return}b.disabled=true;b.textContent="Sending...";var fd=new FormData();fd.append("action","walletup_confirm_payment_sent");fd.append("nonce","%2$s");fd.append("payment_method","%3$s");fd.append("amount","%4$s");fd.append("customer_name",n);fd.append("customer_email",e);fd.append("transaction_reference",r);fd.append("post_id","%5$s");fd.append("wc_order_id","%9$s");fetch("%6$s",{method:"POST",body:fd}).then(function(r){return r.json()}).then(function(d){m.style.display="block";if(d.success){m.style.color="#059669";m.textContent=d.data.message||"Confirmation received!";b.textContent="Sent!";tgl.style.display="none"}else{m.style.color="#dc2626";m.textContent=d.data&&d.data.message?d.data.message:"Failed.";b.disabled=false;b.textContent="%7$s"}}).catch(function(){m.style.display="block";m.style.color="#dc2626";m.textContent="Network error.";b.disabled=false;b.textContent="%7$s"})})})();',
            esc_js($formId),
            esc_js($nonce),
            esc_js($method),
            esc_js($amount),
            esc_js($postId),
            esc_url($ajaxUrl),
            $confirmLabel,
            $isWcOrder ? 'true' : 'false',
            esc_js($wcOrderId)
        );

        return ['html' => $html, 'js' => $js];
    }

    private function isCryptocurrency(string $method): bool
    {
        return in_array($method, ['bitcoin', 'ethereum', 'usdt', 'usdc', 'bnb', 'dogecoin', 'litecoin']);
    }

    /**
     * Receiving address as copyable text for a crypto method.
     *
     * Reads the same source getHolder() uses (wallet_up_transfer_call), never the
     * payment URL: USDT/USDC encode an EIP-681 token-contract URI
     * (ethereum:<contract>/transfer?address=<recipient>), so the recipient lives
     * in a query parameter, not after the scheme — parsing the URL would surface
     * the contract address. Returns '' for non-crypto methods or when no address
     * is configured, so the caller can append unconditionally.
     */
    /**
     * URL of a merchant-uploaded QR image for this method, or '' if none.
     * Stored per method in wallet_up_custom_qr_images by the Payments admin.
     */
    private function getCustomQRImage(string $method): string
    {
        $images = get_option('wallet_up_custom_qr_images', []);
        if (!is_array($images)) {
            return '';
        }
        $url = trim((string) ($images[$method] ?? ''));
        return $url;
    }

    /**
     * Render a merchant-uploaded QR image in the standard card, with no payment-link
     * wrapper (the image is the payment artifact — e.g. a bank's own Zelle code — so
     * there's nothing to click through to).
     */
    private function generateCustomQRImage(string $method, string $imageUrl, array $settings): string
    {
        $show_method_logo = $settings['showMethodLogo'] ?? true;
        $show_powered_by  = $settings['showPoweredBy'] ?? true;

        $method_names = [
            'cashapp' => 'Cash App', 'venmo' => 'Venmo', 'paypal' => 'PayPal.me',
            'zelle' => 'Zelle', 'fbpay' => 'Meta Pay', 'waluppay' => 'WalUp Pay',
        ];
        $method_name = $method_names[$method] ?? ucfirst($method);

        $logo_html = '';
        if ($show_method_logo) {
            $plugin_url = defined('WALLET_UP_PRO_URL') ? WALLET_UP_PRO_URL : plugin_dir_url(dirname(__DIR__, 2) . '/wallet-up.php');
            $logo_file = $plugin_url . 'assets/images/' . $method . '-walup.png';
            $logo_html = sprintf(
                '<div style="text-align:center;margin-bottom:8px;"><img src="%s" alt="%s" style="height:28px;width:auto;display:inline-block;border-radius:6px;" onerror="this.style.display=\'none\'"></div>',
                esc_url($logo_file),
                esc_attr($method_name)
            );
        }

        $powered_by = '';
        if ($show_powered_by) {
            $powered_by = '<div style="text-align:center;margin-top:10px;padding-top:8px;border-top:1px solid rgba(0,0,0,0.06);"><a href="https://walletup.app" target="_blank" rel="noopener" style="font-size:10px;color:#9CA3AF;text-decoration:none;font-family:-apple-system,BlinkMacSystemFont,sans-serif;letter-spacing:0.02em;">Powered by <span style="color:#674FBF;font-weight:600;">WalletUp</span></a></div>';
        }

        return sprintf(
            '<div class="walletup-container walletup-custom-qr" style="max-width:220px;margin:0 auto;text-align:center;">'
                . '<div class="walletup-content" style="background:#FFFFFF;border-radius:12px;padding:16px;box-shadow:0 4px 6px -1px rgba(0,0,0,0.1);">'
                    . '%s'
                    . '<img src="%s" alt="%s QR Code" style="display:block;width:100%%;height:auto;border-radius:8px;" data-walletup-custom-qr="%s">'
                    . '%s'
                . '</div>'
            . '</div>',
            $logo_html,
            esc_url($imageUrl),
            esc_attr($method_name),
            esc_attr($method),
            $powered_by
        );
    }

    /**
     * "Please include Order #N in your payment note" — shown on the order-received page
     * for non-crypto methods when the merchant toggle is on (default on).
     */
    private function generateOrderReferenceNote(string $method, array $data): string
    {
        if (empty($data['order_id']) || intval($data['order_id']) <= 0) {
            return '';
        }

        $wc = get_option('wallet_up_wc_settings', []);
        $enabled = !is_array($wc)
            || !array_key_exists('show_order_id_in_instructions', $wc)
            || !empty($wc['show_order_id_in_instructions']);
        if (!$enabled) {
            return '';
        }

        // Crypto transfers carry no payer-supplied note; they reconcile by tx hash.
        if ($this->isCryptocurrency($method)) {
            return '';
        }

        $order_ref = sprintf(
            /* translators: %s: order number, e.g. "Order #123" */
            esc_html__('Please include "%s" in your payment note', 'walletup'),
            esc_html(sprintf(
                /* translators: %s: numeric order id */
                __('Order #%s', 'walletup'),
                $data['order_id']
            ))
        );

        return sprintf(
            '<div class="walletup-order-note" style="text-align: center; margin-top: 8px; padding: 6px 12px; background: #f0fdf4; border: 1px solid #bbf7d0; border-radius: 8px; font-size: 13px; color: #166534;">%s</div>',
            $order_ref
        );
    }

    /**
     * Zelle help block: how to pay (scan from the bank app) plus the handle with a Copy button
     * as the reliable fallback for banks with no in-app scanner (e.g. M&T) and same-phone payers.
     */
    private function generateZelleHelper(string $method): string
    {
        if ($method !== 'zelle') {
            return '';
        }
        $accounts = get_option('wallet_up_transfer_call', []);
        $handle = is_array($accounts) ? trim((string) ($accounts['zelle_holder'] ?? '')) : '';
        if ($handle === '') {
            return '';
        }

        return sprintf(
            '<div class="walletup-zelle-help" style="max-width:280px;margin:10px auto 0;padding:10px 12px;border:1px solid #e5e7eb;border-radius:10px;background:#fff;font-family:-apple-system,BlinkMacSystemFont,\'Segoe UI\',Roboto,sans-serif;text-align:left;">'
                . '<div style="font-size:12px;line-height:1.5;color:#374151;margin-bottom:8px;">%1$s</div>'
                . '<div style="font-size:11px;font-weight:600;letter-spacing:0.04em;text-transform:uppercase;color:#6B7280;margin-bottom:6px;">%2$s</div>'
                . '<div style="font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:1.5;color:#111827;word-break:break-all;background:#f9fafb;border:1px solid #f0f1f3;border-radius:8px;padding:8px 10px;">%3$s</div>'
                . '<button type="button" class="walletup-copy-address" data-walletup-copy="%4$s" data-copied-label="%5$s" aria-label="%6$s" style="display:block;width:100%%;margin-top:8px;cursor:pointer;border:1px solid #d1d5db;background:#f9fafb;color:#374151;font-size:13px;font-weight:600;border-radius:8px;padding:8px 10px;font-family:inherit;">%7$s</button>'
            . '</div>',
            esc_html__('Open your bank app, choose Zelle, then Scan and point at the code above.', 'walletup'),
            esc_html__('Bank can\'t scan? Send in Zelle to', 'walletup'),
            esc_html($handle),
            esc_attr($handle),
            esc_attr__('Copied', 'walletup'),
            esc_attr__('Copy Zelle handle', 'walletup'),
            esc_html__('Copy', 'walletup')
        );
    }

    private function generateCryptoAddress(string $method): string
    {
        if (!$this->isCryptocurrency($method)) {
            return '';
        }

        $accounts = get_option('wallet_up_transfer_call', []);
        $address = is_array($accounts) ? trim((string) ($accounts[$method . '_holder'] ?? '')) : '';
        if ($address === '') {
            return '';
        }

        // The copy interaction is handled by a delegated listener in wup-events.js
        // (works for AJAX-injected checkout markup); the address rides in a data
        // attribute. JS swaps the button label to data-copied-label on success.
        return sprintf(
            '<div class="walletup-crypto-address" style="max-width:280px;margin:10px auto 0;padding:10px 12px;border:1px solid #e5e7eb;border-radius:10px;background:#fff;font-family:-apple-system,BlinkMacSystemFont,\'Segoe UI\',Roboto,sans-serif;text-align:left;">'
                . '<div style="font-size:11px;font-weight:600;letter-spacing:0.04em;text-transform:uppercase;color:#6B7280;margin-bottom:6px;">%1$s</div>'
                . '<div style="font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;line-height:1.5;color:#111827;word-break:break-all;background:#f9fafb;border:1px solid #f0f1f3;border-radius:8px;padding:8px 10px;">%2$s</div>'
                . '<button type="button" class="walletup-copy-address" data-walletup-copy="%3$s" data-copied-label="%4$s" aria-label="%5$s" style="display:block;width:100%%;margin-top:8px;cursor:pointer;border:1px solid #d1d5db;background:#f9fafb;color:#374151;font-size:13px;font-weight:600;border-radius:8px;padding:8px 10px;font-family:inherit;">%6$s</button>'
            . '</div>',
            esc_html__('Wallet address', 'walletup'),
            esc_html($address),
            esc_attr($address),
            esc_attr__('Copied', 'walletup'),
            esc_attr__('Copy wallet address', 'walletup'),
            esc_html__('Copy', 'walletup')
        );
    }

    private function formatAmountForDisplay(string $amount, string $method): string
    {
        if ($this->isCryptocurrency($method)) {
            $symbols = [
                'bitcoin' => 'BTC',
                'ethereum' => 'ETH',
                'usdt' => 'USDT',
                'usdc' => 'USDC',
                'bnb' => 'BNB',
                'dogecoin' => 'DOGE',
                'litecoin' => 'LTC',
            ];

            if (empty($amount)) {
                return sprintf('%s', $symbols[$method] ?? 'crypto');
            }

            try {
                if (!class_exists(\WalletUpPro\Core\Crypto\CryptoConverter::class)) {
                    throw new \Exception('CryptoConverter not available');
                }
                $converter = \WalletUpPro\Core\Crypto\CryptoConverter::getInstance();
                $conversion = $converter->convertUsdToCrypto(floatval($amount), $method);
                if ($conversion['success'] && !empty($conversion['amount'])) {
                    $cryptoAmount = $conversion['amount'];
                    $symbol = $symbols[$method] ?? strtoupper($method);
                    return sprintf('%s %s ($%s)', esc_html($cryptoAmount), $symbol, esc_html(number_format(floatval($amount), 2)));
                }
            } catch (\Exception $e) {
                // Fallback: show USD amount with crypto label
            }

            // Fallback if conversion fails — show as USD value
            return sprintf('$%s in %s', esc_html(number_format(floatval($amount), 2)), $symbols[$method] ?? strtoupper($method));
        }
        
        // For fiat currencies
        if (empty($amount)) {
            return '';  // Return empty for fiat when no amount
        }
        // Currency must show 2 decimal places. floatval() tolerates strings like
        // "92.70" or "1234.5"; number_format restores trailing zeros and adds
        // thousand separators ("$1,234.50") consistent with the crypto branch above.
        return sprintf('$%s', esc_html(number_format(floatval($amount), 2)));
    }

    private function generateMessage($amount, $method, $settings, $display_mode = 'qr')
    {
        // Support both formats for message display settings
        $hide_message = $settings['hideMessage'] ?? $settings['hide_message'] ?? false;
        if ($hide_message) {
            return '';
        }

        $show_default = $settings['showDefaultMessage'] ?? $settings['show_default_message'] ?? true;
        $custom_message = $settings['customMessage'] ?? $settings['custom_message'] ?? '';

        // Get merchant name for "Pay [merchant]" display
        $merchant_name = $settings['merchant_name'] ?? '';
        if (empty($merchant_name)) {
            $profile = get_option('wallet_up_transfer_call', []);
            $merchant_name = $profile['holder_owner'] ?? '';
        }

        // Support both size formats
        $qr_size = self::QR_DIMENSIONS[$settings['qrSize'] ?? $settings['size'] ?? 'medium'] ?? 180;

        if (empty($amount) && !$show_default && empty($custom_message)) {
            return '';
        }

        // Get action text based on display mode
        $action_text = '';
        switch ($display_mode) {
            case 'qr':
                $action_text = 'Scan or Click';
                break;
            case 'button':
                $action_text = 'Click';
                break;
            case 'link':
                $action_text = 'Click here';
                break;
            default:
                $action_text = 'Click';
                break;
        }

        // Special handling for Zelle to display holder ID
        if ($method === 'zelle' && ($show_default || empty($custom_message))) {
            // Get Zelle holder ID from settings or payment method
            $holder_id = $settings['holder'] ?? $settings['zelle_holder'] ?? '';
            
            if (!empty($holder_id)) {
                if (empty($amount)) {
                    // No amount - just show "Send to recipient via Zelle"
                    return sprintf(
                        '<div class="walletup-message walletup-zelle-message" style="font-size: 14px; text-align: center; width: %spx; margin: 0 auto 10px;">Please <strong>%s</strong> to Send Payment to<br><strong>%s</strong> via Zelle</div>',
                        $qr_size,
                        $action_text,
                        esc_html($holder_id)
                    );
                } else {
                    // With amount - show "Send $50 to recipient via Zelle"
                    $formatted_amount = $this->formatAmountForDisplay($amount, $method);
                    return sprintf(
                        '<div class="walletup-message walletup-zelle-message" style="font-size: 14px; text-align: center; width: %spx; margin: 0 auto 10px;">Please <strong>%s</strong> to Send <strong>%s</strong> to<br><strong>%s</strong> via Zelle</div>',
                        $qr_size,
                        $action_text,
                        $formatted_amount,
                        esc_html($holder_id)
                    );
                }
            }
        }

        if ($show_default || empty($custom_message)) {
            $formatted_amount = $this->formatAmountForDisplay($amount, $method);
            $recipient_suffix = !empty($merchant_name)
                ? sprintf(' to <strong>%s</strong>', esc_html($merchant_name))
                : '';

            // Different messages based on whether amount is provided
            // Method display names
            $method_labels = [
                'cashapp' => 'Cash App', 'venmo' => 'Venmo', 'paypal' => 'PayPal.me',
                'zelle' => 'Zelle', 'fbpay' => 'Meta Pay', 'waluppay' => 'WalUp Pay',
                'bitcoin' => 'Bitcoin', 'ethereum' => 'Ethereum', 'usdt' => 'USDT',
                'usdc' => 'USDC', 'bnb' => 'BNB', 'dogecoin' => 'Dogecoin',
            ];
            $method_label = esc_html($method_labels[$method] ?? ucfirst($method));
            $msg_style = sprintf(
                'font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,sans-serif;text-align:center;width:%spx;margin:0 auto 8px;line-height:1.4;',
                $qr_size
            );

            // Recipient line (separate from amount to avoid size inheritance)
            $recipient_line = !empty($merchant_name)
                ? sprintf('<div style="font-size:12px;color:#6B7280;margin-top:2px;">to <strong style="color:#374151;">%s</strong></div>', esc_html($merchant_name))
                : '';

            if (empty($amount)) {
                if ($this->isCryptocurrency($method)) {
                    return sprintf(
                        '<div class="walletup-message" style="%s"><div style="font-size:13px;color:#6B7280;">%s to send</div><div style="font-size:16px;font-weight:700;color:#111827;margin:2px 0;">%s</div>%s</div>',
                        $msg_style, $action_text, $formatted_amount, $recipient_line
                    );
                } else {
                    return sprintf(
                        '<div class="walletup-message" style="%s"><div style="font-size:13px;color:#6B7280;">%s to pay with</div><div style="font-size:16px;font-weight:700;color:#111827;margin:2px 0;">%s</div>%s</div>',
                        $msg_style, $action_text, $method_label, $recipient_line
                    );
                }
            } else {
                return sprintf(
                    '<div class="walletup-message" style="%s"><div style="font-size:13px;color:#6B7280;">%s to pay</div><div style="font-size:22px;font-weight:700;color:#111827;margin:4px 0;">%s</div><div style="font-size:12px;color:#9CA3AF;">via %s</div>%s</div>',
                    $msg_style, $action_text, $formatted_amount, $method_label, $recipient_line
                );
            }
        } else {
            $formatted_amount = $this->formatAmountForDisplay($amount, $method);
            $message = str_replace(
                ['$amount', '$method'],
                [strpos($custom_message, '$amount') !== false ? $formatted_amount : esc_html($amount), ucfirst($method)],
                $custom_message
            );
            return sprintf(
                '<div class="walletup-message" style="font-size: 14px; text-align: center; width: %spx; margin: 0 auto 10px;">%s</div>',
                $qr_size,
                wp_kses($message, array('strong' => array()))
            );
        }
    }

    private function formatSettingsForQR($settings)
    {
        // Support both formats when formatting settings
        return [
            'qrSize' => $settings['qrSize'] ?? $settings['size'] ?? 'medium',
            'qrColor' => $settings['qrColor'] ?? $settings['color'] ?? '#674FBF',
            'qrBackground' => $settings['qrBackground'] ?? $settings['background'] ?? '#FFFFFF',
            'qrBorder' => $settings['qrBorder'] ?? $settings['border'] ?? false,
            'qrStyle' => $settings['qrStyle'] ?? $settings['style'] ?? 'square',
            'showDefaultMessage' => $settings['showDefaultMessage'] ?? $settings['show_default_message'] ?? true,
            'customMessage' => $settings['customMessage'] ?? $settings['custom_message'] ?? '',
            'hideMessage' => $settings['hideMessage'] ?? $settings['hide_message'] ?? false,
        ];
    }

    private function formatError(string $key, string ...$args): string
    {
        $message = self::ERROR_MESSAGES[$key] ?? 'Unknown error occurred';

        // Include merchant contact on error display
        $contact_html = '';
        $profile = get_option('wallet_up_transfer_call', []);
        $email = $profile['holder_email'] ?? '';
        $phone = $profile['holder_no'] ?? '';
        if (!empty($email) || !empty($phone)) {
            $parts = [];
            if (!empty($email)) {
                $parts[] = sprintf('<a href="mailto:%s">%s</a>', esc_attr($email), esc_html($email));
            }
            if (!empty($phone)) {
                $parts[] = sprintf('<a href="tel:%s">%s</a>', esc_attr($phone), esc_html($phone));
            }
            $contact_html = sprintf(
                '<p style="margin-top:8px;font-size:13px;color:#6b7280;">%s %s</p>',
                esc_html__('Need help? Contact:', 'walletup'),
                implode(' &middot; ', $parts)
            );
        }

        return sprintf(
            '<div class="walletup-error"><p style="color: red;">%s</p>%s</div>',
            esc_html(vsprintf($message, $args)),
            $contact_html
        );
    }


    public function generateTrackingScript(array $data): string
    {
        if (!isset($data['method'])) {
            return '';
        }

        $sanitized_amount = isset($data['amount']) ? esc_js($data['amount']) : '';
        $sanitized_method = esc_js($data['method']);
        $tracking_id = uniqid('walletup_', true);
        $session_id = hash('sha256', wp_get_session_token() . $sanitized_method . time());

        $trackingData = [
            'tracking_id' => $tracking_id,
            'session_id' => $session_id,
            'post_id' => intval($data['post_id'] ?? get_the_ID() ?: 0),
            'post_type' => sanitize_text_field($data['post_type'] ?? get_post_type() ?: 'unknown'),
            'post_title' => sanitize_text_field($data['post_title'] ?? get_the_title() ?: 'Unknown Title'),
            'display_mode' => sanitize_text_field($data['display_mode'] ?? 'unknown'),
            'amount' => $sanitized_amount,
            'method' => $sanitized_method,
            'timestamp' => time(),
            'user_agent_hash' => hash('sha256', sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'] ?? '')) ?? ''),
            'ip_hash' => hash('sha256', wp_privacy_anonymize_ip(sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'] ?? '')) ?? ''))
        ];

        $nonce = wp_create_nonce('wallet_up_admin_nonce');

        ob_start();
        ?>
        <script>
            (() => {
                'use strict';

                const WALLETUP_TRACKER = {
                    method: '<?php echo esc_js($sanitized_method); ?>',
                    nonce: '<?php echo esc_js($nonce); ?>',
                    endpoint: '<?php echo esc_url(admin_url('admin-ajax.php')); ?>',
                    trackingData: <?php echo wp_json_encode($trackingData, JSON_UNESCAPED_SLASHES | JSON_NUMERIC_CHECK); ?>,
                    impressionSent: false,
                    requestQueue: [],
                    isProcessing: false,

                    init() {
                        // This script is embedded WITH the payment display.
                        // If this script runs, the QR/button is being rendered — that IS the impression.
                        this.trackImpression();
                        this.setupClickHandler();
                    },

                    trackImpression() {
                        // Deduplicate: one impression per method per page load
                        const key = 'walletup_imp_' + this.method + '_' + this.trackingData.post_id;
                        if (this.impressionSent || (window._walletupImpressions && window._walletupImpressions[key])) {
                            return;
                        }
                        this.impressionSent = true;
                        if (!window._walletupImpressions) window._walletupImpressions = {};
                        window._walletupImpressions[key] = true;

                        this.sendEvent('impression');
                    },

                    setupClickHandler() {
                        // Listen for clicks on any walletup payment element for this method.
                        // Targets: links, buttons, QR images within the payment display.
                        document.addEventListener('click', (e) => {
                            // Match clicks on walletup containers, links, or QR images for this method
                            const container = e.target.closest(
                                '[data-wallet-up-method="' + this.method + '"],' +
                                '.walletup-display-container,' +
                                '.walletup-qr-container,' +
                                '.walletup-button-container'
                            );
                            if (!container) return;

                            const containerMethod = container.dataset?.walletUpMethod;
                            if (containerMethod && containerMethod !== this.method) return;

                            // Debounce: ignore clicks within 500ms
                            const now = Date.now();
                            if (this._lastClick && (now - this._lastClick) < 500) return;
                            this._lastClick = now;

                            const isQR = e.target.closest('img[data-walletup-qr], .walletup-qr-code, img[src*="qr"]');
                            if (isQR) {
                                this.sendEvent('scan');
                            }
                            this.sendEvent('click');
                        }, { passive: true });
                    },

                    sendEvent(type) {
                        const eventData = {
                            ...this.trackingData,
                            event_type: type,
                            event_timestamp: Date.now(),
                            screen_resolution: window.screen ? (window.screen.width + 'x' + window.screen.height) : ''
                        };
                        this.queueRequest(eventData);
                    },

                    queueRequest(eventData) {
                        this.requestQueue.push(eventData);
                        if (!this.isProcessing) {
                            this.processQueue();
                        }
                    },

                    async processQueue() {
                        if (this.isProcessing || this.requestQueue.length === 0) return;
                        this.isProcessing = true;

                        while (this.requestQueue.length > 0) {
                            const eventData = this.requestQueue.shift();
                            try {
                                await this.sendRequest(eventData);
                            } catch (err) {
                                // Silent fail — don't break user experience
                            }
                        }
                        this.isProcessing = false;
                    },

                    async sendRequest(eventData) {
                        const body = new URLSearchParams({
                            action: 'wallet_up_track_usage',
                            type: eventData.event_type,
                            method: this.method,
                            tracking_data: JSON.stringify(eventData),
                            nonce: this.nonce
                        });

                        // Use sendBeacon for fire-and-forget reliability (survives page navigation)
                        if (navigator.sendBeacon) {
                            const blob = new Blob([body.toString()], { type: 'application/x-www-form-urlencoded' });
                            navigator.sendBeacon(this.endpoint, blob);
                            return;
                        }

                        // Fallback to fetch
                        const controller = new AbortController();
                        const timeoutId = setTimeout(() => controller.abort(), 5000);
                        try {
                            const response = await fetch(this.endpoint, {
                                method: 'POST',
                                headers: {
                                    'Content-Type': 'application/x-www-form-urlencoded',
                                    'X-Requested-With': 'XMLHttpRequest'
                                },
                                body: body,
                                signal: controller.signal,
                                credentials: 'same-origin'
                            });
                            clearTimeout(timeoutId);
                            return response.ok ? await response.json() : null;
                        } catch {
                            clearTimeout(timeoutId);
                            return null;
                        }
                    }
                };

                if (document.readyState === 'loading') {
                    document.addEventListener('DOMContentLoaded', () => WALLETUP_TRACKER.init());
                } else {
                    WALLETUP_TRACKER.init();
                }

                window.WALLETUP_TRACKER = WALLETUP_TRACKER;
            })();
        </script>
        <?php
        $script = ob_get_clean();
        
        // Prevent WordPress from encoding our JavaScript operators
        // This is necessary because some themes/plugins apply content filters that break JS
        $script = str_replace('&amp;&amp;', '&&', $script);
        $script = str_replace('&amp;', '&', $script);
        $script = str_replace('&#038;&#038;', '&&', $script);
        $script = str_replace('&#038;', '&', $script);
        
        return $script;
    }
}