// debounce handles for setTimeout tasks
let doosearchasClearTimeout;
let doosearchasClearTimeout2;
let doosearchasClearTimeout3;

// Search terms values are used in filtering and processing
let doosearchasInputValue = '';
let doosearchasTurm0 = '';
let doosearchasTurm1 = '';
let doosearchasTurm3 = '';
let doosearchasTurm4 = '';
let doosearchasTurm6 = '';
let doosearchasTurm7 = '';
let doosearchasTurm8 = '';

// Filter states: selected brands, prices, categories, etc.
let doosearchasBrand = [];
let doosearchasPrice1 = [];
let doosearchasPrice2 = [];
let doosearchasCategory = [];
let doosearchasTransformedCategory = [];

// Min and max price filter range
let doosearchasMinMaxPrice = [];

// Used to avoid recalculating min/max price too often
let doosearchasNotAlwaysNewMinMax = [];

// Conditional booleans for multi-state filter logic or UI control
let doosearchasConditionalBol1 = 'false';
let doosearchasConditionalBol2 = 'false';
let doosearchasConditionalBol3 = 'false';

// Track whether filter UI is open or closed
let doosearchasConditionalWay = 'open';

// Pagination state
let doosearchasCurrentPage = 1;

// Store previous search term to detect if search has changed
let doosearchasTurmHistroy = '';

// Flag to detect if current search is same as last (for optimization)
let doosearchasIsSame ='';

// Reset all the above states to their initial values
function doosearchas_initialState(){
    doosearchasInputValue = '';
    doosearchasTurm0 = '';
    doosearchasTurm1 = '';
    doosearchasTurm3 = '';
    doosearchasTurm4 = '';
    doosearchasTurm6 = '';
    doosearchasTurm7 = '';
    doosearchasTurm8 = '';
    doosearchasBrand = [];
    doosearchasPrice1 = [];
    doosearchasPrice2 = [];
    doosearchasCategory = [];
    doosearchasTransformedCategory = [];
    doosearchasMinMaxPrice = [];
    doosearchasNotAlwaysNewMinMax = [];
    doosearchasConditionalBol1 = 'false';
    doosearchasConditionalBol2 = 'false';
    doosearchasConditionalBol3 = 'false';
    doosearchasConditionalWay = 'open';
    doosearchasCurrentPage = 1;
    doosearchasTurmHistroy = '';
    doosearchasIsSame ='';
}

// Utility to safely parse JSON settings data provided from backend (localized script)
function doosearchas_func_setting_data(){
    try {
        const jsObject = JSON.parse(doosearchasLocalizeFrontent.settings_data);
        return jsObject;
    } catch (error) {
        console.error("Invalid JSON string:", error);
    }
}

// Additional search term and control variables
let doosearchasTurm09 = '';
let currentExecutionId = 0; // To track unique async calls to prevent ajax call
let doosearchasConditionalStop = 'run'; // Flag to stop some conditional processing
let targetNameHold = '';

// Number of Products per page for pagination
const doosearchasProductsPerPage = 40;


/**
 * Class: DooSearchas_Class_Search
 * 
 * Handles API calls to fetch filtered search results from the custom WordPress REST API.
 * Builds query parameters based on user input and filter states (brand, category, price, page).
 * Processes response data and updates the UI with results, filters, and price ranges.
 * 
 * Called From:
 * - DooSearchas_Class_Controler > myRender()
 */
class DooSearchas_Class_Search {
    constructor(oldExecIdPara, filter, targetNamePara, doosearchasBrandPara, doosearchasCategoryPara , doosearchasPrice2Para, pagePara = 1) {
        this.query = filter['searchTurm'];
        this.searchField = filter['searchField'];
        this.brand = filter['brand'].join('~');
        this.category = filter['category'].join('~');
        this.minPrice = filter['minPrice'];
        this.maxPrice = filter['maxPrice'];
        this.page = pagePara;
        this.brandV = doosearchasBrandPara;
        this.categoryV = doosearchasCategoryPara;
        this.price2V = doosearchasPrice2Para;
        this.targetName = targetNamePara;
        this.execId = oldExecIdPara;
        this.doosearchasReorganizedResult = [];

        // Start the AJAX request on initialization
        this.myAJAX()
    }
    async myAJAX() {
        try {
            // Build the API URL with query parameters
            let apiUrl = `${doosearchasLocalizeFrontent.root_url}/wp-json/dsas/v1/items`;
            const params = new URLSearchParams();
            if (this.query) {
                params.append('search', this.query);
            }
            if (this.searchField) {
                params.append('search_field', this.searchField);
            }
            if (this.brand) {
                params.append('brand', this.brand);
            }
            if (this.category) {
                params.append('category', this.category);
            }
            if (this.minPrice) {
                params.append('min_price', this.minPrice);
            }
            if (this.maxPrice) {
                params.append('max_price', this.maxPrice);
            }
            if (this.page) {
                params.append('page', this.page);
            }
            apiUrl += `?${params.toString()}`;

            // Fetch the search results from the API
            const response = await fetch(apiUrl);
            const data = await response.json();

            // Process products data through a reorganizer class
            const doosearchasReorganized = new DooSearchas_Class_Product_Reorganized(data['data']['products']);
            this.doosearchasReorganizedResult = doosearchasReorganized.process();

            // Extract filter data from API response
            let freeFilterTotal = data.pagination.total_items;
            let freeFilterBrand = {"brand": data.brand_counts};
            let freeFilterCategory = {"Category": data.category_counts} ;
            let freeFilterPrice = data.price_range;
            let minMaxPriceArry = [freeFilterPrice.min,freeFilterPrice.max];

            // Check if this is the most recent search execution
            if (this.execId !== currentExecutionId) {
                return; // Abort if outdated execution
            }

            // Render the UI with the reorganized products and total count
            const doosearchasRender = new DooSearchas_Class_UI(this.doosearchasReorganizedResult,freeFilterTotal);

            // If there are results, trigger fullscreen popup and update history
            if (this.doosearchasReorganizedResult && this.doosearchasReorganizedResult.length > 0) {
                const doosearchasFullScreen = new DooSearchas_Class_All();
                doosearchasFullScreen.fullscreenPopup('full');
                const historyManager = new DooSearchas_Class_HistoryManager();
                historyManager.addHistoryToList();
            }

            // Update the filter UI (brand/category counts and price range sliders)
            const DooSearchasFilter = new DooSearchas_Class_filter (this.targetName,this.brandV,this.categoryV,this.price2V,minMaxPriceArry,freeFilterBrand,freeFilterCategory);
        } catch (error) {
            console.error('Search API error:', error);
        }
    }
}

/**
 * Class: DooSearchas_Class_UI
 * 
 * Handles rendering of search result UI elements such as product cards, 
 * feature lists, result count, pagination, and no-result screen.
 * 
 * Called From:
 * - DooSearchas_Class_Search after processing and reorganizing product data.
 * 
 * Responsibilities:
 * - Renders product result items and features list.
 * - Manages product stock, price display, and Add to Cart/View Cart buttons.
 * - Displays pagination UI and controls.
 * - Handles "no result found" screen display.
 */
class DooSearchas_Class_UI{
    constructor(productPara,freeFilterTotal) {
      this.reorganizedProduct = productPara;
      this.totalProduct = freeFilterTotal;
      this.productList(); // Render the product list on initialization
    }

