/**
 * FederatedDropdown Component
 *
 * Full-featured federated search dropdown with:
 * - Multi-column layout (suggestions + products)
 * - Filtered tabs with product results
 * - Popular brands
 * - Trending products
 * - Category navigation
 * - Responsive design
 * - Rich product cards
 */
import React, { useState, useEffect, useRef, useCallback, useMemo, forwardRef, useImperativeHandle, useId, } from "react";
import { useSearchContext } from "./SearchProvider";
import { useQuerySuggestionsEnhanced } from "../hooks/useQuerySuggestionsEnhanced";
import { ensureSeekoraStyles } from "../styles/inject";
import { clsx } from "clsx";
import { useAnchorPortal } from "../utils/use-anchor-portal";
// ============================================================================
// (styles moved to packages/react/src/styles/components.css — BEM migration)
// ============================================================================
// ============================================================================
// Icons
// ============================================================================
const SearchIcon = () => (React.createElement("svg", { viewBox: "0 0 20 20", fill: "currentColor", className: "seekora-federated-dropdown__suggestion-icon" },
    React.createElement("path", { fillRule: "evenodd", d: "M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z", clipRule: "evenodd" })));
const ClockIcon = () => (React.createElement("svg", { viewBox: "0 0 20 20", fill: "currentColor", className: "seekora-federated-dropdown__suggestion-icon" },
    React.createElement("path", { fillRule: "evenodd", d: "M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z", clipRule: "evenodd" })));
const ArrowRightIcon = ({ visible }) => (React.createElement("svg", { viewBox: "0 0 20 20", fill: "currentColor", className: clsx("seekora-federated-dropdown__suggestion-arrow", visible && "seekora-federated-dropdown__suggestion-arrow--visible") },
    React.createElement("path", { fillRule: "evenodd", d: "M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z", clipRule: "evenodd" })));
const TrendingIcon = () => (React.createElement("svg", { viewBox: "0 0 20 20", fill: "currentColor", className: "seekora-federated-dropdown__trending-icon" },
    React.createElement("path", { fillRule: "evenodd", d: "M12 7a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0V8.414l-4.293 4.293a1 1 0 01-1.414 0L8 10.414l-4.293 4.293a1 1 0 01-1.414-1.414l5-5a1 1 0 011.414 0L11 10.586 14.586 7H12z", clipRule: "evenodd" })));
const ImagePlaceholder = () => (React.createElement("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", className: "seekora-federated-dropdown__product-image-placeholder" },
    React.createElement("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2", strokeWidth: "2" }),
    React.createElement("circle", { cx: "8.5", cy: "8.5", r: "1.5", strokeWidth: "2" }),
    React.createElement("polyline", { points: "21 15 16 10 5 21", strokeWidth: "2" })));
