/*
 * Copyright 2025 Criptomart
 * License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
 */

(function () {
    "use strict";

    window.realtimeSearch = {
        searchInput: null,
        categorySelect: null,
        allProducts: [],
        debounceTimer: null,
        debounceDelay: 0,
        categoryHierarchy: {}, // Maps parent category IDs to their children
        selectedTags: new Set(), // Set of selected tag IDs (for OR logic filtering)
        availableTags: {}, // Maps tag ID to {id, name, count}

        init: function () {
            console.log("[realtimeSearch] Initializing...");

            // searchInput y categorySelect ya fueron asignados por tryInit()
            console.log("[realtimeSearch] Search input:", this.searchInput);
            console.log("[realtimeSearch] Category select:", this.categorySelect);

            if (!this.searchInput) {
                console.error("[realtimeSearch] ERROR: Search input not found!");
                return false;
            }

            if (!this.categorySelect) {
                console.error("[realtimeSearch] ERROR: Category select not found!");
                return false;
            }

            this._buildCategoryHierarchyFromDOM();
            this._storeAllProducts();
            console.log(
                "[realtimeSearch] After _storeAllProducts(), calling _attachEventListeners()..."
            );
            this._attachEventListeners();
            console.log("[realtimeSearch] ✓ Initialized successfully");
            return true;
        },

        _buildCategoryHierarchyFromDOM: function () {
            /**
             * Construye un mapa de jerarquía de categorías desde las opciones del select.
             * Ahora todas las opciones son planas pero con indentación visual (↳ arrows).
             *
             * La profundidad se determina contando el número de arrows (↳).
             * Estructura: categoryHierarchy[parentCategoryId] = [childCategoryId1, childCategoryId2, ...]
             */
            var self = this;
            var allOptions = this.categorySelect.querySelectorAll("option[value]");
            var optionStack = []; // Stack para mantener los padres en cada nivel

            allOptions.forEach(function (option) {
                var categoryId = option.getAttribute("value");
                var text = option.textContent;

                // Contar arrows para determinar profundidad
                var arrowCount = (text.match(/↳/g) || []).length;
                var depth = arrowCount; // Depth: 0 for roots, 1 for children, 2 for grandchildren, etc.

                // Ajustar el stack al nivel actual
                // Si la profundidad es menor o igual, sacamos elementos del stack
                while (optionStack.length > depth) {
                    optionStack.pop();
                }

                // Si hay un padre en el stack (profundidad > 0), agregar como hijo
                if (depth > 0 && optionStack.length > 0) {
                    var parentId = optionStack[optionStack.length - 1];
                    if (!self.categoryHierarchy[parentId]) {
                        self.categoryHierarchy[parentId] = [];
                    }
                    if (!self.categoryHierarchy[parentId].includes(categoryId)) {
                        self.categoryHierarchy[parentId].push(categoryId);
                    }
                }

                // Agregar este ID al stack como posible padre para los siguientes
                // Adjust position in stack based on depth
                if (optionStack.length > depth) {
                    optionStack[depth] = categoryId;
                } else {
                    optionStack.push(categoryId);
                }
            });

            console.log(
                "[realtimeSearch] Complete category hierarchy built:",
                self.categoryHierarchy
            );
        },

        _storeAllProducts: function () {
            var productCards = document.querySelectorAll(".product-card");
            console.log("[realtimeSearch] Found " + productCards.length + " product cards");

            var self = this;
            this.allProducts = [];

            productCards.forEach(function (card, index) {
                var name = card.getAttribute("data-product-name") || "";
                var categoryId = card.getAttribute("data-category-id") || "";
                var tagIdsStr = card.getAttribute("data-product-tags") || "";

                // Parse tag IDs from comma-separated string
                var tagIds = [];
                if (tagIdsStr) {
                    tagIds = tagIdsStr
                        .split(",")
                        .map(function (id) {
                            return parseInt(id.trim(), 10);
                        })
                        .filter(function (id) {
                            return !isNaN(id);
                        });
                }

                self.allProducts.push({
                    element: card,
                    name: name.toLowerCase(),
                    category: categoryId.toString(),
                    originalCategory: categoryId,
                    tags: tagIds, // Array of tag IDs for this product
                });
            });

            console.log("[realtimeSearch] Total products stored: " + this.allProducts.length);
        },

        _attachEventListeners: function () {
            var self = this;

            // Flag to prevent filtering during initialization
            self.isInitializing = true;

            // Initialize available tags from DOM
            self._initializeAvailableTags();

            // Store original colors for each tag badge
            self.originalTagColors = {}; // Maps tag ID to original color

            // Store last values at instance level so polling can access them
            // Initialize to current values to avoid triggering reset on first poll
            self.lastSearchValue = self.searchInput.value.trim();
            self.lastCategoryValue = self.categorySelect.value;

            console.log(
                "[realtimeSearch] Initial values stored - search:",
                JSON.stringify(self.lastSearchValue),
                "category:",
                JSON.stringify(self.lastCategoryValue)
            );

            // Clear search button
            self.clearSearchBtn = document.getElementById("clear-search-btn");
            if (self.clearSearchBtn) {
                console.log("[realtimeSearch] Clear search button found, attaching listeners");

                // Show/hide button based on input content (passive, no filtering)
                // This listener is separate from the filtering listener
                self.searchInput.addEventListener("input", function () {
                    if (self.searchInput.value.trim().length > 0) {
                        self.clearSearchBtn.style.display = "block";
                    } else {
                        self.clearSearchBtn.style.display = "none";
                    }
                });

                // Clear search when button clicked
                self.clearSearchBtn.addEventListener("click", function (e) {
                    e.preventDefault();
                    e.stopPropagation();
                    console.log("[realtimeSearch] Clear search button clicked");

                    // Clear the input
                    self.searchInput.value = "";
                    self.clearSearchBtn.style.display = "none";

                    // Update last stored value to prevent polling from detecting "change"
                    self.lastSearchValue = "";

                    // Reset infinite scroll to reload all products from server
                    if (
                        window.infiniteScroll &&
                        typeof window.infiniteScroll.resetWithFilters === "function"
                    ) {
                        console.log(
                            "[realtimeSearch] Resetting infinite scroll to show all products"
                        );
                        window.infiniteScroll.resetWithFilters("", self.lastCategoryValue);
                    } else if (!self.isInitializing) {
                        // Fallback: filter locally
                        self._filterProducts();
                    }

                    // Focus back to search input
                    self.searchInput.focus();
                });

                // Initial check - don't show if empty
                if (self.searchInput.value.trim().length > 0) {
                    self.clearSearchBtn.style.display = "block";
                }
            }

            // Prevent form submission completely
            var form = self.searchInput.closest("form");
            if (form) {
                form.addEventListener("submit", function (e) {
                    e.preventDefault();
                    e.stopPropagation();
                    console.log("[realtimeSearch] Form submission prevented and stopped");
                    return false;
                });
            }

            // Prevent Enter key from submitting
            self.searchInput.addEventListener("keypress", function (e) {
                if (e.key === "Enter") {
                    e.preventDefault();
                    e.stopPropagation();
                    console.log("[realtimeSearch] Enter key prevented on search input");
                    return false;
                }
            });

            // Search input: listen to 'input' for real-time filtering
            self.searchInput.addEventListener("input", function (e) {
                try {
                    // Skip filtering during initialization
                    if (self.isInitializing) {
                        console.log("[realtimeSearch] INPUT event during init - skipping filter");
                        return;
                    }
                    console.log('[realtimeSearch] INPUT event - value: "' + e.target.value + '"');
                    self._filterProducts();
                } catch (error) {
                    console.error("[realtimeSearch] Error in input listener:", error.message);
                }
            });

            // Also keep 'keyup' for extra compatibility
            self.searchInput.addEventListener("keyup", function (e) {
                try {
                    // Skip filtering during initialization
                    if (self.isInitializing) {
                        console.log("[realtimeSearch] KEYUP event during init - skipping filter");
                        return;
                    }
                    console.log('[realtimeSearch] KEYUP event - value: "' + e.target.value + '"');
                    self._filterProducts();
                } catch (error) {
                    console.error("[realtimeSearch] Error in keyup listener:", error.message);
                }
            });

            // Category select
            self.categorySelect.addEventListener("change", function (e) {
                try {
                    // Skip filtering during initialization
                    if (self.isInitializing) {
                        console.log("[realtimeSearch] CHANGE event during init - skipping filter");
                        return;
                    }
                    console.log(
                        '[realtimeSearch] CHANGE event - selected: "' + e.target.value + '"'
                    );
                    self._filterProducts();
                } catch (error) {
                    console.error(
                        "[realtimeSearch] Error in category change listener:",
                        error.message
                    );
                }
            });

            // Tag filter badges: click to toggle selection (independent state)
            var tagBadges = document.querySelectorAll('[data-toggle="tag-filter"]');
            console.log("[realtimeSearch] Found " + tagBadges.length + " tag filter badges");

            // Get theme colors from CSS variables
            var rootStyles = getComputedStyle(document.documentElement);
            var primaryColor =
                rootStyles.getPropertyValue("--bs-primary").trim() ||
                rootStyles.getPropertyValue("--primary").trim() ||
                "#0d6efd";
            var secondaryColor =
                rootStyles.getPropertyValue("--bs-secondary").trim() ||
                rootStyles.getPropertyValue("--secondary").trim() ||
                "#6c757d";

            console.log(
                "[realtimeSearch] Theme colors - Primary:",
                primaryColor,
                "Secondary:",
                secondaryColor
            );

            // Store original colors for each badge BEFORE adding event listeners
            tagBadges.forEach(function (badge) {
                var tagId = parseInt(badge.getAttribute("data-tag-id"), 10);
                var tagColor = badge.getAttribute("data-tag-color");

                // Store the original color (either from data-tag-color or use secondary for tags without color)
                if (tagColor) {
                    self.originalTagColors[tagId] = tagColor;
                    console.log(
                        "[realtimeSearch] Stored original color for tag " + tagId + ": " + tagColor
                    );
                } else {
                    self.originalTagColors[tagId] = "var(--bs-secondary, " + secondaryColor + ")";
                    console.log("[realtimeSearch] Tag " + tagId + " has no color, using secondary");
                }
            });

            tagBadges.forEach(function (badge) {
                badge.addEventListener("click", function (e) {
                    e.preventDefault();
                    var tagId = parseInt(badge.getAttribute("data-tag-id"), 10);
                    var originalColor = self.originalTagColors[tagId];
                    console.log(
                        "[realtimeSearch] Tag badge clicked: " +
                            tagId +
                            " (original color: " +
                            originalColor +
                            ")"
                    );

                    // Toggle tag selection
                    if (self.selectedTags.has(tagId)) {
                        // Deselect
                        self.selectedTags.delete(tagId);
                        console.log("[realtimeSearch] Tag " + tagId + " deselected");
                    } else {
                        // Select
                        self.selectedTags.add(tagId);
                        console.log("[realtimeSearch] Tag " + tagId + " selected");
                    }

                    // Update colors for ALL badges based on selection state
                    tagBadges.forEach(function (badge) {
                        var id = parseInt(badge.getAttribute("data-tag-id"), 10);

                        if (self.selectedTags.size === 0) {
                            // No tags selected: restore all to original colors
                            var originalColor = self.originalTagColors[id];
                            badge.style.setProperty("background-color", originalColor, "important");
                            badge.style.setProperty("border-color", originalColor, "important");
                            badge.style.setProperty("color", "#ffffff", "important");
                            console.log(
                                "[realtimeSearch] Badge " +
                                    id +
                                    " reset to original color (no selection)"
                            );
                        } else if (self.selectedTags.has(id)) {
                            // Selected: primary color
                            badge.style.setProperty(
                                "background-color",
                                "var(--bs-primary, " + primaryColor + ")",
                                "important"
                            );
                            badge.style.setProperty(
                                "border-color",
                                "var(--bs-primary, " + primaryColor + ")",
                                "important"
                            );
                            badge.style.setProperty("color", "#ffffff", "important");
                            console.log(
                                "[realtimeSearch] Badge " + id + " set to primary (selected)"
                            );
                        } else {
                            // Not selected but others are: secondary color
                            badge.style.setProperty(
                                "background-color",
                                "var(--bs-secondary, " + secondaryColor + ")",
                                "important"
                            );
                            badge.style.setProperty(
                                "border-color",
                                "var(--bs-secondary, " + secondaryColor + ")",
                                "important"
                            );
                            badge.style.setProperty("color", "#ffffff", "important");
                            console.log(
                                "[realtimeSearch] Badge " + id + " set to secondary (not selected)"
                            );
                        }
                    });

                    // Filter products (independent of search/category state)
                    // Skip during initialization
                    if (!self.isInitializing) {
                        self._filterProducts();
                    }
                });
            });

            // POLLING FALLBACK: Since Odoo components may intercept events,
            // use polling to detect value changes
            console.log("[realtimeSearch] 🚀 POLLING INITIALIZATION STARTING");
            console.log("[realtimeSearch] Search input element:", self.searchInput);
            console.log("[realtimeSearch] Category select element:", self.categorySelect);

            var pollingCounter = 0;
            var pollInterval = setInterval(function () {
                try {
                    // Skip polling during initialization to avoid clearing products
                    if (self.isInitializing) {
                        return;
                    }

                    pollingCounter++;

                    // Try multiple ways to get the search value
                    var currentSearchValue = self.searchInput.value || "";
                    var currentSearchAttr = self.searchInput.getAttribute("value") || "";
                    var currentSearchDataValue = self.searchInput.getAttribute("data-value") || "";
                    var currentSearchInnerText = self.searchInput.innerText || "";

                    var currentCategoryValue = self.categorySelect
                        ? self.categorySelect.value || ""
                        : "";

                    // FIRST POLL: Detailed debug
                    if (pollingCounter === 1) {
                        console.log("═══════════════════════════════════════════");
                        console.log("[realtimeSearch] 🔍 FIRST POLLING DEBUG (POLL #1)");
                        console.log("═══════════════════════════════════════════");
                        console.log("Search input .value:", JSON.stringify(currentSearchValue));
                        console.log(
                            'Search input getAttribute("value"):',
                            JSON.stringify(currentSearchAttr)
                        );
                        console.log(
                            'Search input getAttribute("data-value"):',
                            JSON.stringify(currentSearchDataValue)
                        );
                        console.log(
                            "Search input innerText:",
                            JSON.stringify(currentSearchInnerText)
                        );
                        console.log(
                            "Category select .value:",
                            JSON.stringify(currentCategoryValue)
                        );
                        console.log(
                            'Last stored values - search:"' +
                                self.lastSearchValue +
                                '" category:"' +
                                self.lastCategoryValue +
                                '"'
                        );
                        console.log("═══════════════════════════════════════════");
                    }

                    // Log every 20 polls (reduce spam)
                    if (pollingCounter % 20 === 0) {
                        console.log(
                            "[realtimeSearch] POLLING #" +
                                pollingCounter +
                                ': search="' +
                                currentSearchValue +
                                '" category="' +
                                currentCategoryValue +
                                '"'
                        );
                    }

                    // Check for ANY change in either field
                    if (
                        currentSearchValue !== self.lastSearchValue ||
                        currentCategoryValue !== self.lastCategoryValue
                    ) {
                        console.log(
                            '[realtimeSearch] ⚡ CHANGE DETECTED: search="' +
                                currentSearchValue +
                                '" (was:"' +
                                self.lastSearchValue +
                                '") | category="' +
                                currentCategoryValue +
                                '" (was:"' +
                                self.lastCategoryValue +
                                '")'
                        );
                        self.lastSearchValue = currentSearchValue;
                        self.lastCategoryValue = currentCategoryValue;

                        // Reset infinite scroll with new filters (will reload from server)
                        if (
                            window.infiniteScroll &&
                            typeof window.infiniteScroll.resetWithFilters === "function"
                        ) {
                            console.log(
                                "[realtimeSearch] Calling infiniteScroll.resetWithFilters()"
                            );
                            window.infiniteScroll.resetWithFilters(
                                currentSearchValue,
                                currentCategoryValue
                            );
                        } else {
                            // Fallback: filter locally (but this only filters loaded products)
                            // Skip during initialization
                            if (!self.isInitializing) {
                                console.log(
                                    "[realtimeSearch] infiniteScroll not available, filtering locally only"
                                );
                                self._filterProducts();
                            }
                        }
                    }
                } catch (error) {
                    console.error("[realtimeSearch] ❌ Error in polling:", error.message);
                }
            }, 300); // Check every 300ms

            console.log("[realtimeSearch] ✅ Polling interval started with ID:", pollInterval);

            console.log("[realtimeSearch] Event listeners attached with polling fallback");

            // Initialization complete - allow filtering now
            self.isInitializing = false;
            console.log("[realtimeSearch] ✅ Initialization complete - filtering enabled");
        },

        _initializeAvailableTags: function () {
            /**
             * Initialize availableTags map from the DOM tag filter badges.
             * Format: availableTags[tagId] = {id, name, count}
             */
            var self = this;
            var tagBadges = document.querySelectorAll('[data-toggle="tag-filter"]');

            tagBadges.forEach(function (badge) {
                var tagId = parseInt(badge.getAttribute("data-tag-id"), 10);
                var tagName = badge.getAttribute("data-tag-name") || "";
                var countSpan = badge.querySelector(".tag-count");
                var count = countSpan ? parseInt(countSpan.textContent, 10) : 0;

                self.availableTags[tagId] = {
                    id: tagId,
                    name: tagName,
                    count: count,
                };
            });

            console.log(
                "[realtimeSearch] Initialized " +
                    Object.keys(self.availableTags).length +
                    " available tags"
            );
        },

        _filterProducts: function () {
            var self = this;

            try {
                var searchQuery = (self.searchInput.value || "").toLowerCase().trim();
                var selectedCategoryId = (self.categorySelect.value || "").toString();

                console.log(
                    "[realtimeSearch] Filtering: search=" +
                        searchQuery +
                        " category=" +
                        selectedCategoryId +
                        " tags=" +
                        Array.from(self.selectedTags).join(",")
                );

                // Build a set of allowed category IDs (selected category + ALL descendants recursively)
                var allowedCategories = {};

                if (selectedCategoryId) {
                    allowedCategories[selectedCategoryId] = true;

                    // Recursive function to get all descendants
                    var getAllDescendants = function (parentId) {
                        var descendants = [];
                        if (self.categoryHierarchy[parentId]) {
                            self.categoryHierarchy[parentId].forEach(function (childId) {
                                descendants.push(childId);
                                allowedCategories[childId] = true;
                                // Recursivamente obtener descendientes del hijo
                                var grandDescendants = getAllDescendants(childId);
                                descendants = descendants.concat(grandDescendants);
                            });
                        }
                        return descendants;
                    };

                    var allDescendants = getAllDescendants(selectedCategoryId);
                    console.log(
                        "[realtimeSearch] Selected category " +
                            selectedCategoryId +
                            " has " +
                            allDescendants.length +
                            " total descendants"
                    );
                    console.log(
                        "[realtimeSearch] Allowed categories:",
                        Object.keys(allowedCategories)
                    );
                }

                var visibleCount = 0;
                var hiddenCount = 0;

                // NOTE: Tag counts are NOT updated dynamically here because with lazy loading,
                // self.allProducts only contains products from current page.
                // Tag counts must remain as provided by backend (calculated on full dataset).

                self.allProducts.forEach(function (product) {
                    var nameMatches = !searchQuery || product.name.indexOf(searchQuery) !== -1;
                    var categoryMatches =
                        !selectedCategoryId || allowedCategories[product.category];

                    // Tag filtering: if tags are selected, product must have AT LEAST ONE selected tag (OR logic)
                    var tagMatches = true;
                    if (self.selectedTags.size > 0) {
                        tagMatches = product.tags.some(function (productTagId) {
                            return self.selectedTags.has(productTagId);
                        });
                    }

                    var shouldShow = nameMatches && categoryMatches && tagMatches;

                    if (shouldShow) {
                        product.element.classList.remove("hidden-product");
                        visibleCount++;
                    } else {
                        product.element.classList.add("hidden-product");
                        hiddenCount++;
                    }
                });

                console.log(
                    "[realtimeSearch] Filter result: visible=" +
                        visibleCount +
                        " hidden=" +
                        hiddenCount +
                        " (selectedTags: " +
                        Array.from(self.selectedTags).join(",") +
                        ")"
                );

                // Auto-load more products if too few are visible
                self._autoLoadMoreIfNeeded(visibleCount);
            } catch (error) {
                console.error("[realtimeSearch] ERROR in _filterProducts():", error.message);
                console.error("[realtimeSearch] Stack:", error.stack);
            }
        },

        _autoLoadMoreIfNeeded: function (visibleCount) {
            /**
             * Automatically load more products if there are too few visible on screen.
             * This prevents empty screens when filters hide most products.
             *
             * @param {number} visibleCount - Number of currently visible products
             */
            var self = this;
            var minVisibleProducts = 10; // Minimum products before auto-loading more

            // Only auto-load if infinite scroll is available and has more pages
            if (
                !window.infiniteScroll ||
                typeof window.infiniteScroll.loadNextPage !== "function"
            ) {
                return;
            }

            // Check if we need more products
            if (visibleCount < minVisibleProducts && window.infiniteScroll.hasMore) {
                console.log(
                    "[realtimeSearch] Only " +
                        visibleCount +
                        " products visible (min: " +
                        minVisibleProducts +
                        "), auto-loading next page..."
                );

                // Delay slightly to avoid race conditions
                setTimeout(function () {
                    if (
                        window.infiniteScroll &&
                        !window.infiniteScroll.isLoading &&
                        window.infiniteScroll.hasMore
                    ) {
                        window.infiniteScroll.loadNextPage();
                    }
                }, 100);
            }
        },
    };

    // Initialize when DOM is ready
    console.log("[realtimeSearch] Script loaded, DOM state: " + document.readyState);

    function tryInit() {
        try {
            console.log("[realtimeSearch] Attempting initialization...");

            // Query product cards
            var productCards = document.querySelectorAll(".product-card");
            console.log("[realtimeSearch] Found " + productCards.length + " product cards");

            // Use the NEW pure HTML input with ID (not transformed by Odoo)
            var searchInput = document.getElementById("realtime-search-input");
            console.log("[realtimeSearch] Search input found:", !!searchInput);
            if (searchInput) {
                console.log("[realtimeSearch] Search input class:", searchInput.className);
                console.log("[realtimeSearch] Search input type:", searchInput.type);
            }

            // Category select with ID (not transformed by Odoo)
            var categorySelect = document.getElementById("realtime-category-select");
            console.log("[realtimeSearch] Category select found:", !!categorySelect);

            if (productCards.length > 0 && searchInput) {
                console.log("[realtimeSearch] ✓ All elements found! Initializing...");
                // Assign elements to window.realtimeSearch BEFORE calling init()
                window.realtimeSearch.searchInput = searchInput;
                window.realtimeSearch.categorySelect = categorySelect;
                window.realtimeSearch.init();
                console.log("[realtimeSearch] ✓ Initialization complete!");
            } else {
                console.log(
                    "[realtimeSearch] Waiting for elements... (products:" +
                        productCards.length +
                        ", search:" +
                        !!searchInput +
                        ")"
                );
                if (productCards.length === 0) {
                    console.log(
                        "[realtimeSearch] No product cards found. Current HTML body length:",
                        document.body.innerHTML.length
                    );
                }
                setTimeout(tryInit, 500);
            }
        } catch (error) {
            console.error("[realtimeSearch] ERROR in tryInit():", error.message);
        }
    }

    if (document.readyState === "loading") {
        console.log("[realtimeSearch] Adding DOMContentLoaded listener");
        document.addEventListener("DOMContentLoaded", function () {
            console.log("[realtimeSearch] DOMContentLoaded fired");
            tryInit();
        });
    } else {
        console.log("[realtimeSearch] DOM already loaded, initializing with delay");
        setTimeout(tryInit, 500);
    }
})();