    // Main method to render product list UI
    productList() {
        // Show the popup container for search results
        const doosearchasPopupResult = new DooSearchas_Class_Popup();
        doosearchasPopupResult.showResult();

        // Hide suggestions box if exists
        const suggestionsBox = document.getElementById('doosearchas_s-suggestions');
        if(suggestionsBox){
            suggestionsBox.style.display = 'none';
        }

        // Show cart icon wrapper and clear previous results & spinners
        document.querySelector('.doosearchas_s-cart-icon-wrapper').style.visibility = 'visible';
        document.getElementById('doosearchas_s-result-item-list').innerHTML = '';
        document.querySelector('.doosearchas_s-spinnerSpan').classList.remove('visible');
        document.querySelector('.doosearchas_s-spinnerSpan2').classList.remove('visible');

        doosearchasConditionalBol3 = 'false'

        // Update the result count display
        document.getElementById('doosearchas_s-result-item-count').innerHTML = '';
        document.getElementById('doosearchas_s-result-item-count').innerHTML = `<span>${this.totalProduct}</span> Result Found`;

        if (this.reorganizedProduct.length) {
            // Iterate through each product to build and append its UI element
            this.reorganizedProduct.forEach(item => {
                const uniqueFeatureId = `product-features-${item.id}`;
                const resultItem = document.createElement('div');
                resultItem.className = 'doosearchas_s-result-item';

                // Construct product HTML with dynamic sale label, stock info, price, etc.
                resultItem.innerHTML = `
                    <a href="${item.permalink}" class="doosearchas_s-result-link">
                        <div class="doosearchas_s-item-wrap">
                            <div class="doosearchas_s-img-wrapper">
                                <img class="doosearchas_s-img-scale" src="${item.image}" alt="${item.title}" />
                            </div>
                            ${item.del_price != 0?`
                            <div class="doosearchas_s-product-labels">
                                <span class="doosearchas_s-tag">Sale!</span>
                                <span class="doosearchas_s-off">${Math.floor([(item.del_price-item.price)/item.del_price]*100)}%</span>
                            </div>`:``}
                            <p class="doosearchas_s-product-id">
                                <span>#${item.id}</span>
                            </p>
                            <div class="doosearchas_s-content-wrap">
                                <h3>${item.title}</h3>
                                ${item.status == 1? 
                                    (item.stock_quantity > 0 ? `<span class="doosearchas_s-price-style">${item.price_html}</span>` :`<span class="doosearchas_s-price-style outof">${item.price_html}</span>`) 
                                    : `<span class="doosearchas_s-price-style">${item.price_html}</span>` 
                                }
                                ${item.status == 1? 
                                    (item.stock_quantity > 0 ? 
                                    `<p class="doosearchas_s-instock">In stock:<span class="stock-value"> ${item.stock_quantity}</span></p>` :
                                    '<p class="doosearchas_s-outofstock">Out of stock</p>') 
                                    : ''
                                }
                                ${doosearchas_func_setting_data().description[0] === 'description'?`<p class="doosearchas_s-product-description">${this.getCleanShortDescription(item.short_description,doosearchas_func_setting_data().description[1])}</p>`:''}
                                <ul class="doosearchas_s-product-features" id="${uniqueFeatureId}"></ul>
                            </div>
                        </div>
                    </a>
                    ${item.status == 1? 
                        (item.stock_quantity > 0 ? 
                        `
                            <a href="?add-to-cart=${item.id}" data-goto-product-id="${item.id}" class="doosearchas_s-add-to-cart">
                                <span class="doosearchas_s-icon-add-to-cart" id="doosearchas_s-icon-add-to-cart-${item.id}">
                                    <div>
                                        <img src="${doosearchasLocalizeFrontent.icons_url}add_shopping_cart.svg" alt="Add to Cart Icon" width="20" height="20" />
                                    </div>
                                </span>
                                <span class="doosearchas_s-cart-text">${doosearchasLocalizeFrontent.text_domain.add_to_cart_text}</span>
                            </a>
                        ` :
                        `
                            <a href="?add-to-cart=${item.id}" data-goto-product-id="${item.id}" class="doosearchas_s-add-to-cart" style="pointer-events: none; background-color: gray;">
                                <span class="doosearchas_s-icon-add-to-cart" id="doosearchas_s-icon-add-to-cart-${item.id}">
                                    <div>
                                        <img src="${doosearchasLocalizeFrontent.icons_url}add_shopping_cart.svg" alt="Add to Cart Icon" width="20" height="20" />
                                    </div>
                                </span>
                                <span class="doosearchas_s-cart-text">${doosearchasLocalizeFrontent.text_domain.add_to_cart_text}</span>
                            </a>                   
                        `) 
                        : 
                        `
                            <a href="?add-to-cart=${item.id}" data-goto-product-id="${item.id}" class="doosearchas_s-add-to-cart">
                                <span class="doosearchas_s-icon-add-to-cart" id="doosearchas_s-icon-add-to-cart-${item.id}">
                                    <div>
                                        <img src="${doosearchasLocalizeFrontent.icons_url}add_shopping_cart.svg" alt="Add to Cart Icon" width="20" height="20" />
                                    </div>
                                </span>
                                <span class="doosearchas_s-cart-text">${doosearchasLocalizeFrontent.text_domain.add_to_cart_text}</span>
                            </a>
                        `
                    }
                    <a href="${doosearchasLocalizeFrontent.cart_url}" class="doosearchas_s-view-cart" id="doosearchas_s-view-cart-${item.id}">
                        <span class="doosearchas_s-view-cart-icon">
                            <div>
                                <img src="${doosearchasLocalizeFrontent.icons_url}eye.svg" alt="Eye Icon" width="20" height="20" />
                            </div>
                        </span>
                        <span class="doosearchas_s-view-cart-text">${doosearchasLocalizeFrontent.text_domain.view_cart_text}</span>
                    </a>
                `;

                // Append the built product item to the results list container
                document.getElementById('doosearchas_s-result-item-list').appendChild(resultItem);

                // Scroll product list wrapper to top after adding product
                const container1 = document.getElementById('doosearchas_s-result-item-wrapper');
                if (container1) container1.scrollTop = 0;

                // Features exclusion list from settings
                const exclude = doosearchas_func_setting_data().featuresList[2]; //["Vendor Name","BTU"]
                function parseStringToObj(inputString, exclude) {
                    const parts = inputString.split('||');
                    const keyValueString = parts[parts.length - 1].trim();
                    const keyValuePairs = keyValueString.split(',');
                    const resultObj = {};
                    keyValuePairs.forEach(pair => {
                        const [key, value] = pair.split(':').map(str => str.trim());
                        if (key && value && !exclude.includes(key)) {
                            resultObj[key] = value;
                        }
                    });
                    return resultObj;
                }

                // Features to add first and max items to show, from settings
                const addFirst = doosearchas_func_setting_data().featuresList[3]; //["Power Type","BTU","Material",];
                const maxItems = doosearchas_func_setting_data().featuresList[1]; // max number(1-5) of items to display
                function generateFeatureList(obj, addFirstKeys, maxItems, uniqueId) {
                    const featureList = document.getElementById(uniqueId);
                    featureList.innerHTML = "";
                    const keys = Object.keys(obj);
                    if (keys.length === 0) {
                        featureList.style.display = "none";
                        return;
                    } else {
                        featureList.style.display = "block";
                    }
                    const finalList = [];
                    for (const key of addFirstKeys) {
                        if (obj.hasOwnProperty(key) && finalList.length < maxItems) {
                            finalList.push(key);
                        }
                    }
                    for (const key of keys) {
                        if (!finalList.includes(key) && finalList.length < maxItems) {
                            finalList.push(key);
                        }
                    }
                    finalList.forEach(key => {
                        const value = obj[key];
                        const listItem = document.createElement("li");
                        listItem.innerHTML = `<span class="doosearchas_s-checked">✓</span> ${key}: ${value}`;
                        featureList.appendChild(listItem);
                    });
                }

                // After appending the item, generate the product features list dynamically
                const listInfo = parseStringToObj(item.filter,exclude);
                const featureList = doosearchas_func_setting_data().featuresList[0];  // 'on'/'off'
                if(featureList === 'on'){
                    generateFeatureList(listInfo, addFirst, maxItems, uniqueFeatureId);
                }

                // Shorten long feature text for better display
                const productFeatures = document.querySelectorAll('.doosearchas_s-product-features li');
                if(productFeatures){
                    productFeatures.forEach(item => {
                        let fullText = item.textContent.trim();
                        let checkmark = fullText.slice(0, 2); // Preserve the "✓ " part
                        let text = fullText.slice(2).trim(); // The rest of the content after "✓ "
                        if (text.length > 22) {
                            text = text.replace(/\bType:/g, ':');
                            if (text.length > 22) {
                                text = text.replace(/^[^:]+:\s*/, '');
                                if (text.length > 22) {
                                    text = text.slice(0, 19) + '...';
                                }
                            }
                        }
                        item.textContent = checkmark + ' ' + text;
                    });
                }
            });

            // After product list rendered, create pagination UI
            this.createPagination();
        } else {
            // No products found, show no result UI
            this.noResultFound('noResult');
        }
    }

    // Clean short description to plain text and limit length
    getCleanShortDescription(desc, maxLength = 18) {
        const tempDiv = document.createElement("div");
        tempDiv.innerHTML = desc;
        const textOnly = tempDiv.textContent || tempDiv.innerText || "";
        return textOnly.length > maxLength 
            ? textOnly.slice(0, maxLength).trim() + "..." 
            : textOnly;
    }

    // Show no result popup/screen when no products found
    noResultFound(noRes){
        if(noRes === 'noResult'){
            const doosearchasShortScreen = new DooSearchas_Class_All();
            doosearchasShortScreen.fullscreenPopup('short');
            doosearchasConditionalBol2 = 'true'
        }
    }

    // Pagination UI creation logic
    createPagination() {
        const paginationContainer = document.getElementById('doosearchas_s-pagination');
        paginationContainer.innerHTML = '';

        // Calculate total pages based on total product count and items per page
        let totalPages = Math.ceil(this.totalProduct / doosearchasProductsPerPage);
        if (totalPages <= 1) return; // No pagination if only one page

        // Previous page button if applicable
        if (doosearchasCurrentPage > 1) {
            paginationContainer.innerHTML += `<button onclick="doosearchas_Func_change_page(${doosearchasCurrentPage - 1})">Previous</button>`;
        }

        const maxButtons = 8;
        const pageButtons = [];

        // Logic for showing page buttons and ellipses for large page sets
        if (totalPages <= maxButtons) {
            for (let i = 1; i <= totalPages; i++) {
                pageButtons.push(i);
            }
        } else {
            if (doosearchasCurrentPage <= 4) {
                pageButtons.push(...[1, 2, 3, 4, 5, 6, '...', totalPages]);
            } else if (doosearchasCurrentPage >= totalPages - 3) {
                pageButtons.push(...[1, '...', totalPages - 5, totalPages - 4, totalPages - 3, totalPages - 2, totalPages - 1, totalPages]);
            } else {
                pageButtons.push(...[
                    1,
                    '...',
                    doosearchasCurrentPage - 1,
                    doosearchasCurrentPage,
                    doosearchasCurrentPage + 1,
                    '...',
                    totalPages
                ]);
            }
        }

        // Render the page buttons and dots in the container
        for (let i = 0; i < pageButtons.length; i++) {
            const btn = pageButtons[i];
            if (btn === '...') {
                paginationContainer.innerHTML += `<span class="dots">...</span>`;
            } else {
                paginationContainer.innerHTML += `<button onclick="doosearchas_Func_change_page(${btn})" class="${btn === doosearchasCurrentPage ? 'active' : ''}">${btn}</button>`;
            }
        }

        // Next page button if applicable
        if (doosearchasCurrentPage < totalPages) {
            paginationContainer.innerHTML += `<button onclick="doosearchas_Func_change_page(${doosearchasCurrentPage + 1})">Next</button>`;
        }
    }
}

/**
 * Class: DooSearchas_Class_filter
 * 
 * Dynamically generate and control brand/category filters and price range UI.
 *
 * Called From:
 * - DooSearchas_Class_Search after fetching filtered product data.
 */
class DooSearchas_Class_filter{
    constructor(targetNamePara,brandVPara,CategoryVPara,price2VPara,minMaxPriceArry,freeFilterBrand,freeFilterCategory) {
        // Store all incoming parameters for filtering
        this.targetName = targetNamePara;
        this.brandArr = brandVPara;
        this.categoryArr = CategoryVPara;
        this.price2Arr = price2VPara;
        this.minMax = minMaxPriceArry;
        this.brand = freeFilterBrand;
        this.category = freeFilterCategory;
        this.sideberFilterCallLogic(); // Start the filtering logic
    }

    // Main logic controller for sidebar filters
    sideberFilterCallLogic(){
        clearTimeout(doosearchasClearTimeout2);
        doosearchasClearTimeout2 = setTimeout(()=>{
            // Apply dependent filter logic based on the current target filter
            if(this.targetName === "price"){
                this.sideberBrandFilterLogic(this.brand);
                this.sideberCategoryFilterLogic(this.category);
            }else if(this.targetName === "brand"){
                this.sideberCategoryFilterLogic(this.category);
            }
        },100);

        const doosearchasSecondaryInput = document.getElementById('doosearchas_s-secondary-input');

        // If input changed or new search triggered, reset scroll & update filters
        if ( doosearchasConditionalBol2 === 'true' || doosearchasTurm8 != doosearchasSecondaryInput.value) {
            doosearchasTurm8 = doosearchasSecondaryInput.value;
            doosearchasConditionalBol2 = 'false';
            const container2 = document.getElementById('doosearchas_s-result-filter');
            if (container2) container2.scrollTop = 0;
            this.sideberBrandFilterLogic(this.brand);
            this.sideberCategoryFilterLogic(this.category);
            this.contralPrice();
        } else {
            this.contralPrice();
        }
    }