// ============================================================================
// Component
// ============================================================================
export const FederatedDropdown = forwardRef(function FederatedDropdown(props, ref) {
    const { query, isOpen = true, maxSuggestions = 8, maxProducts = 8, maxBrands = 8, minQueryLength = 0, debounceMs = 200, filteredTabs: tabsConfig, showProducts = true, showBrands = true, showFilteredTabs = true, showRecentSearches = true, layout = "side-by-side", productsColumnWidth = "60%", suggestionsColumnWidth = "40%", showPrices = true, currencySymbol = "$", classNames = {}, style, renderProduct, renderSuggestion, renderBrand, renderTab, header, footer, viewAllProductsLink, width = "800px", maxHeight = "600px", zIndex = 1000, analyticsTags, includeFacets: includeFacetsProp = true, includeCategories: includeCategoriesProp = true, includeDropdownRecommendations: includeDropdownRecommendationsProp = true, anchorRef, onSuggestionSelect, onProductClick, onBrandClick, onTabSelect, onRecentSearchClick, onRecentSearchRemove, onViewAllClick, onOpen, onClose, } = props;
    useEffect(() => {
        ensureSeekoraStyles();
    }, []);
    const { client } = useSearchContext();
    const containerRef = useRef(null);
    const [activeIndex, setActiveIndex] = useState(-1);
    const [activeTab, setActiveTab] = useState("all");
    // Defect 5: generation counter tracks which tab was active when a products
    // fetch was initiated.  Each handleTabChange increments the counter; when
    // filteredTabs updates, we only accept the update if the current generation
    // matches the generation under which the tab was set.
    const tabGenerationRef = useRef(0);
    const [committedTabGeneration, setCommittedTabGeneration] = useState(0);
    // Stable component ID for aria-activedescendant item IDs.
    const componentId = useId();
    // Portal positioning — only active when anchorRef is provided.
    const { portalStyle, wrapWithPortal, dataPosition } = useAnchorPortal(anchorRef, 600, zIndex);
    // Use enhanced hook
    const { suggestions, loading, filteredTabs, trendingProducts, popularBrands, recentSearches, addRecentSearch, removeRecentSearch, hasContent, } = useQuerySuggestionsEnhanced({
        client,
        query,
        enabled: isOpen,
        debounceMs,
        maxSuggestions,
        minQueryLength,
        includeDropdownRecommendations: includeDropdownRecommendationsProp,
        includeCategories: includeCategoriesProp,
        includeFacets: includeFacetsProp,
        filteredTabs: tabsConfig,
        analyticsTags,
        enableRecentSearches: showRecentSearches,
    });
    // Defect 5: stableFilteredTabs only updates when the generation at the time
    // filteredTabs resolved matches the committed (latest) generation.  This
    // prevents a slow Tab A fetch from overwriting Tab B results.
    const [stableFilteredTabs, setStableFilteredTabs] = useState(filteredTabs);
    useEffect(() => {
        // Accept the new filteredTabs only if the current committed generation
        // matches the latest tab switch generation (i.e. the user hasn't
        // switched away again since this fetch was started).
        if (committedTabGeneration === tabGenerationRef.current) {
            setStableFilteredTabs(filteredTabs);
        }
    }, [filteredTabs, committedTabGeneration]);
    // Get products for current tab
    const currentTabProducts = useMemo(() => {
        if (activeTab === "all") {
            // Combine trending products with first tab products
            const allProducts = [...trendingProducts];
            stableFilteredTabs.forEach((tab) => {
                if (tab.products) {
                    tab.products.forEach((product) => {
                        if (!allProducts.find((p) => p.id === product.id)) {
                            allProducts.push(product);
                        }
                    });
                }
            });
            return allProducts.slice(0, maxProducts);
        }
        const tab = stableFilteredTabs.find((t) => t.id === activeTab);
        return tab?.products?.slice(0, maxProducts) || [];
    }, [activeTab, stableFilteredTabs, trendingProducts, maxProducts]);
    // All navigable items — includes suggestions, recents, products, and brands
    // so Tab/Enter can reach every interactive item in the dropdown.
    const allItems = useMemo(() => {
        const items = [];
        // Recent searches (when no query)
        if (query.length === 0 && showRecentSearches) {
            recentSearches.slice(0, 5).forEach((search) => {
                items.push({ type: "recent", data: search });
            });
        }
        // Suggestions
        suggestions.forEach((suggestion) => {
            items.push({ type: "suggestion", data: suggestion });
        });
        // Products (current tab)
        if (showProducts) {
            currentTabProducts.forEach((product) => {
                items.push({ type: "product", data: product });
            });
        }
        // Brands
        if (showBrands) {
            popularBrands.slice(0, maxBrands).forEach((brand) => {
                items.push({ type: "brand", data: brand });
            });
        }
        return items;
    }, [
        query,
        showRecentSearches,
        recentSearches,
        suggestions,
        showProducts,
        currentTabProducts,
        showBrands,
        popularBrands,
        maxBrands,
    ]);
    // Reset active index when item list changes.
    useEffect(() => {
        setActiveIndex(-1);
    }, [allItems.length]);
    // Navigation
    const navigateNext = useCallback(() => {
        if (allItems.length === 0)
            return;
        setActiveIndex((prev) => (prev < allItems.length - 1 ? prev + 1 : 0));
    }, [allItems.length]);
    const navigatePrevious = useCallback(() => {
        if (allItems.length === 0)
            return;
        setActiveIndex((prev) => (prev > 0 ? prev - 1 : allItems.length - 1));
    }, [allItems.length]);
    const selectActive = useCallback(() => {
        if (activeIndex < 0 || activeIndex >= allItems.length)
            return;
        const item = allItems[activeIndex];
        if (item.type === "recent") {
            onRecentSearchClick?.(item.data);
        }
        else if (item.type === "suggestion") {
            onSuggestionSelect?.(item.data);
            addRecentSearch(item.data.query);
        }
        else if (item.type === "product") {
            onProductClick?.(item.data);
        }
        else if (item.type === "brand") {
            onBrandClick?.(item.data);
        }
    }, [
        activeIndex,
        allItems,
        onRecentSearchClick,
        onSuggestionSelect,
        addRecentSearch,
        onProductClick,
        onBrandClick,
    ]);
    // Expose ref
    useImperativeHandle(ref, () => ({
        getActiveIndex: () => activeIndex,
        setActiveIndex,
        selectActive,
        navigateNext,
        navigatePrevious,
        getActiveTab: () => activeTab,
        setActiveTab,
        getTotalItems: () => allItems.length,
    }), [
        activeIndex,
        selectActive,
        navigateNext,
        navigatePrevious,
        activeTab,
        allItems.length,
    ]);
    // Highlight query in text
    const highlightQuery = (text) => {
        if (!query)
            return text;
        const parts = text.split(new RegExp(`(${query})`, "gi"));
        return parts.map((part, i) => part.toLowerCase() === query.toLowerCase() ? (React.createElement("span", { key: i, className: "seekora-federated-dropdown__highlight" }, part)) : (part));
    };
    // Format price
    const formatPrice = (price, currency) => {
        if (price === undefined)
            return "";
        const symbol = currency || currencySymbol;
        return `${symbol}${price.toLocaleString()}`;
    };
    // Handle tab change
    // Defect 5: bump the generation so any in-flight filteredTabs update that
    // was tagged with the previous generation is ignored.
    const handleTabChange = (tabId) => {
        tabGenerationRef.current += 1;
        const gen = tabGenerationRef.current;
        setActiveTab(tabId);
        setCommittedTabGeneration(gen);
        const tab = stableFilteredTabs.find((t) => t.id === tabId);
        if (tab) {
            onTabSelect?.(tab);
        }
    };
    if (!isOpen)
        return null;
    const showTabs = showFilteredTabs &&
        (stableFilteredTabs.length > 0 || trendingProducts.length > 0);
    const showProductsSection = showProducts && currentTabProducts.length > 0;
    const showBrandsSection = showBrands && popularBrands.length > 0;
    const showRecent = showRecentSearches && query.length === 0 && recentSearches.length > 0;
    const showSuggestions = suggestions.length > 0;
    const isStackedLayout = layout === "stacked" || layout === "full-width";
    // Derive active descendant ID for aria support.
    const activeItemId = activeIndex >= 0 ? `seekora-sugg-${componentId}-${activeIndex}` : undefined;
    // Compute effective container style — portal overrides position/top/left/width.
    const containerStyle = portalStyle
        ? { ...portalStyle, ...style }
        : { position: "absolute", width, zIndex, ...style };
    const dropdownTree = (React.createElement("div", { ref: containerRef, role: "listbox", "aria-label": "Search suggestions and products", "aria-activedescendant": activeItemId, "data-position": dataPosition, className: clsx("seekora-federated-dropdown", isStackedLayout && "seekora-federated-dropdown--stacked", classNames.root, classNames.container), style: containerStyle },
        header && (React.createElement("div", { className: "seekora-federated-dropdown__header" }, header)),
        showTabs && (React.createElement("div", { className: clsx("seekora-federated-dropdown__tabs", classNames.tabsList) },
            React.createElement("button", { key: "all-results", className: clsx("seekora-federated-dropdown__tab", activeTab === "all" && "seekora-federated-dropdown__tab--active", classNames.tabItem, activeTab === "all" && classNames.tabActive), onClick: () => handleTabChange("all") },
                "All Results",
                trendingProducts.length > 0 && (React.createElement("span", { className: clsx("seekora-federated-dropdown__tab-count", activeTab === "all" &&
                        "seekora-federated-dropdown__tab-count--active") },
                    trendingProducts.length,
                    "+"))),
            stableFilteredTabs.map((tab) => renderTab ? (renderTab(tab, activeTab === tab.id)) : (React.createElement("button", { key: tab.id, className: clsx("seekora-federated-dropdown__tab", activeTab === tab.id &&
                    "seekora-federated-dropdown__tab--active", classNames.tabItem, activeTab === tab.id && classNames.tabActive), onClick: () => handleTabChange(tab.id) },
                tab.label,
                tab.nb_hits !== undefined && (React.createElement("span", { className: clsx("seekora-federated-dropdown__tab-count", activeTab === tab.id &&
                        "seekora-federated-dropdown__tab-count--active") }, tab.nb_hits))))))),
        React.createElement("div", { className: "seekora-federated-dropdown__content", style: { maxHeight } },
            React.createElement("div", { className: clsx("seekora-federated-dropdown__suggestions-column", isStackedLayout &&
                    "seekora-federated-dropdown__suggestions-column--full"), style: isStackedLayout
                    ? undefined
                    : { width: suggestionsColumnWidth, minWidth: "280px" } },
                showRecent && (React.createElement("div", { className: clsx("seekora-federated-dropdown__section", classNames.recentSearches) },
                    React.createElement("div", { className: "seekora-federated-dropdown__section-header" },
                        React.createElement("h3", { className: "seekora-federated-dropdown__section-title" }, "Recent Searches")),
                    recentSearches.slice(0, 5).map((search, index) => {
                        const isActive = activeIndex === index;
                        const itemId = `seekora-sugg-${componentId}-${index}`;
                        return (React.createElement("div", { key: `recent-${search.query}`, id: itemId, role: "option", "aria-selected": isActive, tabIndex: -1, className: clsx("seekora-federated-dropdown__item", isActive && "seekora-federated-dropdown__item--active", classNames.recentItem, isActive && classNames.suggestionItemActive), onClick: () => onRecentSearchClick?.(search), onMouseEnter: () => setActiveIndex(index) },
                            React.createElement(ClockIcon, null),
                            React.createElement("span", { className: "seekora-federated-dropdown__item-text" }, search.query),
                            React.createElement(ArrowRightIcon, { visible: isActive })));
                    }))),
                showSuggestions && (React.createElement("div", { className: clsx("seekora-federated-dropdown__section", classNames.suggestionsList) },
                    React.createElement("div", { className: "seekora-federated-dropdown__section-header" },
                        React.createElement("h3", { className: "seekora-federated-dropdown__section-title" }, query ? "Suggestions" : "Popular Searches")),
                    suggestions.slice(0, maxSuggestions).map((suggestion, index) => {
                        const itemIndex = showRecent
                            ? recentSearches.length + index
                            : index;
                        const isActive = activeIndex === itemIndex;
                        const itemId = `seekora-sugg-${componentId}-${itemIndex}`;
                        return renderSuggestion ? (renderSuggestion(suggestion, index, isActive)) : (React.createElement("div", { key: suggestion.objectID || `suggestion-${index}`, id: itemId, role: "option", "aria-selected": isActive, tabIndex: -1, className: clsx("seekora-federated-dropdown__item", isActive && "seekora-federated-dropdown__item--active", classNames.suggestionItem, isActive && classNames.suggestionItemActive), onClick: () => {
                                onSuggestionSelect?.(suggestion);
                                addRecentSearch(suggestion.query);
                            }, onMouseEnter: () => setActiveIndex(itemIndex) },
                            React.createElement(SearchIcon, null),
                            React.createElement("span", { className: "seekora-federated-dropdown__item-text" }, highlightQuery(suggestion.query)),
                            suggestion.count !== undefined && (React.createElement("span", { className: "seekora-federated-dropdown__item-count" }, suggestion.count.toLocaleString())),
                            React.createElement(ArrowRightIcon, { visible: isActive })));
                    }))),
                showBrandsSection && (React.createElement("div", { className: clsx("seekora-federated-dropdown__section", classNames.brandsList) },
                    React.createElement("div", { className: "seekora-federated-dropdown__section-header" },
                        React.createElement("h3", { className: "seekora-federated-dropdown__section-title" }, "Popular Brands")),
                    React.createElement("div", { className: "seekora-federated-dropdown__brands-grid" }, popularBrands.slice(0, maxBrands).map((brand, index) => {
                        // brands come after recents + suggestions + products in allItems
                        const brandItemIndex = (showRecent ? Math.min(recentSearches.length, 5) : 0) +
                            Math.min(suggestions.length, maxSuggestions) +
                            (showProducts ? currentTabProducts.length : 0) +
                            index;
                        const isBrandActive = activeIndex === brandItemIndex;
                        const brandItemId = `seekora-sugg-${componentId}-${brandItemIndex}`;
                        return renderBrand ? (renderBrand(brand, index)) : (React.createElement("button", { key: `brand-${brand.name}`, id: brandItemId, role: "option", "aria-selected": isBrandActive, tabIndex: -1, className: clsx("seekora-federated-dropdown__brand-chip", isBrandActive &&
                                "seekora-federated-dropdown__brand-chip--active", classNames.brandItem), onClick: () => onBrandClick?.(brand), onMouseEnter: () => setActiveIndex(brandItemIndex) },
                            brand.logo && (React.createElement("img", { src: brand.logo, alt: brand.name, className: "seekora-federated-dropdown__brand-logo", onError: (e) => {
                                    e.target.style.display =
                                        "none";
                                } })),
                            React.createElement("span", null, brand.name)));
                    }))))),
            showProductsSection && !isStackedLayout && (React.createElement("div", { className: "seekora-federated-dropdown__products-column", style: { width: productsColumnWidth } },
                React.createElement("div", { className: "seekora-federated-dropdown__section" },
                    React.createElement("div", { className: "seekora-federated-dropdown__section-header" },
                        React.createElement("h3", { className: "seekora-federated-dropdown__section-title" }, activeTab === "all"
                            ? "Trending Products"
                            : `Products in ${stableFilteredTabs.find((t) => t.id === activeTab)
                                ?.label || activeTab}`),
                        viewAllProductsLink && (React.createElement("a", { href: viewAllProductsLink, className: "seekora-federated-dropdown__view-all", onClick: (e) => {
                                e.preventDefault();
                                onViewAllClick?.("products");
                            } }, "View all"))),
                    React.createElement("div", { className: clsx("seekora-federated-dropdown__products-grid", classNames.productsList) }, currentTabProducts.map((product, index) => {
                        // products come after recents + suggestions in allItems
                        const productItemIndex = (showRecent ? Math.min(recentSearches.length, 5) : 0) +
                            Math.min(suggestions.length, maxSuggestions) +
                            index;
                        const isProductActive = activeIndex === productItemIndex;
                        const productItemId = `seekora-sugg-${componentId}-${productItemIndex}`;
                        return renderProduct ? (renderProduct(product, index)) : (React.createElement("div", { key: product.id || product.objectID, id: productItemId, role: "option", "aria-selected": isProductActive, tabIndex: -1, className: clsx("seekora-federated-dropdown__product-card", isProductActive &&
                                "seekora-federated-dropdown__product-card--active", classNames.productItem), onClick: () => onProductClick?.(product), onMouseEnter: () => setActiveIndex(productItemIndex) },
                            product.image ? (React.createElement("img", { src: product.image, alt: product.title || product.name || "", className: "seekora-federated-dropdown__product-image", onError: (e) => {
                                    e.target.style.display =
                                        "none";
                                } })) : (React.createElement("div", { className: "seekora-federated-dropdown__product-image seekora-federated-dropdown__product-image--placeholder" },
                                React.createElement(ImagePlaceholder, null))),
                            React.createElement("div", { className: "seekora-federated-dropdown__product-info" },
                                React.createElement("h4", { className: "seekora-federated-dropdown__product-title" }, product.title || product.name),
                                showPrices && product.price !== undefined && (React.createElement("p", { className: "seekora-federated-dropdown__product-price" }, formatPrice(product.price, product.currency))))));
                    })))))),
        footer ? (React.createElement("div", { className: "seekora-federated-dropdown__footer" }, footer)) : (React.createElement("div", { className: "seekora-federated-dropdown__footer" },
            React.createElement("span", null, "Press \u21B5 to search, \u2191\u2193 to navigate"),
            query && (React.createElement("button", { className: "seekora-federated-dropdown__view-all seekora-federated-dropdown__view-all--btn", onClick: () => onViewAllClick?.("suggestions") },
                "See all results for \u201C",
                query,
                "\u201D"))))));
    return wrapWithPortal(dropdownTree);
});
export default FederatedDropdown;
