Greasy Fork

AliExpress Real Price

Shows true prices including shipping and variants on AliExpress, since sellers often misleadingly put accessory variants as the primary price, not the advertised item.

// ==UserScript==
// @name         AliExpress Real Price
// @namespace    https://github.com/joshwand/aliexpress-real-price-userscript
// @version      1.0.0
// @description  Shows true prices including shipping and variants on AliExpress, since sellers often misleadingly put accessory variants as the primary price, not the advertised item. 
// @author       Josh Wand
// @license      GPL-3.0-or-later
// @copyright    2025 Josh Wand
// @match        *://*.aliexpress.com/*
// @match        *://*.aliexpress.us/*
// @grant        GM.xmlHttpRequest
// @grant        GM_addStyle
// @grant        GM.getValue
// @grant        GM.setValue
// @grant        GM.cookie
// @connect      aliexpress.us
// @connect      aliexpress.com
// @grant        GM_listValues
// @grant        GM_addStyle
// @grant        GM_xmlhttpRequest
// @grant        unsafeWindow
// ==/UserScript==

(function() {
    'use strict';

    // --- Global Cache Disable Flag ---
    let isCacheDisabled = false;

    // Debug logging utility
    const DEBUG = true;
    const log = (...args) => {
        if (DEBUG) {
            const productId = args.find(arg => typeof arg === 'object' && arg?.productId)?.productId || '';
            console.log(`[AliExpress Real Price${productId ? ` - ID:${productId}` : ''}]`, ...args);
        }
    };

    // Rate limiter for API calls
    class RateLimiter {
        constructor(maxRequests = 2, timeWindow = 1000) {
            this.maxRequests = maxRequests;
            this.timeWindow = timeWindow;
            this.requests = [];
            this.backoffTime = 1000; // Start with 1 second backoff
            this.maxBackoffTime = 32000; // Max backoff of 32 seconds
        }

        async waitForSlot() {
            // Remove old requests outside the time window
            const now = Date.now();
            this.requests = this.requests.filter(time => now - time < this.timeWindow);

            // If we have capacity, add the request
            if (this.requests.length < this.maxRequests) {
                this.requests.push(now);
                return;
            }

            // Wait for the oldest request to expire
            const oldestRequest = this.requests[0];
            const waitTime = this.timeWindow - (now - oldestRequest);
            await new Promise(resolve => setTimeout(resolve, waitTime));
            return this.waitForSlot();
        }

        async executeWithBackoff(fn) {
            while (true) {
                try {
                    await this.waitForSlot();
                    const result = await fn();
                    this.backoffTime = 1000; // Reset backoff on success
                    return result;
                } catch (error) {
                    if (error.message?.includes('FAIL_SYS_ILLEGAL_ACCESS')) {
                        log(`Rate limit exceeded, backing off for ${this.backoffTime}ms`);
                        await new Promise(resolve => setTimeout(resolve, this.backoffTime));
                        this.backoffTime = Math.min(this.backoffTime * 2, this.maxBackoffTime);
                        continue;
                    }
                    throw error;
                }
            }
        }
    }

    // Loading Manager for global progress
    class LoadingManager {
        constructor() {
            this.totalItems = 0;
            this.completedItems = 0;
            this.createElements();
            this.addStyles(); // Add styles for the elements
        }

        createElements() {
            // Create main container for status text and clear button
            this.container = document.createElement('div');
            this.container.className = 'ali-real-price-status-container';
            // this.container.title = 'AliExpress Real Price UserScript';

            // Create icon container for collapsed state
            this.iconContainer = document.createElement('div');
            this.iconContainer.className = 'ali-real-price-icon';
            this.iconContainer.innerHTML = '🐟'; // Fish icon - because the prices are fishy
            this.iconContainer.title = 'Hmm, something is fishy here...';
            this.container.appendChild(this.iconContainer);

            // Create expandable content container
            this.expandableContent = document.createElement('div');
            this.expandableContent.className = 'ali-real-price-expandable-content';

            // Create status text
            this.statusText = document.createElement('div');
            this.statusText.className = 'ali-real-price-status';
            this.expandableContent.appendChild(this.statusText);

            // Create settings container with disclosure arrow
            this.settingsContainer = document.createElement('div');
            this.settingsContainer.className = 'ali-real-price-settings-container';

            // Add disclosure arrow
            this.disclosureArrow = document.createElement('span');
            this.disclosureArrow.className = 'ali-real-price-disclosure-arrow collapsed';
            
            // Create a separate text node for the arrow symbol
            this.arrowSymbol = document.createTextNode('▶');
            this.disclosureArrow.appendChild(this.arrowSymbol);
            this.disclosureArrow.title = 'Advanced Options';

            // Create custom tooltip
            this.tooltip = document.createElement('div');
            this.tooltip.className = 'ali-real-price-tooltip';
            this.tooltip.textContent = 'Advanced Options';
            this.disclosureArrow.appendChild(this.tooltip);

            // Restore click handler
            this.disclosureArrow.onclick = () => {
                const container = this.settingsContainer;
                const isExpanding = !container.classList.contains('expanded');
                container.classList.toggle('expanded');
                this.disclosureArrow.classList.toggle('collapsed');
                this.arrowSymbol.nodeValue = isExpanding ? '▼' : '▶';
            };

            // Remove default title to prevent both tooltips
            this.disclosureArrow.removeAttribute('title');

            this.expandableContent.appendChild(this.disclosureArrow);

            // Settings content (initially hidden)
            this.settingsContent = document.createElement('div');
            this.settingsContent.className = 'ali-real-price-settings-content';

            // --- Create Clear Cache button ---
            this.clearCacheButton = document.createElement('span');
            this.clearCacheButton.className = 'ali-real-price-clear-cache';
            this.clearCacheButton.textContent = 'Clear Cache';
            this.clearCacheButton.onclick = async () => {
                await clearCacheAndReload();
            };
            this.settingsContent.appendChild(this.clearCacheButton);

            // --- Create Disable Cache Checkbox --- 
            this.disableCacheContainer = document.createElement('div');
            this.disableCacheContainer.className = 'ali-real-price-disable-cache-container';

            this.disableCacheCheckbox = document.createElement('input');
            this.disableCacheCheckbox.type = 'checkbox';
            this.disableCacheCheckbox.id = 'ali-real-price-disable-cache-checkbox';
            this.disableCacheCheckbox.className = 'ali-real-price-disable-cache-checkbox';
            log(`[LoadingManager.createElements] Setting checkbox state based on isCacheDisabled: ${isCacheDisabled}`);
            this.disableCacheCheckbox.checked = isCacheDisabled;
            this.disableCacheCheckbox.addEventListener('change', handleDisableCacheChange);

            this.disableCacheLabel = document.createElement('label');
            this.disableCacheLabel.htmlFor = 'ali-real-price-disable-cache-checkbox';
            this.disableCacheLabel.textContent = 'Disable Cache';
            this.disableCacheLabel.className = 'ali-real-price-disable-cache-label';

            this.disableCacheContainer.appendChild(this.disableCacheCheckbox);
            this.disableCacheContainer.appendChild(this.disableCacheLabel);
            this.settingsContent.appendChild(this.disableCacheContainer);

            // Add settings content to settings container
            this.settingsContainer.appendChild(this.settingsContent);
            this.expandableContent.appendChild(this.settingsContainer);

            // Add expandable content to main container
            this.container.appendChild(this.expandableContent);

            document.body.appendChild(this.container);

            // Add hover behavior
            this.container.addEventListener('mouseenter', () => {
                this.container.classList.add('expanded');
            });

            this.container.addEventListener('mouseleave', () => {
                // Only collapse if we're done loading AND the mouse isn't in the container
                if (this.completedItems >= this.totalItems && !this.container.matches(':hover')) {
                    this.container.classList.remove('expanded');
                    // Also collapse settings if expanded
                    this.settingsContainer.classList.remove('expanded');
                    this.disclosureArrow.classList.add('collapsed');
                    this.arrowSymbol.nodeValue = '▶';
                }
            });
        }

        // Add CSS styles
        addStyles() {
            const existingStyle = document.getElementById('ali-real-price-styles');
            if (existingStyle) {
                existingStyle.remove();
            }

            const styleElement = document.createElement('style');
            styleElement.id = 'ali-real-price-styles';
            styleElement.textContent = `
                .ali-real-price-status-container {
                    position: fixed;
                    top: 10px;
                    right: 10px;
                    z-index: 99999;
                    background-color: rgba(0, 0, 0, 0.8);
                    color: white;
                    padding: 8px;
                    border-radius: 4px;
                    box-shadow: 0 2px 5px rgba(0,0,0,0.3);
                    transition: all 0.3s ease;
                    cursor: pointer;
                    display: flex; /* Use flexbox by default */
                    align-items: flex-start; /* Align items to top */
                    gap: 8px; /* Space between icon and content */
                    visibility: hidden; /* Use visibility instead of display: none */
                    opacity: 0;
                }

                .ali-real-price-status-container.visible {
                    visibility: visible;
                    opacity: 1;
                }

                .ali-real-price-icon {
                    font-size: 16px;
                    flex-shrink: 0; /* Prevent icon from shrinking */
                }

                .ali-real-price-expandable-content {
                    display: none;
                    flex-grow: 1; /* Allow content to grow */
                    min-width: 0; /* Allow content to shrink if needed */
                }

                .ali-real-price-status-container.expanded .ali-real-price-expandable-content {
                    display: block;
                }

                .ali-real-price-status {
                    font-size: 12px;
                    margin-right: 10px;
                    display: inline-block;
                }

                .ali-real-price-disclosure-arrow {
                    font-size: 10px;
                    margin-left: 5px;
                    cursor: pointer;
                    color: #666;
                    position: relative;
                }

                .ali-real-price-tooltip {
                    position: absolute;
                    background: rgba(0, 0, 0, 0.8);
                    color: white;
                    padding: 4px 8px;
                    border-radius: 4px;
                    font-size: 11px;
                    white-space: nowrap;
                    pointer-events: none;
                    opacity: 0;
                    transition: opacity 0.15s;
                    top: 100%;
                    margin-top: 4px;
                    right: 0;
                }

                /* Show tooltip on hover when collapsed (default state) */
                .ali-real-price-disclosure-arrow.collapsed:hover .ali-real-price-tooltip {
                    opacity: 1;
                }

                /* Hide tooltip when expanded */
                .ali-real-price-disclosure-arrow:hover .ali-real-price-tooltip {
                    opacity: 0;
                }

                /* Add a small arrow at the bottom of the tooltip */
                .ali-real-price-tooltip:after {
                    content: '';
                    position: absolute;
                    top: -4px;
                    right: 2px;
                    border-width: 0 4px 4px 4px;
                    border-style: solid;
                    border-color: transparent transparent rgba(0, 0, 0, 0.8) transparent;
                }

                .ali-real-price-settings-container {
                    margin-top: 5px;
                }

                .ali-real-price-settings-content {
                    display: none;
                    margin-top: 5px;
                    padding-top: 5px;
                    border-top: 1px solid rgba(255, 255, 255, 0.1);
                }

                .ali-real-price-settings-container.expanded .ali-real-price-settings-content {
                    display: block;
                }

                .ali-real-price-clear-cache {
                    color: #ffc107;
                    font-size: 11px;
                    cursor: pointer;
                    text-decoration: underline;
                    display: block;
                    margin-bottom: 5px;
                }

                .ali-real-price-clear-cache:hover {
                    color: #ffa000;
                }

                .ali-real-price-disable-cache-container {
                    display: flex;
                    align-items: center;
                    margin-top: 5px;
                }

                .ali-real-price-disable-cache-checkbox {
                    margin: 0 5px 0 0;
                    cursor: pointer;
                }

                .ali-real-price-disable-cache-label {
                    font-size: 11px;
                    color: #ccc;
                    cursor: pointer;
                    user-select: none;
                }
            `;
            document.head.appendChild(styleElement);
        }

        startLoading(totalItems) {
            this.totalItems = totalItems;
            this.updateProgress();
            this.container.classList.add('visible');
            this.container.classList.remove('expanded');
        }

        itemComplete() {
            log(`[itemComplete] Before increment: completed=${this.completedItems}, total=${this.totalItems}`);
            this.completedItems++;
            // If completedItems exceeds totalItems, update totalItems
            if (this.completedItems > this.totalItems) {
                this.totalItems = this.completedItems;
            }
            log(`[itemComplete] After increment: completed=${this.completedItems}, total=${this.totalItems}`);
            this.updateProgress();

            if (this.completedItems >= this.totalItems) {
                // When complete, only collapse if mouse isn't in the container
                if (!this.container.matches(':hover')) {
                    this.container.classList.remove('expanded');
                }
            }
        }

        updateProgress() {
            log(`[updateProgress] Updating text: completed=${this.completedItems}, total=${this.totalItems}`);
            this.statusText.textContent = `Loading prices: ${this.completedItems}/${this.totalItems}`;
            // Show expanded state while loading
            if (this.completedItems < this.totalItems) {
                this.container.classList.add('expanded');
            }
        }
    }

    // Global loading manager instance
    const loadingManager = new LoadingManager();

    // Global rate limiter instance
    const rateLimiter = new RateLimiter();

    // Global cache instance
    let globalCache;

    // Function to clear cache and reload
    async function clearCacheAndReload() {
        try {
            if (globalCache) {
                log('Clearing cache...');
                await globalCache.clear();
                alert('AliExpress Real Price cache cleared. Reloading page.');
                window.location.reload();
            } else {
                log('Cache instance not found');
                alert('Cache instance not found.');
            }
        } catch (error) {
            log('Error clearing cache:', error);
            alert('Error clearing cache. See console for details.');
        }
    }

    log('Script starting...');

    // MD5 implementation for sign generation
    function md5(string) {
        function cmn(q, a, b, x, s, t) {
            a = add32(add32(a, q), add32(x, t));
            return add32((a << s) | (a >>> (32 - s)), b);
        }

        function ff(a, b, c, d, x, s, t) {
            return cmn((b & c) | ((~b) & d), a, b, x, s, t);
        }

        function gg(a, b, c, d, x, s, t) {
            return cmn((b & d) | (c & (~d)), a, b, x, s, t);
        }

        function hh(a, b, c, d, x, s, t) {
            return cmn(b ^ c ^ d, a, b, x, s, t);
        }

        function ii(a, b, c, d, x, s, t) {
            return cmn(c ^ (b | (~d)), a, b, x, s, t);
        }

        function md5cycle(x, k) {
            let a = x[0], b = x[1], c = x[2], d = x[3];

            a = ff(a, b, c, d, k[0], 7, -680876936);
            d = ff(d, a, b, c, k[1], 12, -389564586);
            c = ff(c, d, a, b, k[2], 17, 606105819);
            b = ff(b, c, d, a, k[3], 22, -1044525330);
            a = ff(a, b, c, d, k[4], 7, -176418897);
            d = ff(d, a, b, c, k[5], 12, 1200080426);
            c = ff(c, d, a, b, k[6], 17, -1473231341);
            b = ff(b, c, d, a, k[7], 22, -45705983);
            a = ff(a, b, c, d, k[8], 7, 1770035416);
            d = ff(d, a, b, c, k[9], 12, -1958414417);
            c = ff(c, d, a, b, k[10], 17, -42063);
            b = ff(b, c, d, a, k[11], 22, -1990404162);
            a = ff(a, b, c, d, k[12], 7, 1804603682);
            d = ff(d, a, b, c, k[13], 12, -40341101);
            c = ff(c, d, a, b, k[14], 17, -1502002290);
            b = ff(b, c, d, a, k[15], 22, 1236535329);

            a = gg(a, b, c, d, k[1], 5, -165796510);
            d = gg(d, a, b, c, k[6], 9, -1069501632);
            c = gg(c, d, a, b, k[11], 14, 643717713);
            b = gg(b, c, d, a, k[0], 20, -373897302);
            a = gg(a, b, c, d, k[5], 5, -701558691);
            d = gg(d, a, b, c, k[10], 9, 38016083);
            c = gg(c, d, a, b, k[15], 14, -660478335);
            b = gg(b, c, d, a, k[4], 20, -405537848);
            a = gg(a, b, c, d, k[9], 5, 568446438);
            d = gg(d, a, b, c, k[14], 9, -1019803690);
            c = gg(c, d, a, b, k[3], 14, -187363961);
            b = gg(b, c, d, a, k[8], 20, 1163531501);
            a = gg(a, b, c, d, k[13], 5, -1444681467);
            d = gg(d, a, b, c, k[2], 9, -51403784);
            c = gg(c, d, a, b, k[7], 14, 1735328473);
            b = gg(b, c, d, a, k[12], 20, -1926607734);

            a = hh(a, b, c, d, k[5], 4, -378558);
            d = hh(d, a, b, c, k[8], 11, -2022574463);
            c = hh(c, d, a, b, k[11], 16, 1839030562);
            b = hh(b, c, d, a, k[14], 23, -35309556);
            a = hh(a, b, c, d, k[1], 4, -1530992060);
            d = hh(d, a, b, c, k[4], 11, 1272893353);
            c = hh(c, d, a, b, k[7], 16, -155497632);
            b = hh(b, c, d, a, k[10], 23, -1094730640);
            a = hh(a, b, c, d, k[13], 4, 681279174);
            d = hh(d, a, b, c, k[0], 11, -358537222);
            c = hh(c, d, a, b, k[3], 16, -722521979);
            b = hh(b, c, d, a, k[6], 23, 76029189);
            a = hh(a, b, c, d, k[9], 4, -640364487);
            d = hh(d, a, b, c, k[12], 11, -421815835);
            c = hh(c, d, a, b, k[15], 16, 530742520);
            b = hh(b, c, d, a, k[2], 23, -995338651);

            a = ii(a, b, c, d, k[0], 6, -198630844);
            d = ii(d, a, b, c, k[7], 10, 1126891415);
            c = ii(c, d, a, b, k[14], 15, -1416354905);
            b = ii(b, c, d, a, k[5], 21, -57434055);
            a = ii(a, b, c, d, k[12], 6, 1700485571);
            d = ii(d, a, b, c, k[3], 10, -1894986606);
            c = ii(c, d, a, b, k[10], 15, -1051523);
            b = ii(b, c, d, a, k[1], 21, -2054922799);
            a = ii(a, b, c, d, k[8], 6, 1873313359);
            d = ii(d, a, b, c, k[15], 10, -30611744);
            c = ii(c, d, a, b, k[6], 15, -1560198380);
            b = ii(b, c, d, a, k[13], 21, 1309151649);
            a = ii(a, b, c, d, k[4], 6, -145523070);
            d = ii(d, a, b, c, k[11], 10, -1120210379);
            c = ii(c, d, a, b, k[2], 15, 718787259);
            b = ii(b, c, d, a, k[9], 21, -343485551);

            x[0] = add32(a, x[0]);
            x[1] = add32(b, x[1]);
            x[2] = add32(c, x[2]);
            x[3] = add32(d, x[3]);
        }

        function md5blk(s) {
            let i, md5blks = [];
            for (i = 0; i < 64; i += 4) {
                md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
            }
            return md5blks;
        }

        function md5blk_array(a) {
            let i, md5blks = [];
            for (i = 0; i < 64; i += 4) {
                md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
            }
            return md5blks;
        }

        function md51(s) {
            let n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i;
            for (i = 64; i <= s.length; i += 64) {
                md5cycle(state, md5blk(s.substring(i - 64, i)));
            }
            s = s.substring(i - 64);
            let tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
            for (i = 0; i < s.length; i++) {
                tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);
            }
            tail[i >> 2] |= 0x80 << ((i % 4) << 3);
            if (i > 55) {
                md5cycle(state, tail);
                for (i = 0; i < 16; i++) tail[i] = 0;
            }
            tail[14] = n * 8;
            md5cycle(state, tail);
            return state;
        }

        function md51_array(a) {
            let n = a.length, state = [1732584193, -271733879, -1732584194, 271733878], i;
            for (i = 64; i <= a.length; i += 64) {
                md5cycle(state, md5blk_array(a.subarray(i - 64, i)));
            }
            a = (i - 64) < a.length ? a.subarray(i - 64) : new Uint8Array(0);
            let tail = new Uint8Array(64), len = a.length;
            for (i = 0; i < len; i++) {
                tail[i] = a[i];
            }
            tail[len] = 0x80;
            if (len > 55) {
                md5cycle(state, tail.subarray(0, 64));
                for (i = 0; i < 64; i++) tail[i] = 0;
            }
            for (i = 0; i < 8; i++) tail[56 + i] = (n * 8) >>> (i * 8) & 0xff;
            md5cycle(state, tail);
            return state;
        }

        function hex_chr(n) {
            return '0123456789abcdef'.charAt(n);
        }

        function rhex(n) {
            let s = '', j = 0;
            for (; j < 4; j++) {
                s += hex_chr((n >> (j * 8 + 4)) & 0x0F) + hex_chr((n >> (j * 8)) & 0x0F);
            }
            return s;
        }

        function hex(x) {
            for (let i = 0; i < x.length; i++) {
                x[i] = rhex(x[i]);
            }
            return x.join('');
        }

        function add32(a, b) {
            return (a + b) & 0xFFFFFFFF;
        }

        if (typeof string !== 'string') string = '';
        let result;
        if (/[\x80-\xFF]/.test(string)) {
            result = hex(md51(unescape(encodeURIComponent(string))));
        } else {
            result = hex(md51(string));
        }
        return result;
    }

    // CSS Styles
    const STYLES = `
        .ali-real-price-range {
            font-weight: bold;
            color: #333;
        }

        .ali-real-price-global-loading {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            background: #2196F3;
            height: 3px;
            z-index: 10000;
            transition: width 0.3s ease-out;
        }

        .ali-real-price-global-status {
            position: fixed;
            top: 3px;
            right: 10px;
            background: rgba(33, 150, 243, 0.9);
            color: white;
            padding: 8px 12px;
            border-radius: 0 0 4px 4px;
            font-size: 12px;
            z-index: 10000;
            transition: opacity 0.3s ease-out;
        }

        .ali-real-price-median-indicator {
            color: #2196F3;
            margin-left: 4px;
        }

        .ali-real-price-distribution {
            height: 4px;
            background: #eee;
            margin: 2px 0;
            position: relative;
        }

        .ali-real-price-distribution-marker {
            position: absolute;
            width: 2px;
            height: 8px;
            background: #2196F3;
            top: -2px;
        }

        .ali-real-price-popup {
            position: absolute;
            z-index: 1000;
            background: white;
            border-radius: 4px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
            padding: 12px;
            width: 280px;
            font-size: 12px;
            line-height: 1.5;
        }

        .ali-real-price-popup ul {
            list-style: none;
            padding: 0;
            margin: 0 0 10px 0;
        }

        .ali-real-price-popup li {
            padding: 4px 0;
            border-bottom: 1px solid #f5f5f5;
        }

        .ali-real-price-popup li.median-match {
            font-weight: bold;
            color: #2196F3;
        }

        .ali-real-price-popup .free-shipping-threshold {
            font-style: italic;
            color: #4CAF50;
            margin-top: 8px;
        }
    `;

    // Cache configuration
    const CACHE_CONFIG = {
        variants: { duration: 86400000, maxEntries: 100 },  // 24 hours
        shipping: { duration: 86400000, maxEntries: 100 },  // 24 hours
        context: { duration: 86400000, maxEntries: 10 }      // 24 hours
    };

    // DOM Selectors
    const SELECTORS = {
        productCard: [
            '.search-card-item',         // Main search results
            '.lq_b.io_it',              // Alternative class combination
            '.comet-v2-list-item',      // Keep some old selectors as fallback
            '.comet-v2-product-card',
            'div[class*="ProductItem"]',
            'div[class*="product-card"]',
            'div[class*="card-out-wrapper"]'
        ].join(','),
        price: [
            '.lq_j3',                   // Main price container
            '.lq_et',                   // Price wrapper
            '.l5_k6',
            '.U-S0j',
            'div[class*="price-current"]',
            'div[class*="PriceText"]',
            'div[class*="productPrice"]',
            'div[class*="price"]',      // More generic fallbacks
            'span[class*="price"]',
            '[data-price]',             // Data attribute
            '[data-product-price]'
        ].join(','),
        title: [
            '.lq_jl',                   // Product title
            '.lq_ae h3'                 // Title wrapper
        ].join(','),
        shipping: [
            '.lq_lv',                   // Shipping info
            '.mi_l6[title*="shipping"]' // Shipping text
        ].join(','),
        discount: [
            '.lq_eu',                   // Discount percentage
            '.lq_j4'                    // Original price
        ].join(','),
        relatedItems: [
            '.pdp-recommend-item',
            '.recommend-item',
            '.bundle-item',
            'div[class*="RecommendItem"]'
        ].join(','),
        variants: [
            '.sku-property-item',
            '.sku-property-text',
            '.sku-property-image',
            'div[class*="SkuItem"]'
        ].join(',')
    };

    // Utility functions
    const utils = {
        extractProductId(element) {
            // Try multiple methods to find the product ID
            const methods = [
                // Method 1: New URL pattern (from your example)
                () => {
                    const link = element.getAttribute('href');
                    if (!link) return null;
                    const match = link.match(/item\/(\d+)\.html/);
                    return match ? match[1] : null;
                },
                // Method 2: Legacy pattern
                () => {
                    const link = element.querySelector('a[href*="/item/"]');
                    if (!link) return null;
                    const match = link.href.match(/\/(\d+)\.html/);
                    return match ? match[1] : null;
                },
                // Method 3: Data attribute
                () => {
                    return element.getAttribute('data-product-id') || 
                           element.getAttribute('data-item-id') ||
                           element.getAttribute('data-id');
                }
            ];

            // Try each method until we find a product ID
            for (const method of methods) {
                const id = method();
                if (id) {
                    log('Found product ID:', id, { productId: id });
                    return id;
                }
            }

            log('Could not find product ID for element:', element);
            return null;
        },

        formatPrice(value, currency = 'USD') {
            return new Intl.NumberFormat('en-US', {
                style: 'currency',
                currency: currency
            }).format(value);
        },

        delay(ms) {
            return new Promise(resolve => setTimeout(resolve, ms));
        },

        // Get cookie by name
        getCookie(name) {
            const cookies = document.cookie.split(';');
            for (let i = 0; i < cookies.length; i++) {
                const cookie = cookies[i].trim();
                if (cookie.startsWith(name + '=')) {
                    return cookie.substring(name.length + 1);
                }
            }
            return '';
        },

        // Generate sign for API requests
        generateSign(token, timestamp, appKey, data) {
            const signStr = `${token}&${timestamp}&${appKey}&${data}`;
            return md5(signStr);
        }
    };

    // Cache Manager
    class CacheManager {
        constructor() {
            this.cache = new Map();
            // Load immediately, respecting the flag set during init
            this.loadFromStorage();
        }

        async loadFromStorage() {
            if (isCacheDisabled) {
                log('Cache is disabled, skipping load from storage.');
                this.cache.clear();
                return;
            }
            try {
                const storedCache = await GM.getValue('aliexpress_cache', null);
                if (storedCache) {
                    const parsed = JSON.parse(storedCache);
                    // Only load non-expired entries
                    Object.entries(parsed).forEach(([key, entry]) => {
                        if (Date.now() <= entry.expiresAt) {
                            this.cache.set(key, entry);
                        }
                    });
                    log('Loaded cache from storage:', this.cache.size, 'entries');
                }
            } catch (error) {
                log('Error loading cache from storage:', error);
            }
        }

        async saveToStorage() {
            if (isCacheDisabled) {
                // log('Cache is disabled, skipping save to storage.'); // Maybe too noisy
                return; // Don't save if cache is disabled
            }
            try {
                // Convert Map to object for storage
                const cacheObj = {};
                this.cache.forEach((value, key) => {
                    cacheObj[key] = value;
                });
                await GM.setValue('aliexpress_cache', JSON.stringify(cacheObj));
                log('Saved cache to storage:', Object.keys(cacheObj).length, 'entries');
            } catch (error) {
                log('Error saving cache to storage:', error);
            }
        }

        async get(key) {
            if (isCacheDisabled) return null; // Bypass cache if disabled
            const entry = this.cache.get(key);
            if (!entry) return null;

            if (Date.now() > entry.expiresAt) {
                this.cache.delete(key);
                await this.saveToStorage();
                return null;
            }

            return entry.data;
        }

        async set(key, data, config) {
            if (isCacheDisabled) return; // Bypass cache if disabled

            // Check if config is provided, otherwise use a default or skip
            if (!config || !config.maxEntries || !config.duration) {
                log('Cache config missing for key:', key, ' Using default or skipping.');
                // Define a default config or return if you don't want to cache without specific config
                config = CACHE_CONFIG.variants; // Example: Default to variants config
                // Or simply return if caching requires explicit config
                // return;
            }

            if (this.cache.size >= config.maxEntries) {
                const oldestKey = this.cache.keys().next().value;
                this.cache.delete(oldestKey);
            }

            this.cache.set(key, {
                data,
                timestamp: Date.now(),
                expiresAt: Date.now() + config.duration
            });

            await this.saveToStorage();
        }

        async clear() {
            this.cache.clear();
            // Always allow clearing storage, even if cache is currently disabled
            await GM.setValue('aliexpress_cache', '{}');
            log('Cache cleared');
        }
    }

    // Data Manager
    class DataManager {
        constructor() {
            this.cache = new CacheManager();
            this.tokenInitialized = false;
        }

        // Initialize token by making a simple request to AliExpress
        async initializeToken() {
            if (this.tokenInitialized) {
                return;
            }

            log('Initializing token...');
            
            // Check if token already exists
            const token = utils.getCookie('_m_h5_tk');
            if (token) {
                log('Token already exists:', token.split('_')[0]);
                this.tokenInitialized = true;
                return;
            }

            // Make a request to the AliExpress homepage to get the token
            try {
                log('Making request to initialize token...');
                return new Promise((resolve, reject) => {
                    GM.xmlHttpRequest({
                        method: 'GET',
                        url: 'https://www.aliexpress.us/',
                        headers: {
                            'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
                            'accept-language': 'en-US,en;q=0.9',
                            'cache-control': 'no-cache',
                            'pragma': 'no-cache',
                            'sec-ch-ua': '"Chromium";v="134", "Not:A-Brand";v="24", "Google Chrome";v="134"',
                            'sec-ch-ua-mobile': '?0',
                            'sec-ch-ua-platform': '"macOS"',
                            'sec-fetch-dest': 'document',
                            'sec-fetch-mode': 'navigate',
                            'sec-fetch-site': 'none',
                            'sec-fetch-user': '?1',
                            'upgrade-insecure-requests': '1',
                            'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36'
                        },
                        onload: (response) => {
                            // Check if token was set in cookies
                            const newToken = utils.getCookie('_m_h5_tk');
                            if (newToken) {
                                log('Token initialized successfully:', newToken.split('_')[0]);
                                this.tokenInitialized = true;
                                resolve();
                            } else {
                                log('Failed to initialize token');
                                // Continue anyway
                                resolve();
                            }
                        },
                        onerror: (error) => {
                            log('Error initializing token:', error);
                            // Continue anyway
                            resolve();
                        }
                    });
                });
            } catch (error) {
                log('Error in token initialization:', error);
                // Continue anyway
            }
        }

        async fetchProductData(productId) {
            log('Fetching product data for ID:', productId, { productId });
            const cacheKey = `product_${productId}`;
            const cachedData = await this.cache.get(cacheKey);
            if (cachedData) {
                log(`[ARP_EnhanceFlow] [fetchProductData] Found cached data for product: ${productId}. Returning it.`, { productId });
                return cachedData;
            }

            try {
                // First get quick data from card
                const card = document.querySelector(`a[href*="${productId}"]`);
                let productData = null;
                
                if (card) {
                    log('Found product card, extracting basic info');
                    const title = card.querySelector(SELECTORS.title)?.textContent?.trim() || '';
                    const priceContainer = card.querySelector(SELECTORS.price);
                    const priceInfo = this.extractPriceFromElement(priceContainer);
                    const shippingElement = card.querySelector(SELECTORS.shipping);
                    const shippingInfo = this.extractShippingFromElement(shippingElement);
                    const discountElement = card.querySelector(SELECTORS.discount);
                    const discountInfo = this.extractDiscountFromElement(discountElement);

                    productData = {
                        productId,
                        title,
                        variants: [{
                            id: 'default',
                            name: 'Default',
                            price: {
                                value: priceInfo.original || priceInfo.current,
                                formattedPrice: utils.formatPrice(priceInfo.original || priceInfo.current),
                                discountedValue: priceInfo.current,
                                discountedFormattedPrice: utils.formatPrice(priceInfo.current),
                                discount: discountInfo.percentage || ''
                            },
                            shipping: {
                                cost: shippingInfo.cost || 0,
                                formattedPrice: utils.formatPrice(shippingInfo.cost || 0),
                                freeThreshold: shippingInfo.freeThreshold
                            },
                            stock: 999,
                            isMainProduct: true
                        }]
                    };
                }

                // // Try to fetch full product data using the direct Taobao API
                // try {
                //     log('Trying direct Aliexpress API call');
                //     const apiData = await this.fetchDirectAliExpressAPI(productId);
                //     if (apiData) {
                //         log('Successfully fetched data from direct Aliexpress API', { apiData});
                //         await this.cache.set(cacheKey, apiData, CACHE_CONFIG.variants);
                //         return apiData;
                //     }
                // } catch (directApiError) {
                //     log(`Direct Taobao API call failed for productId ${productId}:`, directApiError);
                // }

                // Try to fetch full product data using the API
                try {
                    // Get token from cookies
                    const token = utils.getCookie('_m_h5_tk')?.split('_')[0];
                    if (!token) {
                        log(`No token found in cookies, trying to fetch product page data for productId ${productId}`);
                        const pageData = await this.fetchDataFromProductPage(productId);
                        if (pageData) {
                            await this.cache.set(cacheKey, pageData, CACHE_CONFIG.variants);
                            return pageData;
                        }
                        
                        if (productData) {
                            await this.cache.set(cacheKey, productData, CACHE_CONFIG.variants);
                            return productData;
                        }
                        throw new Error('No token found and no fallback data available');
                    }
                    
                    log('Found token:', token);
                    
                    // Prepare API request
                    const timestamp = Date.now();
                    const appKey = '12574478';
                    const apiVersion = '1.0';
                    
                    // Construct the request data object
                    const requestData = {
                        productId,
                        _lang: 'en_US',
                        _currency: 'USD',
                        country: 'US',
                        province: '922867650000000000',
                        city: '922867656497000000',
                        channel: '',
                        pdp_ext_f: '{"order":"10","eval":"1"}',
                        sourceType: '',
                        clientType: 'pc',
                        ext: JSON.stringify({
                            site: 'usa',
                            crawler: false,
                            'x-m-biz-bx-region': '',
                            signedIn: true,
                            host: 'www.aliexpress.us'
                        })
                    };
                    
                    // Convert request data to JSON string
                    const dataStr = JSON.stringify(requestData);
                    
                    // Generate sign
                    const sign = utils.generateSign(token, timestamp, appKey, dataStr);
                    log('Generated sign:', sign);
                    
                    // Construct the API URL with all parameters
                    const baseUrl = 'https://acs.aliexpress.us/h5/mtop.aliexpress.pdp.pc.query/1.0/';
                    const params = new URLSearchParams({
                        jsv: '2.5.1',
                        appKey,
                        t: timestamp,
                        sign,
                        api: 'mtop.aliexpress.pdp.pc.query',
                        type: 'originaljsonp',
                        v: apiVersion,
                        timeout: '15000',
                        dataType: 'originaljsonp',
                        callback: 'mtopjsonp1',
                        data: dataStr
                    });

                    const apiUrl = `${baseUrl}?${params.toString()}`;
                    log('Fetching from API URL:', apiUrl);

                    return new Promise((resolve, reject) => {
                        GM.xmlHttpRequest({
                            method: 'GET',
                            url: apiUrl,
                            headers: {
                                'accept': '*/*',
                                'accept-language': 'en-US,en;q=0.9',
                                'cache-control': 'no-cache',
                                'pragma': 'no-cache',
                                'referer': 'https://www.aliexpress.us/',
                                'sec-ch-ua': '"Chromium";v="134", "Not:A-Brand";v="24", "Google Chrome";v="134"',
                                'sec-ch-ua-mobile': '?0',
                                'sec-ch-ua-platform': '"macOS"',
                                'sec-fetch-dest': 'script',
                                'sec-fetch-mode': 'no-cors',
                                'sec-fetch-site': 'same-site',
                                'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36'
                            },
                            withCredentials: true, // Important: send cookies with the request
                            onload: (response) => {
                                try {
                                    // log(`Received raw API response: ${response.responseText}`);
                                    
                                    // Extract JSON from JSONP response
                                    const jsonMatch = response.responseText.match(/mtopjsonp1\((.*)\)/);
                                    if (!jsonMatch) {
                                        throw new Error('Invalid JSONP response format');
                                    }

                                    const apiResponseData = JSON.parse(jsonMatch[1]);
                                    log('Parsed API response:', {productId, apiResponseData});

                                    if (apiResponseData.ret && apiResponseData.ret[0]?.startsWith('FAIL_')) {
                                        log('API returned error:', apiResponseData.ret[0]);
                                        if (apiResponseData.ret[0].includes('FAIL_SYS_ILLEGAL_ACCESS')) {
                                            throw new Error(apiResponseData.ret[0]); // This will trigger backoff
                                        }
                                        // Try to fetch product page data as fallback
                                        this.fetchDataFromProductPage(productId).then(pageData => {
                                            if (pageData) {
                                                this.cache.set(cacheKey, pageData, CACHE_CONFIG.variants);
                                                resolve(pageData);
                                                return;
                                            }
                                            
                                            if (productData) {
                                                this.cache.set(cacheKey, productData, CACHE_CONFIG.variants);
                                                resolve(productData);
                                            } else {
                                                reject(new Error(`API Error: ${apiResponseData.ret[0]}`));
                                            }
                                        }).catch(err => {
                                            log('Error fetching product page data:', err);
                                            if (productData) {
                                                this.cache.set(cacheKey, productData, CACHE_CONFIG.variants);
                                                resolve(productData);
                                            } else {
                                                reject(new Error(`API Error: ${apiResponseData.ret[0]}`));
                                            }
                                        });
                                        return;
                                    }

                                    const fullProductData = this.parseProductData(apiResponseData);
                                    
                                    if (productData) {
                                        fullProductData.variants = fullProductData.variants.length > 0 
                                            ? fullProductData.variants 
                                            : productData.variants;
                                        
                                        fullProductData.title = fullProductData.title || productData.title;
                                    }

                                    this.cache.set(cacheKey, fullProductData, CACHE_CONFIG.variants);
                                    resolve(fullProductData);

                                } catch (error) {
                                    log('Error processing API response:', error);
                                    // Try to fetch product page data as fallback
                                    this.fetchDataFromProductPage(productId).then(pageData => {
                                        if (pageData) {
                                            this.cache.set(cacheKey, pageData, CACHE_CONFIG.variants);
                                            resolve(pageData);
                                            return;
                                        }
                                        
                                        if (productData) {
                                            this.cache.set(cacheKey, productData, CACHE_CONFIG.variants);
                                            resolve(productData);
                                        } else {
                                            reject(error);
                                        }
                                    }).catch(err => {
                                        log('Error fetching product page data:', err);
                                        if (productData) {
                                            this.cache.set(cacheKey, productData, CACHE_CONFIG.variants);
                                            resolve(productData);
                                        } else {
                                            reject(error);
                                        }
                                    });
                                }
                            },
                            onerror: (error) => {
                                log('Error fetching API data:', error);
                                // Try to fetch product page data as fallback
                                this.fetchDataFromProductPage(productId).then(pageData => {
                                    if (pageData) {
                                        this.cache.set(cacheKey, pageData, CACHE_CONFIG.variants);
                                        resolve(pageData);
                                        return;
                                    }
                                    
                                    if (productData) {
                                        this.cache.set(cacheKey, productData, CACHE_CONFIG.variants);
                                        resolve(productData);
                                    } else {
                                        reject(error);
                                    }
                                }).catch(err => {
                                    log('Error fetching product page data:', err);
                                    if (productData) {
                                        this.cache.set(cacheKey, productData, CACHE_CONFIG.variants);
                                        resolve(productData);
                                    } else {
                                        reject(error);
                                    }
                                });
                            }
                        });
                    });
                } catch (apiError) {
                    log('API request failed, trying to fetch product page data:', apiError);
                    try {
                        const pageData = await this.fetchDataFromProductPage(productId);
                        if (pageData) {
                            this.cache.set(cacheKey, pageData, CACHE_CONFIG.variants);
                            return pageData;
                        }
                    } catch (pageError) {
                        log('Error fetching product page data:', pageError);
                    }
                    
                    if (productData) {
                        this.cache.set(cacheKey, productData, CACHE_CONFIG.variants);
                        return productData;
                    }
                    throw apiError;
                }
            } catch (error) {
                log('Error in fetchProductData:', error);
                throw error;
            }
        }

        // Direct Taobao API call based on the shared resources
        async fetchDirectAliExpressAPI(productId) {
            log('Making direct Taobao API call for product ID:', productId);
            
            try {
                // Based on the shared resources, we'll use a different approach
                // This is based on the GitHub repo and blog post you shared
                
                // Prepare API request
                const timestamp = Date.now();
                const appKey = '12574478';
                
                // Construct the request data object
                const requestData = {
                    itemId: productId,
                    language: 'en',
                    currency: 'USD',
                    region: 'US',
                    locale: 'en_US',
                    site: 'usa'
                };
                
                // Convert request data to JSON string
                const dataStr = JSON.stringify(requestData);
                
                // Construct the API URL
                const apiUrl = `https://www.aliexpress.us/aer-api/v1/product/detail?productId=${productId}`;
                log('Fetching from direct API URL:', apiUrl);
                
                return new Promise((resolve, reject) => {
                    GM.xmlHttpRequest({
                        method: 'GET',
                        url: apiUrl,
                        headers: {
                            'accept': 'application/json, text/plain, */*',
                            'accept-language': 'en-US,en;q=0.9',
                            'cache-control': 'no-cache',
                            'pragma': 'no-cache',
                            'referer': `https://www.aliexpress.us/item/${productId}.html`,
                            'sec-ch-ua': '"Chromium";v="134", "Not:A-Brand";v="24", "Google Chrome";v="134"',
                            'sec-ch-ua-mobile': '?0',
                            'sec-ch-ua-platform': '"macOS"',
                            'sec-fetch-dest': 'empty',
                            'sec-fetch-mode': 'cors',
                            'sec-fetch-site': 'same-origin',
                            'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36'
                        },
                        withCredentials: true,
                        onload: (response) => {
                            try {
                                log('Received direct API response');
                                
                                // if url is 404.html, we didn't find the product
                                if (response.finalUrl.includes('404.html')) {
                                    log(`product ${productId} not found`);
                                    resolve(null);
                                    return;
                                }

                                

                                // Parse JSON response
                                const data = JSON.parse(response.responseText);
                                log('Parsed direct API response:', data);
                                
                                if (!data.data || data.code !== 200) {
                                    log('Direct API returned error:', data.message || 'Unknown error');
                                    resolve(null);
                                    return;
                                }
                                
                                // Parse the product data
                                const productData = this.parseDirectAPIResponse(data, productId);
                                
                                if (productData) {
                                    log('Successfully parsed direct API response');
                                    resolve(productData);
                                } else {
                                    log('Failed to parse direct API response');
                                    resolve(null);
                                }
                            } catch (error) {
                                log('Error processing direct API response:', error);
                                resolve(null);
                            }
                        },
                        onerror: (error) => {
                            log('Error fetching direct API data:', error);
                            resolve(null);
                        }
                    });
                });
            } catch (error) {
                log('Error in fetchDirectTaobaoAPI:', error);
                return null;
            }
        }

        // Parse the direct API response
        parseDirectAPIResponse(data, productId) {
            try {
                log('Parsing direct API response', { productId });
                
                const productDetail = data.data || {};
                
                // Extract title
                const title = productDetail.productTitle || productDetail.title || '';
                
                // Extract variants
                let variants = [];
                
                // Try to extract variants from skuModule
                const skuModule = productDetail.skuModule || {};
                const skuPriceModule = productDetail.priceModule || {};
                const shippingModule = productDetail.shippingModule || {};
                
                if (skuModule.skuPriceList || skuModule.skuList) {
                    const skuList = skuModule.skuPriceList || skuModule.skuList || [];
                    
                    variants = skuList.map(sku => {
                        const skuId = sku.skuId || sku.id;
                        const skuName = this.extractSkuName(sku, skuModule) || 'Default';
                        const priceInfo = sku.skuVal || sku;
                        
                        // Extract shipping info
                        const shippingInfo = this.extractShippingInfoFromModule(shippingModule, productId);
                        
                        return {
                            id: skuId,
                            name: skuName,
                            price: {
                                value: priceInfo.skuAmount?.value || priceInfo.skuPrice || 0,
                                formattedPrice: utils.formatPrice(priceInfo.skuAmount?.value || priceInfo.skuPrice || 0),
                                discountedValue: priceInfo.skuActivityAmount?.value || priceInfo.actSkuPrice || priceInfo.skuPrice || 0,
                                discountedFormattedPrice: utils.formatPrice(priceInfo.skuActivityAmount?.value || priceInfo.actSkuPrice || priceInfo.skuPrice || 0),
                                discount: priceInfo.discount || ''
                            },
                            shipping: shippingInfo,
                            stock: sku.skuVal?.availQuantity || sku.inventory || 999,
                            isMainProduct: this.isMainProductBySku(sku)
                        };
                    });
                }
                
                // If no variants found, create a default one
                if (variants.length === 0) {
                    const priceInfo = skuPriceModule.formatedActivityPrice || skuPriceModule.formatedPrice || '';
                    const priceValue = parseFloat(priceInfo.replace(/[^\d.]/g, '')) || 0;
                    
                    // Extract shipping info
                    const shippingInfo = this.extractShippingInfoFromModule(shippingModule, productId);
                    
                    variants = [{
                        id: 'default',
                        name: 'Default',
                        price: {
                            value: priceValue,
                            formattedPrice: utils.formatPrice(priceValue),
                            discountedValue: priceValue,
                            discountedFormattedPrice: utils.formatPrice(priceValue),
                            discount: skuPriceModule.discount || ''
                        },
                        shipping: shippingInfo,
                        stock: 999,
                        isMainProduct: true
                    }];
                }
                
                return {
                    productId,
                    title,
                    variants
                };
            } catch (error) {
                log('Error parsing direct API response:', error, { productId });
                return null;
            }
        }

        // Extract SKU name from SKU object
        extractSkuName(sku, skuModule) {
            try {
                // Try to extract name from skuAttr (format: "14:350685#1m")
                if (sku.skuAttr) {
                    const parts = sku.skuAttr.split('#');
                    if (parts.length > 1) {
                        return parts[1];
                    }
                }
                
                // Try to extract name from propPath
                if (sku.propPath) {
                    const propIds = sku.propPath.split(';').map(p => p.split(':')[1]);
                    
                    // Find property values
                    const propNames = [];
                    const props = skuModule.props || [];
                    
                    for (const prop of props) {
                        const values = prop.values || [];
                        for (const value of values) {
                            if (propIds.includes(value.id)) {
                                propNames.push(value.name);
                            }
                        }
                    }
                    
                    if (propNames.length > 0) {
                        return propNames.join(' ');
                    }
                }
                
                return 'Default';
            } catch (error) {
                log('Error extracting SKU name:', error);
                return 'Default';
            }
        }

        // Extract shipping info from shipping module
        extractShippingInfoFromModule(shippingModule, productId) {
            try {
                log('Raw shipping module data:', shippingModule, { productId });
                const defaultShipping = {
                    cost: 0,
                    formattedPrice: '$0.00',
                    freeThreshold: null
                };
                
                if (!shippingModule) {
                    return defaultShipping;
                }
                
                // Find shipping cost
                const shippingOptions = shippingModule.freightCalculateInfo?.freight || [];
                if (shippingOptions.length === 0) {
                    return defaultShipping;
                }
                
                // Get the cheapest shipping option
                const cheapestOption = shippingOptions.reduce((min, option) => {
                    const cost = option.freightAmount?.value || 0;
                    return cost < min.cost ? { cost, option } : min;
                }, { cost: Infinity, option: null });
                
                if (cheapestOption.option) {
                    const cost = cheapestOption.cost;
                    
                    // Check for free shipping threshold
                    let freeThreshold = null;
                    if (shippingModule.freightCalculateInfo?.freeShippingText) {
                        const thresholdMatch = shippingModule.freightCalculateInfo.freeShippingText.match(/\$(\d+(\.\d{2})?)/);
                        if (thresholdMatch) {
                            freeThreshold = parseFloat(thresholdMatch[1]);
                        }
                    }
                    
                    return {
                        cost,
                        formattedPrice: utils.formatPrice(cost),
                        freeThreshold
                    };
                }
                
                return defaultShipping;
            } catch (error) {
                log('Error extracting shipping info:', error);
                return {
                    cost: 0,
                    formattedPrice: '$0.00',
                    freeThreshold: null
                };
            }
        }

        extractPriceFromElement(element) {
            if (!element) return { current: 0, original: 0 };

            try {
                // Extract current price
                const currentPriceText = element.textContent.match(/\$[\d,.]+/)?.[0] || '0';
                const currentPrice = parseFloat(currentPriceText.replace(/[$,]/g, ''));

                // Extract original price if available (crossed out price)
                const originalPriceElement = element.querySelector('.lq_j4');
                const originalPriceText = originalPriceElement?.textContent.match(/\$[\d,.]+/)?.[0] || currentPriceText;
                const originalPrice = parseFloat(originalPriceText.replace(/[$,]/g, ''));

                return {
                    current: currentPrice,
                    original: originalPrice
                };
            } catch (error) {
                log('Error extracting price:', error);
                return { current: 0, original: 0 };
            }
        }

        extractShippingFromElement(element) {
            if (!element) return { cost: 0, freeThreshold: null };

            try {
                const text = element.textContent;
                const freeThresholdMatch = text.match(/Free shipping over \$(\d+(\.\d{2})?)/i);
                const shippingCostMatch = text.match(/Shipping: \$(\d+(\.\d{2})?)/i);

                return {
                    cost: shippingCostMatch ? parseFloat(shippingCostMatch[1]) : 0,
                    freeThreshold: freeThresholdMatch ? parseFloat(freeThresholdMatch[1]) : null
                };
            } catch (error) {
                log('Error extracting shipping:', error);
                return { cost: 0, freeThreshold: null };
            }
        }

        extractDiscountFromElement(element) {
            if (!element) return { percentage: '' };

            try {
                const text = element.textContent;
                const percentageMatch = text.match(/-(\d+)%/);

                return {
                    percentage: percentageMatch ? `-${percentageMatch[1]}%` : ''
                };
            } catch (error) {
                log('Error extracting discount:', error);
                return { percentage: '' };
            }
        }

        createSingleVariant(result, productId) {
            // Extract price from the page data
            const priceInfo = result.priceComponent || result.price || {};
            // Extract shipping from the new path
            const shippingData = result.SHIPPING || {};
            const deliveryLayout = shippingData.deliveryLayoutInfo?.[0] || {};
            const shippingBizData = deliveryLayout.bizData || {};
            
            // Get the price values
            const originalPrice = this.extractDefaultPrice(result);
            const discountedPrice = priceInfo.activityPrice || priceInfo.discountPrice || originalPrice;
            
            // Extract base shipping info
            const baseShippingInfo = this.extractShippingInfo(shippingBizData, productId);

            return [{ // Return as an array containing the single variant object
                id: 'default',
                name: 'Default',
                price: {
                    value: originalPrice,
                    formattedPrice: utils.formatPrice(originalPrice),
                    discountedValue: discountedPrice,
                    discountedFormattedPrice: utils.formatPrice(discountedPrice),
                    discount: priceInfo.discount || ''
                },
                shipping: baseShippingInfo, // Use the extracted base info
                stock: 999,
                isMainProduct: true
            }];
        }

        parseProductData(data) {
            log('Parsing data:', data);
            const productId = data.data?.result?.productId || ''; // Extract productId for logging

            // Handle different API response structures
            const result = data.data?.result || data.data || {};
            log('Result object:', result, { productId });

            // Handle error responses
            if (data.ret && data.ret[0]?.startsWith('FAIL_')) {
                log('API returned error:', data.ret[0], { productId });
                return {
                    productId: productId,
                    title: result.title || '',
                    variants: [this.createDefaultVariant(result)]
                };
            }

            // Extract basic product info
            const productInfo = {
                productId: productId,
                title: result.title || '',
            };

            // Extract variants
            let variants = [];
            
            try {
                // Get SKU and price data from the correct paths
                const skuPaths = result.SKU?.skuPaths || [];
                const priceMap = result.PRICE?.skuIdStrPriceInfoMap || {};
                // Extract shipping info from the new path
                const shippingData = result.SHIPPING || {};
                const deliveryLayout = shippingData.deliveryLayoutInfo?.[0] || {};
                const shippingBizData = deliveryLayout.bizData || {};
                const deliveryGuarantee = shippingData.DELIVERY_GUARANTEE_SERVICE || {};
                // Note: Free shipping text info might be nested differently, adjust if needed
                const freeShippingTextInfo = {}; // Placeholder

                if (skuPaths.length > 0) {
                    variants = skuPaths.map(sku => {
                        const skuId = sku.skuIdStr || sku.skuId;
                        const priceInfo = priceMap[skuId] || {};
                        
                        // Base variant data without shipping
                        return {
                            id: skuId,
                            name: this.getSkuName(sku),
                            price: {
                                value: priceInfo.originalPrice?.value || 0,
                                formattedPrice: priceInfo.originalPrice?.formatedAmount || '$0.00',
                                discountedValue: this.extractPriceValue(priceInfo.salePriceString) || priceInfo.originalPrice?.value || 0,
                                discountedFormattedPrice: priceInfo.salePriceString || priceInfo.originalPrice?.formatedAmount || '$0.00',
                                discount: priceInfo.discount || ''
                            },
                            stock: sku.skuStock || sku.availQuantity || 999,
                            isMainProduct: this.isMainProductBySku(sku)
                        };
                    });
                } else {
                    // Single variant case
                    // Pass productId to createSingleVariant
                    variants = [this.createSingleVariant(result, productId)];
                }

                // Extract base shipping info ONCE
                const baseShippingInfo = this.extractShippingInfo(shippingBizData, productId);

                // Add shipping info (cost, guarantee, etc.) to all variants
                variants = this.addShippingInfo(variants, baseShippingInfo, deliveryGuarantee, freeShippingTextInfo, productId);

            } catch (error) {
                log('Error parsing variants:', error, { productId });
                variants = [this.createDefaultVariant(result)];
            }

            return {
                ...productInfo,
                variants: variants.length > 0 ? variants : [this.createDefaultVariant(result, productId)]
            };
        }

        getSkuName(sku) {
            // Extract name from skuAttr (format: "14:350685#1m")
            const skuAttr = sku.skuAttr || '';
            const parts = skuAttr.split('#');
            return parts[1] || 'Default';
        }

        isMainProductBySku(sku) {
            const name = (sku.skuAttr || '').toLowerCase();
            return !this.isAccessory(name);
        }

        extractPriceValue(priceString) {
            if (!priceString) return 0;
            const match = priceString.match(/[\d,.]+/);
            return match ? parseFloat(match[0].replace(/,/g, '')) : 0;
        }

        createDefaultVariant(result, productId) {
            // Create a default variant when no variant info is available
            const defaultPrice = this.extractDefaultPrice(result);
            return {
                id: 'default',
                name: 'Default',
                price: {
                    value: defaultPrice,
                    formattedPrice: utils.formatPrice(defaultPrice),
                    discountedValue: defaultPrice,
                    discountedFormattedPrice: utils.formatPrice(defaultPrice),
                    discount: ''
                },
                shipping: {
                    cost: 0,
                    formattedPrice: '$0.00',
                    freeThreshold: null
                },
                stock: 999,
                isMainProduct: true
            };
        }

        extractDefaultPrice(result) {
            // Try various paths to find the price
            const productId = result?.productId || ''; // Get productId if available
            const paths = [
                result.priceComponent?.originalPrice,
                result.price?.originalPrice?.value,
                result.price?.minPrice,
                result.PRICE?.originalPrice?.value,
                result.PRICE?.minPrice
            ];

            for (const price of paths) {
                if (typeof price === 'number' && !isNaN(price)) {
                    return price;
                }
            }

            log('Could not extract default price from result object', { productId, result });
            return 0;
        }

        extractShippingInfo(shippingBizData, productId) {
            log('Raw shippingBizData object:', shippingBizData, { productId }); // Log the full object
            const hasChoiceFreeShipping = shippingBizData?.choiceFreeShipping === 'yes';
            log(`[extractShippingInfo] choiceFreeShipping status for ${productId}:`, hasChoiceFreeShipping);
            return {
                cost: shippingBizData?.displayAmount || 0,
                // Use formattedAmount if available, otherwise format the cost
                formattedPrice: shippingBizData?.formattedAmount || utils.formatPrice(shippingBizData?.displayAmount || 0),
                // Free threshold logic might need revisiting based on bizData structure - removed for now
                freeThreshold: null, // Keep null for now, threshold *value* extraction needs review
                hasChoiceFreeShipping: hasChoiceFreeShipping // Add the boolean status
            };
        }

        extractFreeShippingThreshold(shipping) {
            // This function needs to be re-evaluated based on the new API structure.
            // It's currently not used because extractShippingInfo sets freeThreshold to null.
            log('extractFreeShippingThreshold called, but logic needs review based on SHIPPING.deliveryLayoutInfo structure', { shipping });
            return null;
        }

        addShippingInfo(variants, baseShippingInfo, deliveryGuarantee, freeShippingTextInfo, productId) {
            // baseShippingInfo is the object returned by extractShippingInfo
            // deliveryGuarantee is the result.DELIVERY_GUARANTEE_SERVICE object
            // freeShippingTextInfo is the (potentially empty) free shipping text component

            return variants.map(variant => ({
                ...variant,
                shipping: {
                    ...baseShippingInfo, // Contains cost, formattedPrice, freeThreshold (currently null)
                    guaranteedDays: deliveryGuarantee?.subContents?.[3]?.content?.match(/\d+/)?.[0] || null,
                    freeShippingText: freeShippingTextInfo?.mainText || null
                    // TODO: Re-evaluate freeThreshold extraction if needed
                }
            }));
        }

        isAccessory(name) {
            const accessoryKeywords = [
                'case', 'cover', 'protector', 'cable', 'adapter', 'charger',
                'holder', 'stand', 'accessory', 'kit', 'pedal', 'spare',
                'replacement', 'tool', 'bag', 'box'
            ];
            return accessoryKeywords.some(keyword => name.includes(keyword));
        }

        // Fetch product data directly from the product page HTML
        async fetchDataFromProductPage(productId) {
            log('Fetching product page data for ID:', productId);
            // Add log to indicate fallback
            log(`Falling back to fetching data directly from product page HTML for productId: ${productId}`, { productId });

            try {
                const productUrl = `https://www.aliexpress.us/item/${productId}.html`;
                log('Fetching product page:', productUrl);
                
                return new Promise((resolve, reject) => {
                    GM.xmlHttpRequest({
                        method: 'GET',
                        url: productUrl,
                        headers: {
                            'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
                            'accept-language': 'en-US,en;q=0.9',
                            'cache-control': 'no-cache',
                            'pragma': 'no-cache',
                            'sec-ch-ua': '"Chromium";v="134", "Not:A-Brand";v="24", "Google Chrome";v="134"',
                            'sec-ch-ua-mobile': '?0',
                            'sec-ch-ua-platform': '"macOS"',
                            'sec-fetch-dest': 'document',
                            'sec-fetch-mode': 'navigate',
                            'sec-fetch-site': 'none',
                            'sec-fetch-user': '?1',
                            'upgrade-insecure-requests': '1',
                            'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36'
                        },
                        onload: (response) => {
                            try {
                                log('Received product page response');
                                
                                // Extract product data from HTML
                                const productData = this.extractProductDataFromHTML(response.responseText, productId);
                                
                                if (productData) {
                                    log('Successfully extracted product data from HTML');
                                    resolve(productData);
                                } else {
                                    log('Failed to extract product data from HTML');
                                    resolve(null);
                                }
                            } catch (error) {
                                log('Error processing product page response:', error);
                                resolve(null);
                            }
                        },
                        onerror: (error) => {
                            log('Error fetching product page:', error);
                            resolve(null);
                        }
                    });
                });
            } catch (error) {
                log('Error in fetchProductPageData:', error);
                return null;
            }
        }

        // Extract product data from HTML
        extractProductDataFromHTML(html, productId) {
            try {
                log('Extracting product data from HTML');
                
                // Create a temporary DOM element to parse the HTML
                const parser = new DOMParser();
                const doc = parser.parseFromString(html, 'text/html');
                
                // Look for the product data in the page
                const scriptElements = Array.from(doc.querySelectorAll('script'));
                
                // Find the script that contains the product data
                let productData = null;
                
                // Method 1: Look for runParams.data
                for (const script of scriptElements) {
                    const content = script.textContent;
                    if (content.includes('runParams.data')) {
                        const match = content.match(/runParams\.data\s*=\s*({.*?});/s);
                        if (match && match[1]) {
                            try {
                                productData = JSON.parse(match[1]);
                                log('Found product data in runParams.data');
                                break;
                            } catch (e) {
                                log('Error parsing runParams.data:', e);
                            }
                        }
                    }
                }
                
                // Method 2: Look for window.__INITIAL_STATE__
                if (!productData) {
                    for (const script of scriptElements) {
                        const content = script.textContent;
                        if (content.includes('window.__INITIAL_STATE__')) {
                            const match = content.match(/window\.__INITIAL_STATE__\s*=\s*({.*?});/s);
                            if (match && match[1]) {
                                try {
                                    const state = JSON.parse(match[1]);
                                    productData = state.productDetail?.data;
                                    log('Found product data in window.__INITIAL_STATE__');
                                    break;
                                } catch (e) {
                                    log('Error parsing window.__INITIAL_STATE__:', e);
                                }
                            }
                        }
                    }
                }
                
                // Method 3: Look for data-pdp-json
                if (!productData) {
                    const jsonElement = doc.querySelector('[data-pdp-json]');
                    if (jsonElement) {
                        try {
                            productData = JSON.parse(jsonElement.getAttribute('data-pdp-json'));
                            log('Found product data in data-pdp-json attribute');
                        } catch (e) {
                            log('Error parsing data-pdp-json:', e);
                        }
                    }
                }
                
                // Method 4: Look for window.runParams
                if (!productData) {
                    for (const script of scriptElements) {
                        const content = script.textContent;
                        if (content.includes('window.runParams')) {
                            const match = content.match(/window\.runParams\s*=\s*({.*?});/s);
                            if (match && match[1]) {
                                try {
                                    const runParams = JSON.parse(match[1]);
                                    productData = runParams.data;
                                    log('Found product data in window.runParams');
                                    break;
                                } catch (e) {
                                    log('Error parsing window.runParams:', e);
                                }
                            }
                        }
                    }
                }
                
                if (!productData) {
                    log('Could not find product data in HTML');
                    return null;
                }
                
                // Extract title
                const title = productData.title || productData.subject || 
                              doc.querySelector('h1')?.textContent?.trim() || '';
                
                // Extract variants
                let variants = [];
                
                // Try to extract variants from skuModule
                const skuModule = productData.skuModule || productData.skuInfo || {};
                const skuPriceModule = productData.priceModule || productData.priceInfo || {};
                
                if (skuModule.skuPriceList || skuModule.skuList) {
                    const skuList = skuModule.skuPriceList || skuModule.skuList || [];
                    
                    variants = skuList.map(sku => {
                        const skuId = sku.skuId || sku.id;
                        const skuName = sku.skuAttr?.split('#')[1] || 'Default';
                        const priceInfo = sku.skuVal || sku;
                        
                        return {
                            id: skuId,
                            name: skuName,
                            price: {
                                value: priceInfo.skuAmount?.value || priceInfo.skuPrice || 0,
                                formattedPrice: utils.formatPrice(priceInfo.skuAmount?.value || priceInfo.skuPrice || 0),
                                discountedValue: priceInfo.skuActivityAmount?.value || priceInfo.actSkuPrice || priceInfo.skuPrice || 0,
                                discountedFormattedPrice: utils.formatPrice(priceInfo.skuActivityAmount?.value || priceInfo.actSkuPrice || priceInfo.skuPrice || 0),
                                discount: priceInfo.discount || ''
                            },
                            shipping: {
                                cost: 0, // We don't have shipping info from HTML
                                formattedPrice: '$0.00',
                                freeThreshold: null
                            },
                            stock: sku.skuVal?.availQuantity || sku.inventory || 999,
                            isMainProduct: true
                        };
                    });
                }
                
                // If no variants found, create a default one
                if (variants.length === 0) {
                    const priceInfo = skuPriceModule.formatedActivityPrice || skuPriceModule.formatedPrice || '';
                    const priceValue = parseFloat(priceInfo.replace(/[^\d.]/g, '')) || 0;
                    
                    variants = [{
                        id: 'default',
                        name: 'Default',
                        price: {
                            value: priceValue,
                            formattedPrice: utils.formatPrice(priceValue),
                            discountedValue: priceValue,
                            discountedFormattedPrice: utils.formatPrice(priceValue),
                            discount: skuPriceModule.discount || ''
                        },
                        shipping: {
                            cost: 0,
                            formattedPrice: '$0.00',
                            freeThreshold: null
                        },
                        stock: 999,
                        isMainProduct: true
                    }];
                }
                
                return {
                    productId,
                    title,
                    variants
                };
            } catch (error) {
                log('Error extracting product data from HTML:', error);
                return null;
            }
        }
    }

    // Price Context Calculator
    class PriceContextCalculator {
        calculatePageContext(productCards) {
            const prices = [];
            for (const card of productCards) {
                const priceElement = card.querySelector(SELECTORS.price);
                if (priceElement) {
                    const price = this.extractPriceValue(priceElement.textContent);
                    if (price) prices.push(price);
                }
            }

            if (prices.length === 0) return null;

            prices.sort((a, b) => a - b);
            const median = this.calculateMedian(prices);
            const threshold = median * 0.3;

            return {
                median,
                lowerBound: median - threshold,
                upperBound: median + threshold,
                distribution: this.calculateDistribution(prices)
            };
        }

        calculateMedian(prices) {
            const mid = Math.floor(prices.length / 2);
            return prices.length % 2 === 0
                ? (prices[mid - 1] + prices[mid]) / 2
                : prices[mid];
        }

        calculateDistribution(prices) {
            return {
                min: Math.min(...prices),
                max: Math.max(...prices),
                clusters: this.findPriceClusters(prices)
            };
        }

        findPriceClusters(prices) {
            // Simple clustering based on price ranges
            const range = prices[prices.length - 1] - prices[0];
            const step = range / 5;
            const clusters = [];

            for (let i = 0; i < 5; i++) {
                const min = prices[0] + (step * i);
                const max = prices[0] + (step * (i + 1));
                const clusterPrices = prices.filter(p => p >= min && p < max);

                if (clusterPrices.length > 0) {
                    clusters.push({
                        centerPrice: (min + max) / 2,
                        count: clusterPrices.length,
                        variance: this.calculateVariance(clusterPrices)
                    });
                }
            }

            return clusters;
        }

        calculateVariance(prices) {
            const mean = prices.reduce((a, b) => a + b) / prices.length;
            return Math.sqrt(
                prices.reduce((sq, n) => sq + Math.pow(n - mean, 2), 0) / prices.length
            );
        }

        findBestMatchingVariant(variants, context) {
            if (!context || variants.length === 0) return variants[0];

            return variants
                .map(variant => ({
                    ...variant,
                    score: this.calculateVariantScore(variant, context)
                }))
                .sort((a, b) => b.score - a.score)[0];
        }

        calculateVariantScore(variant, context) {
            const { median, lowerBound, upperBound } = context;
            const price = variant.price.discountedValue;

            const distanceScore = 1 / (Math.abs(price - median) + 1);
            const inRange = price >= lowerBound && price <= upperBound ? 1.5 : 0.5;
            const productTypeMultiplier = variant.isMainProduct ? 1.3 : 0.7;

            return distanceScore * inRange * productTypeMultiplier;
        }

        extractPriceValue(text) {
            const match = text.match(/[\d,.]+/);
            return match ? parseFloat(match[0].replace(/,/g, '')) : 0;
        }
    }

    // DOM Enhancement Manager
    class DOMEnhancer {
        constructor(dataManager, priceContextCalculator) {
            this.dataManager = dataManager;
            this.priceContextCalculator = priceContextCalculator;
            this.setupIntersectionObserver();
            this.pendingEnhancements = new Set();
            this.processedCards = new WeakSet(); // Track processed cards
        }

        setupIntersectionObserver() {
            this.observer = new IntersectionObserver(
                (entries) => {
                    entries.forEach(entry => {
                        if (entry.isIntersecting) {
                            const productCard = entry.target;
                            const productId = utils.extractProductId(productCard);
                            if (productId) {
                                this.pendingEnhancements.add(productId);
                                this.enhanceProductCard(productCard, productId);
                                this.observer.unobserve(productCard);
                            }
                        }
                    });
                },
                { rootMargin: '200px' }
            );
        }

        async enhanceProductCard(card, productId) {
            // Check if we've already processed this card
            log(`[ARP_EnhanceFlow] [enhanceProductCard START] Processing card ${productId}`, { productId });
            if (this.processedCards.has(card)) {
                log('Card already processed:', productId, { productId });
                this.pendingEnhancements.delete(productId);
                loadingManager.itemComplete();
                return;
            }

            log('Enhancing product card:', productId, { productId });
            let priceElement = null;

            try {
                // Try multiple strategies to find the price element
                const priceSelectors = SELECTORS.price.split(',');
                
                // Log all potential price elements for debugging
                log('Searching for price element with selectors:', priceSelectors, { productId });
                
                for (const selector of priceSelectors) {
                    const elements = card.querySelectorAll(selector.trim());
                    if (elements.length > 0) {
                        // Take the most specific (deepest) price element
                        priceElement = Array.from(elements).reduce((best, current) => {
                            const bestDepth = this.getElementDepth(best);
                            const currentDepth = this.getElementDepth(current);
                            return currentDepth > bestDepth ? current : best;
                        });
                        log('Found price element using selector:', selector, {
                            productId,
                            elementHtml: priceElement.outerHTML,
                            elementClass: priceElement.className
                        });
                        break;
                    }
                }

                if (!priceElement) {
                    // If still not found, try searching deeper in the card
                    log('No price element found with selectors, trying text pattern search', { productId });
                    const allElements = card.getElementsByTagName('*');
                    for (const element of allElements) {
                        const text = element.textContent;
                        // Look for price-like patterns (e.g., $XX.XX)
                        if (/\$\d+(\.\d{2})?/.test(text) && !element.querySelector('*')) {
                            priceElement = element;
                            log('Found price element using text pattern:', {
                                productId,
                                text,
                                elementHtml: element.outerHTML,
                                elementClass: element.className
                            });
                            break;
                        }
                    }
                }

                if (!priceElement) {
                    log('No price element found for product:', productId, {
                        productId,
                        cardHtml: card.outerHTML
                    });
                    this.pendingEnhancements.delete(productId);
                    loadingManager.itemComplete();
                    return;
                }

                // Verify the element is still in the DOM
                if (!document.contains(priceElement)) {
                    log('Price element is no longer in the DOM:', {
                        productId,
                        elementHtml: priceElement.outerHTML
                    });
                    this.pendingEnhancements.delete(productId);
                    loadingManager.itemComplete();
                    return;
                }

                // Mark the card as being processed
                this.processedCards.add(card);

                // Fetch data with rate limiting
                const productData = await rateLimiter.executeWithBackoff(async () => {
                    return await this.dataManager.fetchProductData(productId);
                });
                log(`[ARP_EnhanceFlow] [enhanceProductCard] Got productData (cached or fetched) for ${productId}`, { productId });
                
                // Verify element is still valid after async operation
                if (!document.contains(priceElement)) {
                    log('Price element was removed during async operation', { productId });
                    this.pendingEnhancements.delete(productId);
                    loadingManager.itemComplete();
                    return;
                }

                log('Received product data for enhancement:', productData, { productId });

                const context = this.priceContextCalculator.calculatePageContext(
                    Array.from(document.querySelectorAll(SELECTORS.productCard))
                );

                const bestVariant = this.priceContextCalculator.findBestMatchingVariant(
                    productData.variants,
                    context
                );

                this.updatePriceDisplay(priceElement, bestVariant, productData, context, productId);

            } catch (error) {
                log('Error enhancing product card:', productId, error, { productId });
                if (priceElement && document.contains(priceElement)) {
                    try {
                        // Add error class instead of replacing completely
                        priceElement.classList.add('ali-real-price-error'); 
                        priceElement.textContent = 'Price data unavailable';
                    } catch (displayError) {
                        log('Error showing error state:', displayError, { productId });
                    }
                }
            } finally {
                // *** This SHOULD always run ***
                log(`[ARP_EnhanceFlow] [enhanceProductCard finally] Reached finally block for ${productId}`, { productId });
                this.pendingEnhancements.delete(productId);
                loadingManager.itemComplete(); // This is the call that updates the counter
            }
        }

        updatePriceDisplay(element, bestVariant, productData, context, productId) {
            if (!element) {
                log('Cannot update price display - element is null');
                return;
            }

            if (!element.parentNode) {
                log('Cannot update price display - element has no parent', {
                    elementHtml: element.outerHTML,
                    elementClass: element.className,
                    elementId: element.id
                });
                return;
            }

            // Get total price range (includes shipping)
            const priceRange = this.getPriceRange(productData.variants, productId);
            const displayOptions = {
                showShipping: true, // Keep flag for potential future use, but won't add text now
                showMedianIndicator: true,
                showPriceRange: true,
                showDistributionGraph: true
            };

            // Start with the total price of the best matching variant
            const bestVariantTotal = (bestVariant.price?.discountedValue || 0) + (bestVariant.shipping?.cost || 0);
            let displayText = utils.formatPrice(bestVariantTotal);

            if (displayOptions.showPriceRange && priceRange.min !== priceRange.max) {
                // Display the total price range
                displayText = `${utils.formatPrice(priceRange.min)} - ${utils.formatPrice(priceRange.max)}`;
            }

            // Add note about shipping being included only if:
            // 1. The base shipping cost is > 0
            // 2. There is NO "Choice Free Shipping" option available
            if (bestVariant.shipping?.cost > 0 && !bestVariant.shipping?.hasChoiceFreeShipping) {
                log(`Adding '(including shipping)' for ${productId} because cost is ${bestVariant.shipping?.cost} and hasChoiceFreeShipping is ${bestVariant.shipping?.hasChoiceFreeShipping}`);
                displayText += ' (including shipping)';
            } else {
                log(`NOT adding '(including shipping)' for ${productId} because cost is ${bestVariant.shipping?.cost} and hasChoiceFreeShipping is ${bestVariant.shipping?.hasChoiceFreeShipping}`);
            }

            if (displayOptions.showMedianIndicator) {
                displayText += ' ⊙';
            }

            // Instead of replacing the element, try to modify it in place first
            try {
                element.className = 'ali-real-price-range ' + element.className;
                element.innerHTML = displayText;

                // Add hover events for variant popup
                const card = element.closest(SELECTORS.productCard);
                if (card) {
                    let popupTimeout;
                    element.addEventListener('mouseenter', () => {
                        log('mouseenter', {productId});
                        popupTimeout = setTimeout(() => {
                            this.showVariantPopup(card, productData.variants, bestVariant, context, productId);
                        }, 200); // Small delay to prevent flicker
                    });
                    log('mouseenter event listener added', {productId});

                    element.addEventListener('mouseleave', () => {
                        clearTimeout(popupTimeout);
                        setTimeout(() => {
                            this.hideVariantPopup(card, productId);
                        }, 200); // Small delay to allow moving mouse to popup
                    });
                } else {
                    log('no card found for when establishing hover events', {productId});
                }

                if (displayOptions.showDistributionGraph) {
                    this.addPriceDistributionGraph(element, bestVariant, priceRange, productId);
                }
                return;
            } catch (modifyError) {
                log('Failed to modify element in place:', modifyError);
            }

            // If modifying in place fails, try replacement
            try {
                const container = document.createElement('div');
                container.className = 'ali-real-price-range';
                container.innerHTML = displayText;

                // Add hover events for variant popup
                const card = element.closest(SELECTORS.productCard);
                if (card) {
                    let popupTimeout;
                    container.addEventListener('mouseenter', () => {
                        log('mouseenter (container)', {productId});
                        popupTimeout = setTimeout(() => {
                            this.showVariantPopup(card, productData.variants, bestVariant, context, productId);
                        }, 200); // Small delay to prevent flicker
                    });

                    container.addEventListener('mouseleave', () => {
                        clearTimeout(popupTimeout);
                        setTimeout(() => {
                            this.hideVariantPopup(card, productId);
                        }, 200); // Small delay to allow moving mouse to popup
                    });
                }

                if (displayOptions.showDistributionGraph) {
                    this.addPriceDistributionGraph(container, bestVariant, priceRange, productId);
                }

                element.parentNode.replaceChild(container, element);
            } catch (error) {
                log('Error replacing price element:', error, {
                    elementHtml: element.outerHTML,
                    parentHtml: element.parentNode?.outerHTML
                });
            }
        }

        showVariantPopup(card, variants, bestVariant, context, productId) {
            log('Showing variant popup', { productId });
            // Remove any existing popup first
            this.hideVariantPopup(card, productId, false); // Don't log removal here

            const popup = document.createElement('div');
            popup.className = 'ali-real-price-popup';

            const variantList = document.createElement('ul');

            const sortedVariants = [...variants].sort((a, b) => {
                const totalA = a.price.discountedValue + a.shipping.cost;
                const totalB = b.price.discountedValue + b.shipping.cost;
                return totalA - totalB;
            });

            for (const variant of sortedVariants) {
                const variantItem = document.createElement('li');
                const isMedianMatch = variant.id === bestVariant.id;

                variantItem.innerHTML = `
                    ${isMedianMatch ? '⊙ ' : '• '}
                    ${variant.name} ${variant.price.discountedFormattedPrice}
                    ${variant.shipping.cost > 0 ? `+ ${variant.shipping.formattedPrice} shipping` : ''}
                    = ${utils.formatPrice(variant.price.discountedValue + variant.shipping.cost)} total
                `;

                if (isMedianMatch) {
                    variantItem.classList.add('median-match');
                }

                variantList.appendChild(variantItem);
            }

            popup.appendChild(variantList);

            const freeShippingThreshold = this.getFreeShippingThreshold(variants, productId);
            if (freeShippingThreshold) {
                const thresholdInfo = document.createElement('div');
                thresholdInfo.className = 'free-shipping-threshold';
                thresholdInfo.textContent = `Free shipping over ${utils.formatPrice(freeShippingThreshold)}`;
                popup.appendChild(thresholdInfo);
            }

            this.positionPopup(popup, card);
            card.appendChild(popup);
        }

        hideVariantPopup(card, productId, shouldLog = true) {
            const popup = card.querySelector('.ali-real-price-popup');
            if (popup) {
                if (shouldLog) log('Hiding variant popup', { productId });
                popup.remove();
            }
        }

        positionPopup(popup, card) {
            const cardRect = card.getBoundingClientRect();
            popup.style.left = '100%';
            popup.style.top = '0';

            // Reposition if popup would go off screen
            requestAnimationFrame(() => {
                const popupRect = popup.getBoundingClientRect();
                if (popupRect.right > window.innerWidth) {
                    popup.style.left = 'auto';
                    popup.style.right = '100%';
                }
            });
        }

        getPriceRange(variants, productId) {
            if (!variants || variants.length === 0) {
                log('No variants provided to getPriceRange', { productId });
                return { min: 0, max: 0 };
            }
            // Calculate total price (item + shipping) for each variant
            const totalPrices = variants.map(v => {
                const itemPrice = v.price?.discountedValue || 0;
                const shippingCost = v.shipping?.cost || 0;
                return itemPrice + shippingCost;
            });

            if (totalPrices.length === 0) {
               log('Calculated totalPrices array is empty', { productId, variants });
               return { min: 0, max: 0 };
            }

            return {
                min: Math.min(...totalPrices),
                max: Math.max(...totalPrices)
            };
        }

        getFreeShippingThreshold(variants, productId) {
            return variants.reduce((threshold, variant) => {
                return variant.shipping.freeThreshold !== null
                    ? Math.min(threshold || Infinity, variant.shipping.freeThreshold)
                    : threshold;
            }, null);
        }

        addPriceDistributionGraph(container, bestVariant, priceRange, productId) {
            const graph = document.createElement('div');
            graph.className = 'ali-real-price-distribution';

            const marker = document.createElement('div');
            marker.className = 'ali-real-price-distribution-marker';

            const position = ((bestVariant.price.discountedValue - priceRange.min) /
                (priceRange.max - priceRange.min)) * 100;
            marker.style.left = `${position}%`;

            graph.appendChild(marker);
            container.appendChild(graph);
        }

        // Helper method to get element depth in DOM
        getElementDepth(element) {
            let depth = 0;
            let current = element;
            while (current.parentNode) {
                depth++;
                current = current.parentNode;
            }
            return depth;
        }
    }

    // Initialize the userscript
    async function init() {
        log('Initializing script...');
        
        // --- Load Cache Disable Preference FIRST --- 
        const storedValue = await GM.getValue('aliexpress_disable_cache', false);
        log(`[init] Loaded 'aliexpress_disable_cache' from GM.getValue: ${storedValue} (Type: ${typeof storedValue})`);
        isCacheDisabled = storedValue;
        log(`[init] Set global isCacheDisabled to: ${isCacheDisabled}`);

        // --- Instantiate LoadingManager AFTER loading preference --- // MOVED LATER
        // const loadingManager = new LoadingManager(); // Instance is global now

        // Add styles
        try {
            GM_addStyle(STYLES);
            log('Styles added successfully');
        } catch (error) {
            log('Error adding styles:', error);
        }

        // Create instances of main classes (except DOMEnhancer)
        const dataManager = new DataManager();
        globalCache = dataManager.cache; // Store cache instance globally
        const priceContextCalculator = new PriceContextCalculator();
        // const domEnhancer = new DOMEnhancer(dataManager, priceContextCalculator); // MOVED LATER

        // Initialize token
        await dataManager.initializeToken();
        log('Token initialized (or checked)');

        // Start observing product cards - COUNT FIRST
        const productCards = document.querySelectorAll(SELECTORS.productCard);
        log('Found initial product cards:', productCards.length);
        
        // Initialize loading manager with total number of products
        // Uses the GLOBAL loadingManager instance implicitly now
        if (productCards.length > 0) {
            loadingManager.completedItems = 0;
            loadingManager.startLoading(productCards.length);
            log(`Loading manager initialized: total=${loadingManager.totalItems}, completed=${loadingManager.completedItems}`);
        } else {
            // Ensure totalItems is 0 if no cards found initially
            loadingManager.totalItems = 0;
            loadingManager.completedItems = 0;
            loadingManager.updateProgress(); // Show 0/0
            log(`Loading manager initialized: total=0 (no initial cards)`);
        }
 
        // --- Create DOMEnhancer AFTER initializing loadingManager ---
        const domEnhancer = new DOMEnhancer(dataManager, priceContextCalculator);
        log('DOMEnhancer created');
 
        // --- Observe Initial Cards ---
        productCards.forEach(card => {
            const productId = utils.extractProductId(card);
            if (productId) {
                log('Observing and immediately enhancing initial card:', productId, { productId });
                domEnhancer.observer.observe(card); // Still observe in case manual call fails or for other reasons
                domEnhancer.enhanceProductCard(card, productId); // Start processing immediately, do not await
            } else {
                log('Skipping initial card - no product ID found', card);
                // If no ID, we can't process, and don't need to increment total/complete counts for it.
                // Adjust loading manager counts if necessary (though startLoading already set the total based on querySelectorAll count)
                // Maybe decrement totalItems if an initial card lacks an ID? Or handle it gracefully in itemComplete?
                // For now, just log and skip.
            }
        });

        // --- Handle dynamic content loading (MutationObserver) ---
        const observer = new MutationObserver((mutations) => {
            log('DOM mutation detected');
            let newCards = [];
            mutations.forEach((mutation) => {
                mutation.addedNodes.forEach((node) => {
                    if (node.nodeType === Node.ELEMENT_NODE) {
                        // Check if the added node itself is a product card
                        if (node.matches(SELECTORS.productCard)) {
                            newCards.push(node);
                        } else {
                            // Check if the added node contains product cards
                            const cards = node.querySelectorAll(SELECTORS.productCard);
                            if (cards.length > 0) {
                                newCards.push(...Array.from(cards));
                            }
                        }
                    }
                });
            });
            
            // Filter out cards that might have already been processed 
            // (e.g., if mutation observer fires multiple times rapidly)
            newCards = newCards.filter(card => !domEnhancer.processedCards.has(card));

            if (newCards.length > 0) {
                log('Found new product cards via MutationObserver:', newCards.length);
                // Update loading manager with new total
                const newTotal = loadingManager.totalItems + newCards.length;
                // Reset completed count only if starting from zero
                if (loadingManager.totalItems === 0) {
                    log('First batch of dynamic items detected, resetting completed count.');
                    loadingManager.completedItems = 0;
                }
                loadingManager.startLoading(newTotal); // Sets new total, updates display
                
                newCards.forEach(card => {
                    const productId = utils.extractProductId(card);
                    if (productId) { // Ensure we have an ID before observing
                       log('Observing new card found by MutationObserver:', productId, { productId });
                       domEnhancer.observer.observe(card);
                    } else {
                       log('Skipping observation for new card - no product ID found', card);
                    }
                });
            }
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
        log('Mutation observer started');
    }

    // Start the script
    if (document.readyState === 'loading') {
        log('Document still loading, waiting for DOMContentLoaded');
        document.addEventListener('DOMContentLoaded', init);
    } else {
        log('Document already loaded, initializing immediately');
        init();
    }

    // --- Function to handle cache disable checkbox change ---
    async function handleDisableCacheChange(event) {
        isCacheDisabled = event.target.checked;
        log('Cache disabled preference changed:', isCacheDisabled);
        await GM.setValue('aliexpress_disable_cache', isCacheDisabled);
        // Optional: Clear cache when disabling?
        if (isCacheDisabled && globalCache) {
             await globalCache.clear();
             log('Cache cleared because it was disabled.');
             // Optionally alert the user or reload
             // alert('Cache disabled and cleared.');
        }
    }
})();