    // Price filter controller: Handles price range display and storage logic
    contralPrice(){
        if(this.brandArr.length != [].length || this.categoryArr.length != [].length ){
            if(this.targetName == 'price2' && doosearchasConditionalWay == 'open'){
                doosearchasConditionalWay = 'close';
                doosearchasNotAlwaysNewMinMax = this.minMax;
            }
            if(this.targetName != 'price2'){
                doosearchasConditionalWay = 'open';
                doosearchasNotAlwaysNewMinMax = [];
            } 
            doosearchasMinMaxPrice = this.minMax;
            const storeUnstore = doosearchasNotAlwaysNewMinMax.length == [].length ? doosearchasMinMaxPrice : doosearchasNotAlwaysNewMinMax;
            if(this.price2Arr.length == [].length || this.targetName == 'brand'  || this.targetName == 'category' ){
                this.sidebarPriceFilterLogic2(storeUnstore);
            }

            // Show slider 2 for filtered price
            document.querySelector('.doosearchas_s-slider-wrap').style.display = "none";
            document.querySelector('.doosearchas_s-slider-wrap2').style.display = "block";
        }else if(this.brandArr.length == [].length && this.categoryArr.length == [].length ){
            // Show main price slider
            document.querySelector('.doosearchas_s-slider-wrap').style.display = "block";
            document.querySelector('.doosearchas_s-slider-wrap2').style.display = "none";
            doosearchasPrice2 = [];
        }
        let forMinMaxPriceStore = this.minMax;
        this.sidebarPriceFilterLogic(forMinMaxPriceStore);
    }

    // Price slider for initial filter (main price range)
    sidebarPriceFilterLogic(forMinMaxPriceStore = [0,1000]){
        const doosearchasForMinRangeInput = document.getElementById('doosearchas_s-minRange');
        const doosearchasForMaxRangeInput = document.getElementById('doosearchas_s-maxRange');
        const doosearchasForMinTextInput = document.getElementById('doosearchas_s-minPriceText');
        const doosearchasForMaxTextInput = document.getElementById('doosearchas_s-maxPriceText');
        const doosearchasSecondaryInput = document.getElementById('doosearchas_s-secondary-input');

        // Only reset if input changed
        if(doosearchasTurm1 != doosearchasSecondaryInput.value ){
            doosearchasTurm1 = doosearchasSecondaryInput.value;
            document.querySelector('.doosearchas_s-slider-wrap').style.display = "block";

            // Set slider range values
            doosearchasForMinRangeInput.setAttribute('min', forMinMaxPriceStore[0]);
            doosearchasForMinRangeInput.setAttribute('max', forMinMaxPriceStore[1]);
            doosearchasForMinRangeInput.setAttribute('value', forMinMaxPriceStore[0]);
            doosearchasForMaxRangeInput.setAttribute('min', forMinMaxPriceStore[0]);
            doosearchasForMaxRangeInput.setAttribute('max', forMinMaxPriceStore[1]);
            doosearchasForMaxRangeInput.setAttribute('value', forMinMaxPriceStore[1]);
            doosearchasForMinTextInput.value = forMinMaxPriceStore[0] === Infinity ?'':forMinMaxPriceStore[0];
            doosearchasForMaxTextInput.value = forMinMaxPriceStore[1] === -Infinity ?'':forMinMaxPriceStore[1];
        }
        
        // Slider interaction and UI update
        doosearchasForMinRangeInput.addEventListener('input', function() {
            let minValue = parseInt(doosearchasForMinRangeInput.value);
            let maxValue = parseInt(doosearchasForMaxRangeInput.value);
            if (minValue > maxValue - 1) {
              doosearchasForMinRangeInput.value = maxValue - 1;
              minValue = maxValue - 1;
            }
            inFuncUI(minValue, maxValue);
        });
        doosearchasForMaxRangeInput.addEventListener('input', function() {
        let minValue = parseInt(doosearchasForMinRangeInput.value);
        let maxValue = parseInt(doosearchasForMaxRangeInput.value);
        if (maxValue < minValue + 1) {
            doosearchasForMaxRangeInput.value = minValue + 1;
            maxValue = minValue + 1;
        }
            inFuncUI(minValue, maxValue);
        });

        // Sync UI and track fill
        function inFuncUI(minValue, maxValue) {
            doosearchasForMinTextInput.value = minValue;
            doosearchasForMaxTextInput.value = maxValue;
            inFuncTrack(minValue, maxValue);
        }
        doosearchasForMinRangeInput.value = forMinMaxPriceStore[0];
        doosearchasForMaxRangeInput.value = forMinMaxPriceStore[1];
        inFuncTrack(forMinMaxPriceStore[0], forMinMaxPriceStore[1]);
        function inFuncTrack(min, max) {
            const doosearchasForSliderTrack = document.querySelector('.doosearchas_s-slider-track');
            const rangeMin = parseFloat(doosearchasForMinRangeInput.min);
            const rangeMax = parseFloat(doosearchasForMaxRangeInput.max);
            const percent1 = ((min - rangeMin) / (rangeMax - rangeMin)) * 100;
            const percent2 = ((max - rangeMin) / (rangeMax - rangeMin)) * 100;
            doosearchasForSliderTrack.style.background = `linear-gradient(to right, #ddd ${percent1}%, #4CAF50 ${percent1}%, #4CAF50 ${percent2}%, #ddd ${percent2}%)`;
        }
    }

    // Price slider 2: Used when filters are already applied
    sidebarPriceFilterLogic2(minMaxPara = [0,1000]){
        const doosearchasForMinRangeInput2 = document.getElementById('doosearchas_s-minRange2');
        const doosearchasForMaxRangeInput2 = document.getElementById('doosearchas_s-maxRange2');
        const doosearchasForMinTextInput2 = document.getElementById('doosearchas_s-minPriceText2');
        const doosearchasForMaxTextInput2 = document.getElementById('doosearchas_s-maxPriceText2');

        // Set slider values
        doosearchasForMinRangeInput2.setAttribute('min', minMaxPara[0]);
        doosearchasForMinRangeInput2.setAttribute('max', minMaxPara[1]);
        doosearchasForMinRangeInput2.setAttribute('value', minMaxPara[0]);
        doosearchasForMaxRangeInput2.setAttribute('min', minMaxPara[0]);
        doosearchasForMaxRangeInput2.setAttribute('max', minMaxPara[1]);
        doosearchasForMaxRangeInput2.setAttribute('value', minMaxPara[1]);
        doosearchasForMinTextInput2.value = minMaxPara[0] === Infinity ?'':minMaxPara[0];
        doosearchasForMaxTextInput2.value = minMaxPara[1] === -Infinity ?'':minMaxPara[1];

        // Sync input and track
        doosearchasForMinRangeInput2.addEventListener('input', function() {
            let minValue2 = parseInt(doosearchasForMinRangeInput2.value);
            let maxValue2 = parseInt(doosearchasForMaxRangeInput2.value);
            if (minValue2 > maxValue2 - 1) {
              doosearchasForMinRangeInput2.value = maxValue2 - 1;
              minValue2 = maxValue2 - 1;
            }
            inFuncUI(minValue2, maxValue2);
        });
        doosearchasForMaxRangeInput2.addEventListener('input', function() {
        let minValue2 = parseInt(doosearchasForMinRangeInput2.value);
        let maxValue2 = parseInt(doosearchasForMaxRangeInput2.value);
        if (maxValue2 < minValue2 + 1) {
            doosearchasForMaxRangeInput2.value = minValue2 + 1;
            maxValue2 = minValue2 + 1;
        }
            inFuncUI(minValue2, maxValue2);
        });
        function inFuncUI(minValue2, maxValue2) {
            doosearchasForMinTextInput2.value = minValue2;
            doosearchasForMaxTextInput2.value = maxValue2;
            inFuncTrack(minValue2, maxValue2);
        }
        doosearchasForMinRangeInput2.value = minMaxPara[0];
        doosearchasForMaxRangeInput2.value = minMaxPara[1];
        inFuncTrack(minMaxPara[0], minMaxPara[1]);
        function inFuncTrack(min, max) {
            const doosearchasForSliderTrack2 = document.querySelector('.doosearchas_s-slider-track2');
            const rangeMin2 = parseFloat(doosearchasForMinRangeInput2.min);
            const rangeMax2 = parseFloat(doosearchasForMaxRangeInput2.max);
            const percent1 = ((min - rangeMin2) / (rangeMax2 - rangeMin2)) * 100;
            const percent2 = ((max - rangeMin2) / (rangeMax2 - rangeMin2)) * 100;
            doosearchasForSliderTrack2.style.background = `linear-gradient(to right, #ddd ${percent1}%, #4CAF50 ${percent1}%, #4CAF50 ${percent2}%, #ddd ${percent2}%)`;
        }
    }

    // Filter logic for brand: removes blocked brands
    sideberBrandFilterLogic(brandsPara){
        let allBrands = brandsPara;
        const stopAddingBrand = doosearchas_func_setting_data().brands;
        
        // Remove blocked brands (except the first one)
        allBrands.brand = [
        allBrands.brand[0],
        ...allBrands.brand.slice(1).filter(([label]) => !stopAddingBrand.includes(label))
        ];

        this.sidebarUI(allBrands,'brand');
    }

    // Filter logic for category: removes blocked categories
    sideberCategoryFilterLogic(categoriesPara){
        let allCategories = categoriesPara;
        const stopAddingcategory = doosearchas_func_setting_data().categories.map(category => category.replace(/&/g, '&amp;').trim());

        allCategories.Category = [
        allCategories.Category[0],
        ...allCategories.Category.slice(1).filter(([label]) => !stopAddingcategory.includes(label))
        ];

        this.sidebarUI(allCategories,'category');
    }

    // Render the filter UI dynamically (brands or categories)
    sidebarUI(products,diffCondition){
        const doosearchasForAppendBrand = document.querySelector('.doosearchas_s-brand-filter');
        const doosearchasForAppendCategory = document.querySelector('.doosearchas_s-category-filter');
        if(diffCondition === "brand"){
            doosearchasForAppendBrand.innerHTML = '';
        }else if(diffCondition === "category"){
            doosearchasForAppendCategory.innerHTML = '';
        }
        for (const filterItem in products) {
            const filterType = products[filterItem][0];
            const filterId = filterItem.toLowerCase().replace(/ /g, '-');

            // Create filter layout container
            const filterDiv = document.createElement('div');
            filterDiv.classList.add('doosearchas_s-filter');
            filterDiv.id = `filter-${filterId}`;
            filterDiv.setAttribute('data-original-name', filterItem);

            // Toggle button to collapse/expand
            const toggleButton = document.createElement('button');
            toggleButton.id = `toggleButton-${filterId}`;
            toggleButton.classList.add('doosearchas_s-btn-style');
            toggleButton.textContent = filterItem;

            // Container for checkbox options
            const categoryFilter = document.createElement('div');
            categoryFilter.id = `categoryFilter-${filterId}`;
            categoryFilter.classList.add('doosearchas_s-collapsed');

            // Add "All" option if category or brand
            const allCheckbox = `
                <div style="display: ${filterId == 'brand' || filterId == 'category'?'flex':'none'}; align-items: center; margin-top: 4px; margin-left: 4px;">
                    <input type="${filterType}" id="all-${filterId}" name="${filterId}" value="" checked>
                    <label for="all-${filterId}" style="font-size: 13px; margin-left: 2px; cursor: pointer;">All ${filterItem}</label><br>
                </div>
            `;
            categoryFilter.innerHTML += allCheckbox;

            // Append each filter option
            products[filterItem].slice(1).forEach((item, index) => {
                const optionId = `option${index + 1}-${filterId}`;
                const checkboxOption = `
                    <div class="doosearchas_s-selectorWrap">
                        <label for="${optionId}">
                            <input type="${filterType}" id="${optionId}" name="${filterId}" value="${item[0].replace(/"/g, '&quot;')}">
                            <span>${item[0]}</span>
                        </label>
                        <span class="doosearchas_s-numberOfitem">${item[1]}</span>
                    </div>
                `;
                categoryFilter.innerHTML += checkboxOption;
            });

            // Add "View More" toggle for filters with many items
            const viewMoreBtn = document.createElement('button');
            viewMoreBtn.classList.add('doosearchas_s-view-more-btn');
            viewMoreBtn.id = `viewMore-${filterId}`;
            viewMoreBtn.textContent = 'View More';
            filterDiv.appendChild(toggleButton);
            filterDiv.appendChild(categoryFilter);
            categoryFilter.appendChild(viewMoreBtn);
            filterDiv.appendChild(toggleButton);
            filterDiv.appendChild(categoryFilter);
            if(diffCondition === "brand"){
                doosearchasForAppendBrand.appendChild(filterDiv);
            }else if(diffCondition === "category"){
                doosearchasForAppendCategory.appendChild(filterDiv);
            }

            // Toggle expand/collapse
            toggleButton.addEventListener('click', function () {
                categoryFilter.classList.toggle('doosearchas_s-expanded');
                toggleButton.classList.toggle('doosearchas_s-expanded');
            });

            // Logic for "All" checkbox exclusive selection
            const allCheckboxElement = document.getElementById(`all-${filterId}`);
            const filterCheckboxes = categoryFilter.querySelectorAll(`input[name="${filterId}"]`);
            allCheckboxElement.addEventListener('change', function () {
                if (allCheckboxElement.checked) {
                    filterCheckboxes.forEach(checkbox => {
                        if (checkbox !== allCheckboxElement) {
                            checkbox.checked = false;
                        }
                    });
                }
            });
            filterCheckboxes.forEach(checkbox => {
                if (checkbox !== allCheckboxElement) {
                    checkbox.addEventListener('change', function () {
                        if (checkbox.checked) {
                            allCheckboxElement.checked = false;
                        }
                    });
                }
            });

            // Handle "View More" toggle visibility
            const allSelectorWraps = categoryFilter.querySelectorAll('.doosearchas_s-selectorWrap');
            if (allSelectorWraps.length > 3) {
                allSelectorWraps.forEach((wrap, index) => {
                    if (index >= 3) {
                        wrap.style.display = 'none';
                    }
                });
                viewMoreBtn.addEventListener('click', function() {
                    if (viewMoreBtn.textContent === 'View More') {
                        allSelectorWraps.forEach(wrap => wrap.style.display = 'flex');
                        viewMoreBtn.textContent = 'View Less';
                    } else {
                        allSelectorWraps.forEach((wrap, index) => {
                            if (index >= 3) {
                                wrap.style.display = 'none';
                            }
                        });
                        viewMoreBtn.textContent = 'View More';
                    }
                });
            } else {
                viewMoreBtn.style.display = 'none';
            }
        }  
    }
}

/**
 * Class: DooSearchas_Class_Popup
 * 
 * Handles the display, hiding, and UI interaction of the main search popup and its sections.
 *
 * Called From:
 * - DOMContentLoaded listener (instantiation)
 * - DooSearchas_Class_UI via productList()
 */
class DooSearchas_Class_Popup {
    constructor() {
        // Get references to all required DOM elements
        this.primaryInput = document.getElementById('doosearchas_s-primary-input');
        this.popup = document.getElementById('doosearchas_s-popup');
        this.closeBtn = document.getElementById('doosearchas_s-popup-close');
        this.popupContent = document.getElementById('doosearchas_s-popup-content');
        this.infoSection = document.getElementById('doosearchas_s-info');
        this.resultSection = document.getElementById('doosearchas_s-result');

        this.init(); // Initialize event listeners and default state
    }

    init() {
        // Show popup when primary input is focused
        this.primaryInput.addEventListener('focus', () => this.showPopup());

        // Hide popup when close button is clicked
        this.closeBtn.addEventListener('click', () => this.hidePopup());

        // Hide popup when clicking outside of the popup content
        this.popup.addEventListener('click', (e) => {
            const isOutside = !e.composedPath().includes(this.popupContent);
            if (isOutside) {
                this.hidePopup();
            }
        });

        this.showInfo(); // Show info section by default
    }

    showPopup() {
        // Display the popup overlay
        this.popup.classList.add('doosearchas_s-show');

        // Auto-focus the secondary input
        document.getElementById('doosearchas_s-secondary-input').focus();

        // Prevent body scrolling while popup is open
        document.body.style.overflow = 'hidden';
    }

    hidePopup() {
        // Hide the popup overlay
        this.popup.classList.remove('doosearchas_s-show');

        // Reset popup content to info state
        this.showInfo();

        // Reset screen size (short layout mode)
        const doosearchasShortScreen = new DooSearchas_Class_All();
        doosearchasShortScreen.fullscreenPopup('short');

        // Clear the secondary input
        document.getElementById('doosearchas_s-secondary-input').value = '';

        // Hide the cart icon
        document.querySelector('.doosearchas_s-cart-icon-wrapper').style.visibility = 'hidden';

        // Reset plugin state
        doosearchas_initialState();

        // Re-enable body scrolling
        document.body.style.overflow = '';
    }

    showInfo() {
        // Hide filter open button and show info grid
        document.getElementById("doosearchas_s-filter-popup-open-btn").style.visibility = 'hidden';
        document.getElementById("doosearchas_s-filter-popup-open-btn-text").style.display = 'none';

        // Display the info section and hide result section
        this.infoSection.style.display = 'grid';
        this.resultSection.style.display = 'none';
    }
    showResult() {
        // Show filter open button and result section
        document.getElementById("doosearchas_s-filter-popup-open-btn").style.visibility = 'visible';
        document.getElementById("doosearchas_s-filter-popup-open-btn-text").style.display = 'block';

        // Hide the info section and show results
        this.infoSection.style.display = 'none';
        this.resultSection.style.display = 'flex';

        // Prevent body scrolling while results are shown
        document.body.style.overflow = 'hidden';
    }
    filterPopup(){
        const openButton = document.getElementById("doosearchas_s-filter-popup-open-btn");
        const closeButton = document.getElementById("doosearchas_s-filter-popup-close-btn");
        const popup = document.getElementById("doosearchas_s-result-filter");

        // Open the filter sidebar
        openButton.addEventListener("click", () => {
            popup.classList.add("filter-active");
        });

        // Close the filter sidebar
        closeButton.addEventListener("click", () => {
            popup.classList.remove("filter-active");
        });
    }
}

// Initialize popup logic after DOM is fully loaded
document.addEventListener('DOMContentLoaded', () => {
    const doosearchasPopup = new DooSearchas_Class_Popup();
    doosearchasPopup.filterPopup();
});

/**
 * Class: DooSearchas_Class_Product_Reorganized
 * 
 * Reformats raw WooCommerce product data fetched from the REST API into a simplified and consistent structure.
 * Extracts price, sale price, stock status, and generates a unique filter string from product attributes.
 * 
 * Called From:
 * - DooSearchas_Class_Search > myAJAX()
 */
class DooSearchas_Class_Product_Reorganized {
    constructor(productsArray, product_id) {
        this.productsArray = productsArray; // Array of products to process
        this.product_id = product_id; // Optional product ID override for id 111
        this.processedProducts = [];  // Array to hold processed product objects
    }

    // Extracts the current (sale or regular) price as a float from WooCommerce price HTML string
    extractPrice(priceHtml) {
        const insRegex = /<ins[^>]*>.*?<bdi><span class="woocommerce-Price-currencySymbol">.*?<\/span>([\d,]+\.\d+)<\/bdi>/s;
        const rangeRegex = /<bdi><span class="woocommerce-Price-currencySymbol">.*?<\/span>([\d,]+\.\d+)<\/bdi>.*?&ndash;/s;
        const singleRegex = /<bdi><span class="woocommerce-Price-currencySymbol">.*?<\/span>([\d,]+\.\d+)<\/bdi>/s;
        let match = priceHtml.match(insRegex) || priceHtml.match(rangeRegex) || priceHtml.match(singleRegex);
        if (match && match[1]) {
            return parseFloat(match[1].replace(/,/g, ''));
        }
        return 0;
    }

    // Extracts the original (del) price as a float from WooCommerce price HTML string
    extractDelPrice(priceHtml) {
        const delRegex = /<del[^>]*>.*?<bdi><span class="woocommerce-Price-currencySymbol">.*?<\/span>([\d,]+\.\d+)<\/bdi>/s;
        const match = priceHtml.match(delRegex);
        if (match && match[1]) {
            return parseFloat(match[1].replace(/,/g, ''));
        }
        return 0;
    }

     // Processes the products array and returns an array of simplified, cleaned product objects
    process() {
        this.productsArray.forEach((product) => {
            // Override product ID if it's 111 (custom logic)
            const finalProductId = product.id === 111 ? this.product_id : product.id;
            const numberToString = String(finalProductId);

            // Convert product attributes object into a string "key: value, key2: value2, ..."
            const attributes = product.attributes || {};
            let assocArrayToString = '';
            for (const [key, value] of Object.entries(attributes)) {
                assocArrayToString += `${key}: ${value}, `;
            }
            assocArrayToString = assocArrayToString.replace(/, $/, '');

            // Combined filter string for search/filtering usage
            const combinedFilter = `${numberToString}||${assocArrayToString}`;

            // Create the processed product object
            const processed = {
                id: String(finalProductId),
                sku: product.sku,
                title: product.title,
                del_price: this.extractDelPrice(product.price).toFixed(6),
                image: product.image,
                price: this.extractPrice(product.price).toFixed(2),
                status: product.stock_management_enabled ? "1" : "0",
                stock_quantity: product.stock_quantity,
                rating: product.rating,
                permalink: product.permalink,
                filter: combinedFilter,
                price_html: product.price,
                short_description:product.short_description
            };
            this.processedProducts.push(processed);
        });
        return this.processedProducts;
    }
}

/**
 * Class: DooSearchas_Class_All
 * 
 * Handles UI-wide utility functions like toggling fullscreen popup mode
 * and managing loading spinner states.
 * 
 * Called From:
 * - Other UI/logic classes to trigger global display changes.
 * 
 */
class DooSearchas_Class_All {
    constructor(cStopPara) {
      this.ConditionalStop = cStopPara;
    }

    // Toggles fullscreen class on the popup content element
    fullscreenPopup(fullShort) {
        if (fullShort === 'full') {
            document.getElementById('doosearchas_s-popup-content').classList.add('doosearchas_s-fullscreen');
        } else if(fullShort === 'short') {
            document.getElementById('doosearchas_s-popup-content').classList.remove('doosearchas_s-fullscreen');
        }
    }

    // Shows loading spinner(s) and resets result elements during loading state
    loadingSpinner(){
        // Clear current result count, product list, and pagination UI
        document.getElementById('doosearchas_s-result-item-count').innerHTML = '';
        document.getElementById('doosearchas_s-result-item-list').innerHTML = '';
        document.getElementById('doosearchas_s-pagination').innerHTML = '';
        if(doosearchasConditionalBol3 === 'false'){
            if(doosearchasTurm7 != document.getElementById('doosearchas_s-secondary-input').value){
                doosearchasTurm7 = document.getElementById('doosearchas_s-secondary-input').value;
                document.querySelector('.doosearchas_s-spinnerSpan').classList.add('visible');
                document.querySelector('.doosearchas_s-spinnerSpan').innerHTML = '<div class="spinner-4"></div>';
                doosearchasConditionalBol3 = 'true';
            }else{
                // Show spinner 2 if search term hasn't changed
                document.querySelector('.doosearchas_s-spinnerSpan2').classList.add('visible');
                document.querySelector('.doosearchas_s-spinnerSpan2').innerHTML = '<div class="spinner-4"></div>';
                doosearchasConditionalBol3 = 'true';
                if(this.ConditionalStop !== 'stop'){
                   doosearchasConditionalStop = 'run';
                   doosearchasCurrentPage = 1; 
                }
            }
        }
    }
}

/**
 * Class: DooSearchas_Class_Controler
 * 
 * Controls the execution of the search and filter system.
 * Handles user interactions such as typing in the search bar or changing filter options (brand, price, category).
 * 
 * Called From:
 * - Inside a debounced input/change listener when user interacts with search or filters.
 */
class DooSearchas_Class_Controler {
    constructor(oldExecutionIdpara,searchTurmPara,targetNamePara,doosearchasCurrentPagePara,doosearchasConditionalStopPara) {
        this.searchTurm = searchTurmPara;
        this.targetName = targetNamePara;
        this.oldExecutionId = oldExecutionIdpara;
        this.crPage = doosearchasCurrentPagePara;
        this.ConStop = doosearchasConditionalStopPara;
        this.myRender();
    }
    async myRender(){
        if(this.searchTurm != ''){
            // Show loading spinner during search processing
            const doosearchasLoadingSpinner = new DooSearchas_Class_All(this.ConStop);
            doosearchasLoadingSpinner.loadingSpinner();

            // Handle 'price' filter
            if(this.targetName == 'price'){
                const minPrice = document.getElementById('doosearchas_s-minPriceText').value;
                const maxPrice = document.getElementById('doosearchas_s-maxPriceText').value;
                const minMax = [minPrice , maxPrice];
                doosearchasPrice1 = minMax[0] === ''?[]:minMax;
                doosearchasBrand = [];
                doosearchasCategory = [];
                doosearchasTransformedCategory = [];
            }else if(doosearchasTurm0 != this.searchTurm){
                // Reset price filter if search term changed
                doosearchasTurm0 = this.searchTurm;
                doosearchasPrice1 = [];
            }

            // Handle 'price2' filter
            if(this.targetName == 'price2'){
                const minPrice2 = document.getElementById('doosearchas_s-minPriceText2').value;
                const maxPrice2 = document.getElementById('doosearchas_s-maxPriceText2').value;
                const minMax2 = [minPrice2 , maxPrice2];
                doosearchasPrice2 = minMax2[0] === ''?[]:minMax2;
            }else if(doosearchasTurm6 != this.searchTurm){
                // Reset price2 filter if search term changed
                doosearchasTurm6 = this.searchTurm;
                doosearchasPrice2 = [];
            }

            // Handle 'brand' filter
            if(this.targetName == "brand"){
                doosearchasBrand = Array.from(document.querySelectorAll('input[name="brand"]:checked')).filter(checkbox => checkbox.value !== "").map(checkbox => checkbox.value);
                doosearchasCategory = [];
                doosearchasTransformedCategory = [];
            }else if(doosearchasTurm3 != this.searchTurm){
                // Reset brand filter if search term changed
                doosearchasTurm3 = this.searchTurm;
                doosearchasBrand = [];
            }

            // Handle 'category' filter
            if(this.targetName == "category"){
                doosearchasCategory = Array.from(document.querySelectorAll('input[name="category"]:checked')).filter(checkbox => checkbox.value !== "").map(checkbox => checkbox.value);
                doosearchasTransformedCategory = doosearchasCategory.map(item => {
                    // Replace commas with pipe for category transform
                    if (item.includes(',')) {
                        return item.replace(/, /g, '| ');
                    }
                    return item;
                });
            }else if(doosearchasTurm4 != this.searchTurm){
                // Reset category filter if search term changed
                doosearchasTurm4 = this.searchTurm;
                doosearchasCategory = [];
                doosearchasTransformedCategory = [];
            }

            // Decide which price filter to use
            let newPrice;
            if(this.targetName != 'price2'){
                doosearchasPrice2 = doosearchasPrice1;
            }
            if(doosearchasBrand.length != [].length || doosearchasCategory.length != [].length){
                newPrice = doosearchasPrice2;
            }else if(doosearchasBrand.length == [].length && doosearchasCategory.length == [].length ){
                newPrice = doosearchasPrice1;
            }

            // Build filter object for search request
            let filter = {
                'searchTurm': this.searchTurm,
                'searchField':doosearchas_func_setting_data().searchField,
                'brand':doosearchasBrand,
                'category':doosearchasTransformedCategory,
                'minPrice':newPrice.length === 0 ? '' : newPrice[0],
                'maxPrice':newPrice.length === 0 ? '' : newPrice[1],
            }
            const doosearchasSearch = new DooSearchas_Class_Search(this.oldExecutionId,filter,this.targetName,doosearchasBrand,doosearchasCategory,doosearchasPrice2,this.crPage);
        }
    }
}

// Listen for user input events (keyup, change, input) on the entire document
['keyup', 'change', 'input'].forEach(eventType => {
    document.addEventListener(eventType, (event) => {
        const doosearchasSecondaryInput = document.getElementById('doosearchas_s-secondary-input');
        let doosearchasNotEmpty;

        // Ignore navigation and enter keys to prevent premature search triggering
        if (event.key === 'Enter'||event.key === 'ArrowUp' || event.key === 'ArrowDown') {
            return;
        }

        // Check if the event target is the main input field
        if(event.target === doosearchasSecondaryInput){
            if(doosearchasConditionalBol1 === 'true'){
                doosearchasNotEmpty = doosearchasSecondaryInput.value != '';
                doosearchasConditionalBol1 = 'false' // Reset flag after first trigger
            }
        }

        // Trigger only if:
        // - Input is focused
        // - OR a checkbox or range input changed
        // - OR previously marked as not empty
        if (document.activeElement === doosearchasSecondaryInput || event.target.type === 'checkbox'|| event.target.type === 'range' || doosearchasNotEmpty) {
            const targetName = event.target.name;
            targetNameHold = targetName; // Store target name globally

            // Debounce the search trigger by 700ms to avoid too many calls
            clearTimeout(doosearchasClearTimeout);
            doosearchasClearTimeout = setTimeout(()=>{
                const oldExecutionId = ++currentExecutionId;

                // Reset state if input value changed since last time
                if(doosearchasTurm09 != doosearchasSecondaryInput.value){
                    doosearchasTurm09 = doosearchasSecondaryInput.value;
                    doosearchas_initialState()
                }

                doosearchasInputValue = doosearchasSecondaryInput.value;

                // Only initiate search if input has more than 2 characters
                if(doosearchasInputValue.length > 2){
                    const doosearchasSearch = new DooSearchas_Class_Controler(oldExecutionId,doosearchasInputValue,targetName);
                }
            },700);
        }
    });
});

function doosearchas_Func_change_page(page) {
    doosearchasCurrentPage = page;
    const oldExecutionId = ++currentExecutionId;
    doosearchasConditionalStop = 'stop';
    let targetNmae = targetNameHold;
    const doosearchasSearch = new DooSearchas_Class_Controler(oldExecutionId,document.getElementById('doosearchas_s-secondary-input').value,targetNmae,doosearchasCurrentPage,doosearchasConditionalStop);
    scrollToTop('doosearchas_s-result-item-wrapper');
    function scrollToTop(containerId = null) {
        if (containerId) {
            const container = document.getElementById(containerId);
            if (container) container.scrollTop = 0;
        } else {
            window.scrollTo({ top: 0, behavior: 'smooth' });
        }
    }
}

/**
 * Class: DooSearchas_Class_History
 *
 * Handles storing and managing search history using localStorage.
 * - Adds, deletes, and clears history items
 * - Renders history UI
 * - Persists to localStorage
 *
 * Called From:
 * - DooSearchas_Class_HistoryManager
 */
const doosearchasStateHistory = {}; // Global state object if needed elsewhere
class DooSearchas_Class_History {
    constructor() {
        this.historyList = []; // Store the search terms in an array
    }

    /**
     * Add a new search term to the history.
     * Prevents duplicates and re-renders the history.
     */
    async addItem(searchTerm){
        if (!this.historyList.includes(searchTerm)) {
            this.historyList.unshift(searchTerm);
            this.renderHistory();
        }
        this.persistDate();
    }

    //Remove a specific search term from the history.
    deleteItem(DeleteSearchTerm){
        const index = this.historyList.indexOf(DeleteSearchTerm);
        if (index > -1) {
            this.historyList.splice(index, 1);
            this.renderHistory();
        }
        this.persistDate();
    }

    //Clear all history items.
    clearAll(){
        if(this.historyList != []){
            this.historyList = [];
            this.renderHistory();
        }
        this.persistDate();
    }

    /**
     * Render the history items in the UI.
     * Adds each search term as a list item with remove button.
     */
    renderHistory() {
        const historyContainer = document.querySelector('.doosearchas_s-history-ul');
        historyContainer.innerHTML = '';  // Clear old items
        this.historyList.forEach(item => {
            const li = document.createElement('li');
            li.classList.add('doosearchas_s-history-li');

            // Create the inner HTML structure for history item
            li.innerHTML = `
                <div class="doosearchas_s-histroy-layout">
                    <div>
                        <span class="doosearchas_s-history-icon">
                            <div>
                                <img src="${doosearchasLocalizeFrontent.icons_url}history.svg" alt="History Icon" width="19" height="19" />
                            </div>
                        </span>
                        <span class="doosearchas_s-history-text">${item}</span>
                    </div>
                    <button class="doosearchas_s-history-remove">Remove</button>
                </div>
            `;
            historyContainer.appendChild(li);
        });
    }

    /**
     * Save the historyList array to localStorage.
     */
    persistDate() {
        localStorage.setItem('doosearchas-historyList-localStorage', JSON.stringify(this.historyList))
    }

    /**
     * Load the history list from localStorage (if available).
     * Re-renders the UI with restored data.
     */
    reStorData() {
        const storage = JSON.parse(localStorage.getItem('doosearchas-historyList-localStorage'));
        if(storage){
            this.historyList = storage;
            this.renderHistory();
        }
    }
}

/**
 * Class: DooSearchas_Class_HistoryManager
 *
 * Manages the user’s search history list:
 * - Adds search terms to history
 * - Handles restoring and clearing history
 *
 * Called From:
 * - DooSearchas_Class_Search after a successful search
 */
class DooSearchas_Class_HistoryManager {
    constructor() {
        this.inputEl = document.getElementById('doosearchas_s-secondary-input');
        this.historyUL = document.querySelector('.doosearchas_s-history-ul');
        this.clearAllBtn = document.querySelector('.doosearchas_s-clear-all');
        this.initialize();
    }
    initialize() {
        // On window load, make sure the history instance exists and restore stored history data
        window.addEventListener('load', () => {
            this.ensureHistoryInstance();
            doosearchasStateHistory.history.reStorData();
        });

        // Add click event listener to the history list for removing or selecting history items
        this.historyUL?.addEventListener('click', this.handleHistoryClick.bind(this));
        // Add click listener to the clear all button to clear history
        this.clearAllBtn?.addEventListener('click', this.handleClearAll.bind(this));
    }

    /**
     * Ensures the `doosearchasStateHistory.history` object exists
     * If not, it initializes a new DooSearchas_Class_History instance
     */
    ensureHistoryInstance() {
        if (!doosearchasStateHistory.history) {
            doosearchasStateHistory.history = new DooSearchas_Class_History();
        }
    }

    // Adds the current input value to the history list, with capitalized words
    addHistoryToList() {
        this.ensureHistoryInstance();
        function inFuncCapitalizeWords(str) {
            return str
                .split(' ')
                .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
                .join(' ');
        }
        doosearchasTurmHistroy = inFuncCapitalizeWords(this.inputEl.value);

        // Add to history only if length > 3 and input value has changed since last added
        if (
            doosearchasTurmHistroy.length > 3 &&
            doosearchasIsSame !== this.inputEl.value
        ) {
            doosearchasIsSame = this.inputEl.value;
            doosearchasStateHistory.history.addItem(doosearchasTurmHistroy);
        }
    }

    // Handles clicks on the history list, for either removing or selecting an item
    handleHistoryClick(event) {
        event.preventDefault();
        const removeBtn = event.target.closest('.doosearchas_s-history-remove');
        this.ensureHistoryInstance();
        if (removeBtn) {
            // If the remove button was clicked, delete the corresponding history item
            const historyText = removeBtn.closest('.doosearchas_s-histroy-layout')
                .querySelector('.doosearchas_s-history-text').textContent.trim();
            doosearchasStateHistory.history.deleteItem(historyText);
        } else {
            // Otherwise, if a history item was clicked, populate input with that term and trigger input event
            const historyLi = event.target.closest('.doosearchas_s-history-li');
            if (historyLi) {
                doosearchasConditionalBol1 = 'true';
                const historyText = historyLi.querySelector('.doosearchas_s-history-text').textContent.trim();
                this.inputEl.value = historyText;
                const inputEvent = new Event('input', { bubbles: true });
                this.inputEl.dispatchEvent(inputEvent);
            }
        }
    }

    // Clears all history on clear all button click
    handleClearAll(event) {
        event.preventDefault();
        this.ensureHistoryInstance();
        doosearchasStateHistory.history.clearAll();
    }
}

// Initialize the history manager after DOM content is loaded
document.addEventListener('DOMContentLoaded', () => {
    const historyManager = new DooSearchas_Class_HistoryManager();
});

/**
 * Class: DooSearchas_Class_Suggestions_Ajax
 * 
 * Fetches product titles from a custom REST API and caches them in localStorage (compressed) to improve performance.
 *
 * Called From:
 * - DOMContentLoaded listener (instantiation)
 */
let doosearchasProductTitleArray = []; // Global array to hold product titles used in suggestions.
class DooSearchas_Class_Suggestions_Ajax {
    constructor() {
        this.cacheKey = 'doosearchas-productTitles-localStorage';
        this.cacheTimeKey = 'doosearchas-productTitles-cache-time-localStorage';
        this.cacheTTL = 100 * 6 * 5; // Time-To-Live in ms (note: this is very short, about 3 seconds; maybe adjust to e.g. 3600000 for 1 hour)

        this.fetchAndCacheTitles(); // Start the fetching/caching process on initialization
    }

    /**
     * Fetches product titles from the REST API if cache is expired.
     * Otherwise, loads from localStorage cache.
     */
    async fetchAndCacheTitles() {
        try {
            const lastCacheTime = localStorage.getItem(this.cacheTimeKey);
            const now = Date.now();

            // If cache is fresh, load from cache and return
            if (lastCacheTime && now - lastCacheTime < this.cacheTTL) {
                this.loadTitlesFromCache();
                return;
            }

            // Fetching from REST API
            const per_page = 150;
            let page = 1;
            let totalPages = 1;
            const productTitles = [];

            // Loop through paginated results
            while (page <= totalPages) {
                const apiUrl = `${doosearchasLocalizeFrontent.root_url}/wp-json/dsas/v1/items?page=${page}&per_page=${per_page}`;
                const response = await fetch(apiUrl);
                const result = await response.json();

                // Validate response structure
                if (!result || !result.data || !Array.isArray(result.data.products)) {
                    console.warn(`No valid product data on page ${page}`);
                    break;
                }

                // Extract titles from response
                for (const product of result.data.products) {
                    try {
                        productTitles.push({ title: product.title });
                    } catch (e) {
                        console.warn("Skipping broken product item:", e, product);
                    }
                }

                // Set totalPages from pagination info (only once on page 1)
                if (page === 1 && result.pagination && result.pagination.total_pages) {
                    totalPages = parseInt(result.pagination.total_pages);
                }
                page++;
            }

            // Store in global array
            doosearchasProductTitleArray = productTitles;

            // Compress and save to localStorage
            const compressed = LZString.compress(JSON.stringify(productTitles));
            localStorage.setItem(this.cacheKey, compressed);
            localStorage.setItem(this.cacheTimeKey, now.toString());
        } catch (error) {
            console.error('Failed to fetch product titles:', error);
        }
    }

    /**
     * Loads product titles from localStorage cache.
     * Decompresses and sets global `doosearchasProductTitleArray`.
     */
    loadTitlesFromCache() {
        try {
            const compressed = localStorage.getItem(this.cacheKey);
            if (compressed) {
                const decompressed = LZString.decompress(compressed);
                const titles = JSON.parse(decompressed);
                doosearchasProductTitleArray = titles;
            }
        } catch (error) {
            console.error('Failed to load product titles from cache:', error);
        }
    }
}

// Initialize the history manager after DOM content is loaded
document.addEventListener('DOMContentLoaded', () => {
    const ssTitleAjax = new DooSearchas_Class_Suggestions_Ajax();
});

/**
 * Class: DooSearchas_Class_Suggestions
 * 
 * Handles search suggestions logic—filters titles, matches phrases, and renders suggestions with highlighting and keyboard navigation.
 *
 * Called From:
 * - DOMContentLoaded listener (instantiation)
 */
let doosearchasCurrentFocus = -1;
class DooSearchas_Class_Suggestions {
    constructor() {
        this.decompressed = this.loadData(); // Load product titles from localStorage (decompressed)

        // Default stop words to be ignored in keyword extraction
        this.defaultStopWords = new Set([
            'a', 'an', 'the', 'is', 'are', 'was', 'were', 'in', 'on', 'at', 'for',
            'with', 'there', 'here', 'where', 'by', 'of', 'to', 'and', 'or', 'as',
            'from', 'this', 'that', 'it', 'be', 'has', 'have'
        ]);

        // Dynamic stop words, priority keywords, and max suggestion count (loaded from plugin settings)
        this.stopWords = new Set(doosearchas_func_setting_data().suggestions[2]);
        this.prioritySuggestions = new Set(doosearchas_func_setting_data().suggestions[1]);
        this.suggestionCount = doosearchas_func_setting_data().suggestions[0];

        this.init(); // Initialize event handlers
    }

    /**
     * Load compressed product title data from localStorage.
     * Also calculates and logs data size (useful for debugging).
     */
    loadData() {
        const stored = localStorage.getItem('doosearchas-productTitles-localStorage');
        const decompressed = stored ? JSON.parse(LZString.decompress(stored)) : [];
        const jsonString = JSON.stringify(decompressed);
        const sizeInBytes = new TextEncoder().encode(jsonString).length;
        const sizeInKB = (sizeInBytes / 1024).toFixed(2);
        return decompressed;
    }

    /**
     * Checks whether a word looks like a model number/code.
     */
    isModelCode(word) {
        return /^[A-Z0-9-]{3,}$/.test(word);
    }

    /**
     * Clean and split a block of text into filtered keywords.
     */
    cleanAndSplitBlock(block) {
        return block
            .replace(/\d+&quot;/g, '')   // remove quoted numbers
            .replace(/\d+\"/g, '')       // remove raw double-quoted numbers
            .replace(/\s*\(.*?\)/g, '')  // remove parenthesis content
            .replace(/[^\w\- ]/g, '')    // remove non-alphanumerics except hyphens
            .toLowerCase()
            .split(/\s+/)                // split into words
            .filter(word =>
                word &&
                !this.defaultStopWords.has(word) &&
                !this.stopWords.has(word) &&
                !this.isModelCode(word)
            );
    }

    /**
     * Generate 1-word, 2-word, and 3-word phrases from words.
     */
    generatePhrases(words) {
        const result = new Set();
        for (let i = 0; i < words.length; i++) {
            result.add(words[i]);
            if (i + 1 < words.length) result.add(`${words[i]} ${words[i + 1]}`);
            if (i + 2 < words.length) result.add(`${words[i]} ${words[i + 1]} ${words[i + 2]}`);
        }
        return result;
    }

    /**
     * Split a title into segments (comma-separated blocks), clean them, and extract phrases.
     */
    getSegments(title) {
        const blocks = title.split(',');
        const finalResult = new Set();
        for (let block of blocks) {
            const words = this.cleanAndSplitBlock(block);
            const phrases = this.generatePhrases(words);
            phrases.forEach(p => finalResult.add(p));
        }
        return Array.from(finalResult);
    }

    /**
     * Simple fuzzy match: all characters of `term` must appear in order in `str`.
     */
    fuzzyMatch(term, str) {
        const cleanTerm = term.replace(/[^a-zA-Z0-9]/g, ''); // remove anything not a-z or 0-9
        const regex = new RegExp(cleanTerm.split('').join('.*?'), 'i');
        return regex.test(str);
    }

    /**
     * Levenshtein distance (edit distance) between two strings.
     * Helps in typo-tolerant matching.
     */
    levenshtein(a, b) {
        const dp = Array.from({ length: a.length + 1 }, () => Array(b.length + 1).fill(0));
        for (let i = 0; i <= a.length; i++) dp[i][0] = i;
        for (let j = 0; j <= b.length; j++) dp[0][j] = j;
        for (let i = 1; i <= a.length; i++) {
            for (let j = 1; j <= b.length; j++) {
                if (a[i - 1] === b[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    dp[i][j] = 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);
                }
            }
        }
        return dp[a.length][b.length];
    }

    /**
     * Filters the decompressed product titles using fuzzy match and typo correction.
     */
    filterProducts(searchTerm) {
        if (!searchTerm) return [];
        return this.decompressed.filter(product =>
            this.fuzzyMatch(searchTerm, product.title) ||
            this.levenshtein(searchTerm.toLowerCase(), product.title.toLowerCase()) <= 2
        );
    }

    /**
     * Stores recent search logs in localStorage (up to 100 entries).
     */
    logSearch(term, selectedSuggestion) {
        const maxLogs = 100;
        const logs = JSON.parse(localStorage.getItem('doosearchas_search-logs-localStorage') || '[]');
        logs.push({ time: new Date().toISOString(), term, selected: selectedSuggestion });
        if (logs.length > maxLogs) logs.splice(0, logs.length - maxLogs);
        localStorage.setItem('doosearchas_search-logs-localStorage', JSON.stringify(logs));
    }

    /**
     * Display the filtered keyword suggestions in the DOM.
     */
    displaySuggestions(suggestions, searchTerm) {
        const suggestionsBox = document.getElementById('doosearchas_s-suggestions');
        suggestionsBox.innerHTML = '';
        const uniqueSuggestions = new Set();
        let matchingSegments = [];

        // Extract keyword segments from product titles
        suggestions.forEach(product => {
            const segments = this.getSegments(product.title);
            segments.forEach(segment => {
                if (segment.toLowerCase().includes(searchTerm.toLowerCase()) && !uniqueSuggestions.has(segment.toLowerCase())) {
                    uniqueSuggestions.add(segment.toLowerCase());
                    matchingSegments.push(segment);
                }
            });
        });

        // Sort priority vs normal matches
        const priorityMatches = [];
        const normalMatches = [];
        matchingSegments.forEach(segment => {
            if (this.prioritySuggestions.has(segment.toLowerCase())) {
                priorityMatches.push(segment);
            } else {
                normalMatches.push(segment);
            }
        });

        // Sort by length for better UX (shorter suggestions appear first)
        priorityMatches.sort((a, b) => a.length - b.length);
        normalMatches.sort((a, b) => a.length - b.length);
        const sortedSegments = [...priorityMatches, ...normalMatches];

        // Display top N suggestions
        sortedSegments.slice(0, this.suggestionCount).forEach((segment, index) => {
            const div = document.createElement('div');
            div.classList.add('doosearchas_s-suggestion-item');
            div.setAttribute('data-index', index);

            // Highlight matched term
            const highlightedSegment = segment.replace(new RegExp(`(${searchTerm})`, 'gi'), '<strong>$1</strong>');

            // On click, trigger search with the selected suggestion
            div.innerHTML = highlightedSegment;
            div.addEventListener('click', () => {
                document.getElementById('doosearchas_s-secondary-input').value = segment;
                suggestionsBox.style.display = 'none';
                doosearchasCurrentFocus = -1;
                this.logSearch(searchTerm, segment);
                clearTimeout(doosearchasClearTimeout3);
                doosearchasClearTimeout3 = setTimeout(() => {
                    const oldExecutionId = ++currentExecutionId;
                    const targetName = '';
                    doosearchas_initialState();
                    doosearchasTurm09 = segment;
                    const doosearchasSearch = new DooSearchas_Class_Controler(oldExecutionId,document.getElementById('doosearchas_s-secondary-input').value, targetName);
                }, 700);
            });
            suggestionsBox.appendChild(div);
        });
        suggestionsBox.style.display = matchingSegments.length > 0 ? 'block' : 'none';
    }

    /**
     * Highlights the currently active suggestion (keyboard navigation).
     */
    setActive(items) {
        items.forEach(item => item.classList.remove('doosearchas_s-active'));
        if (doosearchasCurrentFocus >= 0 && doosearchasCurrentFocus < items.length) {
            const activeItem = items[doosearchasCurrentFocus];
            activeItem.classList.add('doosearchas_s-active');

            // Auto-scroll into view
            const container = document.getElementById('doosearchas_s-suggestions');
            const itemTop = activeItem.offsetTop;
            const itemBottom = itemTop + activeItem.offsetHeight;
            const containerTop = container.scrollTop;
            const containerBottom = containerTop + container.offsetHeight;
            if (itemTop < containerTop) {
                container.scrollTop = itemTop;
            } else if (itemBottom > containerBottom) {
                container.scrollTop = itemBottom - container.offsetHeight;
            }
        }
    }

    /**
     * Initializes event listeners for input, keydown (keyboard nav), and outside click.
     */
    init() {
        const debouncedInputHandler = this.debounce(() => {
            const searchTerm = document.getElementById('doosearchas_s-secondary-input').value.trim();
            const suggestions = this.filterProducts(searchTerm);
            this.displaySuggestions(suggestions, searchTerm);
        }, 300);
        document.getElementById('doosearchas_s-secondary-input').addEventListener('input', debouncedInputHandler);
        document.getElementById('doosearchas_s-secondary-input').addEventListener('keydown', (e) => {
            const items = document.querySelectorAll('.doosearchas_s-suggestion-item');
            if (!items.length) return;
            if (e.key === 'ArrowDown') {
                doosearchasCurrentFocus = (doosearchasCurrentFocus + 1) % items.length;
                this.setActive(items);
                e.preventDefault();
            } else if (e.key === 'ArrowUp') {
                doosearchasCurrentFocus = (doosearchasCurrentFocus - 1 + items.length) % items.length;
                this.setActive(items);
                e.preventDefault();
            } else if (e.key === 'Enter') {
                e.preventDefault();
                if (doosearchasCurrentFocus > -1 && items[doosearchasCurrentFocus]) {
                    items[doosearchasCurrentFocus].click();
                }
            }
        });

        // Hide suggestions if clicked outside
        document.addEventListener('click', (event) => {
            const suggestionsBox = document.getElementById('doosearchas_s-suggestions');
            const searchInput = document.getElementById('doosearchas_s-secondary-input');
            if (!searchInput.contains(event.target) && !suggestionsBox.contains(event.target)) {
                suggestionsBox.style.display = 'none';
            }
        });
    }

    /**
     * Utility: debounce wrapper to prevent too frequent function calls.
     */
    debounce(func, delay) {
        let timeout;
        return function (...args) {
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(this, args), delay);
        };
    }
}

// Initialize the history manager after DOM content is loaded
document.addEventListener('DOMContentLoaded', () => {
    const doosearchasSuggestions = new DooSearchas_Class_Suggestions();
});

/**
 * Class: DooSearchas_Class_Cart
 * Description:
 *   Handles the frontend cart functionality for the DooSearch plugin.
 *   - Listens for "Add to Cart" clicks in search results.
 *   - Makes AJAX requests to WooCommerce backend to add/update/remove cart items.
 *   - Updates the cart popup UI dynamically (item count, total price, items).
 *   - Animates add-to-cart icons and handles quantity changes.
 *   - Manages cart popup visibility and interaction events.
 *
 * Dependencies:
 *   - jQuery (used for `jQuery(document.body).trigger`)
 *   - WooCommerce AJAX endpoints via `doosearchasLocalizeFrontent.ajax_url`
 *   - HTML structure with specific IDs and classes (e.g. `#doosearchas_s-cart-icon`, `.doosearchas_s-cart-item`)
 *
 * Usage:
 *   Instantiated automatically on DOMContentLoaded.
 */
class DooSearchas_Class_Cart {
    constructor() {
        // Wait for the DOM to be fully loaded before initializing event listeners and updating cart info
        document.addEventListener('DOMContentLoaded', () => {
            this.setupEventListeners();
            this.updateCartInfo();
            this.setupCartPopupEvents();
        });
    }

    /**
     * Set up event listener for "Add to Cart" buttons inside the search results
     */
    setupEventListeners() {
        const resultItemWrapper = document.querySelector('#doosearchas_s-result-item-list');
        if (resultItemWrapper) {
            resultItemWrapper.addEventListener('click', (event) => {
                const addToCartBtn = event.target.closest('.doosearchas_s-add-to-cart');
                if (addToCartBtn) {
                    event.preventDefault();
                    const productId = addToCartBtn.getAttribute('data-goto-product-id');
                    this.animateAddIcon(productId);
                    this.addToCart(productId);
                }
            });
        }
    }

    /**
     * Set up event listeners related to the cart popup behavior:
     * - Opening popup on cart icon click
     * - Closing popup on close button click or clicking outside
     */
    setupCartPopupEvents() {
        const ssDocCartIcon = document.getElementById('doosearchas_s-cart-icon');
        const ssDocCartPopup = document.getElementById('doosearchas_s-cart-popup');
        const ssDocPopupClose = document.getElementById('doosearchas_s-cart-popup-close');
        if (!ssDocCartIcon || !ssDocCartPopup || !ssDocPopupClose) return;
        ssDocCartIcon.addEventListener('click', function(event) {
            event.preventDefault();
            ssDocCartPopup.classList.add('active'); // Show the cart popup
        });
        ssDocPopupClose.addEventListener('click', function() {
            ssDocCartPopup.classList.remove('active'); // Hide the cart popup
        });

        // Hide popup if clicking outside cart icon or popup
        document.addEventListener('click', function(event) {
            if (!ssDocCartIcon.contains(event.target) && !ssDocCartPopup.contains(event.target)) {
                ssDocCartPopup.classList.remove('active');
            }
        });
    }

    /**
     * Add animation class to the add-to-cart icon for the specified product ID
     */
    animateAddIcon(productId) {
        const icon = document.getElementById(`doosearchas_s-icon-add-to-cart-${productId}`);
        if (icon) {
            icon.classList.add('doosearchas-animation-icon');
        }
    }

    /**
     * Stop animation on add-to-cart icon and show success message on the product item
     */
    stopAddIconAnimation(productId) {
        const icon = document.getElementById(`doosearchas_s-icon-add-to-cart-${productId}`);
        const viewCart = document.getElementById(`doosearchas_s-view-cart-${productId}`);
        if(viewCart){
            viewCart.style.zIndex = '2'; // Bring "View Cart" button above other elements
        }
        if (icon) {
            icon.classList.remove('doosearchas-animation-icon'); // Disable item to prevent double clicks
        }
        const itemWrapper = icon.closest('.doosearchas_s-result-item');
        if (!itemWrapper) return;
        itemWrapper.classList.add('doosearchas-item-disabled');
        const successMsg = document.createElement('div');

        // Create and display "Added to cart" message
        successMsg.className = 'doosearchas-cart-success-msg';
        successMsg.innerText = 'Added to cart';
        itemWrapper.appendChild(successMsg);

        // Remove success message and re-enable item after 3 seconds
        setTimeout(() => {
            successMsg.remove();
            itemWrapper.classList.remove('doosearchas-item-disabled');
        }, 3000);
    }

    /**
     * Send AJAX request to add a product to the cart by product ID
     */
    addToCart(productId) {
        fetch(doosearchasLocalizeFrontent.ajax_url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            body: `action=doosearchas_cb_add_to_cart&product_id=${productId}&nonce=${doosearchasLocalizeFrontent.nonce}`
        })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                this.updateCartInfo(productId);
            }
        })
        .catch(error => console.error('Error:', error));
    }

    /**
     * Fetch and update cart info display: item count, total price, and list of items
     * Optionally stops add-to-cart animation for a product just added
     */
    updateCartInfo(productId = null) {
        fetch(`${doosearchasLocalizeFrontent.ajax_url}?action=doosearchas_cb_get_cart_info&nonce=${doosearchasLocalizeFrontent.nonce}`)
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                // Trigger WooCommerce event to update cart fragments
                jQuery(document.body).trigger('added_to_cart');

                // Update cart icon count and style
                const countElem = document.querySelector('.doosearchas_s-cart-item-count');
                const priceElem = document.querySelector('.doosearchas_s-cart-item-total-price');
                const cartWrapper = document.getElementById('doosearchas_s-cart-item-wrapper');
                const emptyCartWrapper = document.querySelector('.doosearchas_s-empty-cart-wrapper');
                countElem.innerText = data.cart_count;
                countElem.classList.toggle('doosearchas-cart-not-empty', data.cart_count > 0);
                countElem.classList.toggle('doosearchas-cart-empty', data.cart_count <= 0);
                priceElem.innerHTML = `Total: ${data.cart_total}`;

                // Clear current cart items and update with fresh data
                cartWrapper.innerHTML = '';
                if (emptyCartWrapper) {
                    emptyCartWrapper.style.display = (data.cart_items.length !== 0) ? 'none' : 'block';
                }

                // Render each cart item
                data.cart_items.forEach(item => {
                    const itemHTML = `
                        <div class="doosearchas_s-cart-item" data-goto-cart-item-key="${item.key}">
                            ${item.image_html}
                            <div class="doosearchas_s-cart-item-details">
                                <h4>${item.name}</h4>
                                <span class="doosearchas_s-cart-item-price">${item.price}</span>
                                <div class="doosearchas_s-quantity-controls" id="doosearchas_s-quantity-controls-${item.key}">
                                    <button class="doosearchas_s-decrease-quantity" data-goto-cart-item-key="${item.key}">-</button>
                                    <input type="number" class="doosearchas_s-quantity-input" value="${item.quantity}" min="1" readonly>
                                    <button class="doosearchas_s-increase-quantity" data-goto-cart-item-key="${item.key}">+</button>
                                </div>
                            </div>
                            <button class="doosearchas_s-remove-cart-item" id="doosearchas_s-remove-cart-item-${item.key}" data-goto-product-id="${item.product_id}" data-goto-cart-item-key="${item.key}">
                                <div>
                                    <img src="${doosearchasLocalizeFrontent.icons_url}delete.svg" alt="Remove item icon" width="24" height="24" />
                                </div>
                            </button>
                        </div>`;
                    cartWrapper.innerHTML += itemHTML;
                });

                // Stop add-to-cart animation for the product just added (if any)
                if (productId) this.stopAddIconAnimation(productId);

                // Attach event listeners for quantity controls and remove buttons
                this.attachCartItemEventListeners();
            }
        })
        .catch(error => console.error('Error fetching cart info:', error));
    }

    /**
     * Attach event listeners to dynamically generated cart item buttons:
     * - Increase quantity
     * - Decrease quantity
     * - Remove item
     */
    attachCartItemEventListeners() {
        // Increase quantity buttons
        document.querySelectorAll('.doosearchas_s-increase-quantity').forEach(button => {
            button.addEventListener('click', () => {
                const key = button.getAttribute('data-goto-cart-item-key');
                this.updateCartQuantity(key, 1);
            });
        });

        // Decrease quantity buttons
        document.querySelectorAll('.doosearchas_s-decrease-quantity').forEach(button => {
            button.addEventListener('click', () => {
                const key = button.getAttribute('data-goto-cart-item-key');
                const input = button.nextElementSibling;
                if (parseInt(input.value) > 1) {
                    this.updateCartQuantity(key, -1);
                }
            });
        });

        // Remove item buttons
        document.querySelectorAll('.doosearchas_s-remove-cart-item').forEach(button => {
            button.addEventListener('click', () => {
                const key = button.getAttribute('data-goto-cart-item-key');
                const id = button.getAttribute('data-goto-product-id');
                this.removeCartItem(key,id);
            });
        });
    }

    /**
     * Update cart item quantity by sending AJAX request with the new quantity
     */
    updateCartQuantity(cartItemKey, quantityChange) {
        const input = document.querySelector(`[data-goto-cart-item-key="${cartItemKey}"] .doosearchas_s-quantity-input`);
        const currentQty = parseInt(input.value);
        const newQty = currentQty + quantityChange;

        // Disable quantity control buttons temporarily while updating
        const controlWrapper = document.getElementById(`doosearchas_s-quantity-controls-${cartItemKey}`);
        if (controlWrapper) controlWrapper.classList.add('doosearchas-disabled');
        fetch(doosearchasLocalizeFrontent.ajax_url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            body: `action=doosearchas_cb_update_cart_quantity&cart_item_key=${cartItemKey}&quantity=${newQty}&nonce=${doosearchasLocalizeFrontent.nonce}`
        })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                input.value = newQty;
                this.updateCartInfo();
            } else {
                alert('Could not update cart. Please try again.');
            }
        });
    }

    /**
     * Remove a cart item by key, send AJAX request, and update cart UI
     */
    removeCartItem(cartItemKey,cartItemId) {
        const removeButton = document.getElementById(`doosearchas_s-remove-cart-item-${cartItemKey}`);
        if (removeButton) {
            removeButton.classList.add('doosearchas-delete-animation');
        }
        fetch(doosearchasLocalizeFrontent.ajax_url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            body: `action=doosearchas_cb_remove_cart_item&cart_item_key=${cartItemKey}&nonce=${doosearchasLocalizeFrontent.nonce}`
        })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                this.updateCartInfo();
                        // Reset z-index for the "View Cart" button related to removed item
                        const viewCart = document.getElementById(`doosearchas_s-view-cart-${cartItemId}`);
                        if(viewCart){
                            viewCart.style.zIndex = '-1';
                        }
            }
        })
        .catch(error => console.error('Error removing cart item:', error));
    }
}

// Instantiate cart handler
const doosearchasCart = new DooSearchas_Class_Cart();

