/**
 * SearchResults Component
 *
 * Displays search results with customizable rendering
 * Includes keyboard navigation support (arrow keys, Enter to select)
 */
import React, { useState, useRef, useEffect, useCallback } from 'react';
import { useSearchContext } from './SearchProvider';
import { useSearchState } from '../hooks/useSearchState';
import { log } from '@seekora-ai/ui-sdk-core';
import { clsx } from 'clsx';
// Helper function to get nested value from object using dot notation
const getNestedValue = (obj, path) => {
    if (!path)
        return undefined;
    return path.split('.').reduce((current, key) => current?.[key], obj);
};
// Helper function to format price
const formatPrice = (value, currency = '₹') => {
    if (value === undefined || value === null)
        return undefined;
    if (typeof value === 'number')
        return `${currency}${value}`;
    if (typeof value === 'string') {
        const num = parseFloat(value);
        if (!isNaN(num))
            return `${currency}${num}`;
        return value;
    }
    return String(value);
};
export const SearchResults = ({ results: resultsProp, loading: loadingProp, error: errorProp, onResultClick, renderResult, renderEmpty, renderError, className, style, theme: customTheme, itemsPerPage = 20, showPagination = false, viewMode = 'list', fieldMapping, extractResults, enableKeyboardNavigation = true, autoFocus = false, minHeight = '400px', minWidth = '100%', }) => {
    const { theme, client, enableAnalytics } = useSearchContext();
    const { results: stateResults, loading: stateLoading, error: stateError, currentPage, itemsPerPage: stateItemsPerPage } = useSearchState();
    const searchResultsTheme = customTheme || {};
    // Keyboard navigation state
    const [activeIndex, setActiveIndex] = useState(-1);
    const containerRef = useRef(null);
    // Use props if provided, otherwise use state from state manager
    const results = resultsProp !== undefined ? resultsProp : stateResults;
    const loading = loadingProp !== undefined ? loadingProp : stateLoading;
    const error = errorProp !== undefined ? errorProp : stateError;
    // Reset active index when results change
    useEffect(() => {
        setActiveIndex(-1);
    }, [results]);
    // Scroll active item into view
    useEffect(() => {
        if (activeIndex >= 0 && containerRef.current && enableKeyboardNavigation) {
            const activeEl = containerRef.current.querySelector(`[data-result-index="${activeIndex}"]`);
            if (activeEl) {
                activeEl.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
            }
        }
    }, [activeIndex, enableKeyboardNavigation]);
    // Global keyboard listener for seamless navigation from search box to results
    useEffect(() => {
        if (!enableKeyboardNavigation)
            return;
        const handleGlobalKeyDown = (e) => {
            // Only handle if we have results and the container exists
            if (!containerRef.current)
                return;
            const resultElements = containerRef.current.querySelectorAll('[data-result-index]');
            const maxIndex = resultElements.length - 1;
            if (maxIndex < 0)
                return;
            // Check if focus is on an input/textarea (search box)
            const activeElement = document.activeElement;
            const isInputFocused = activeElement?.tagName === 'INPUT' || activeElement?.tagName === 'TEXTAREA';
            if (e.key === 'ArrowDown') {
                // If in search box or no result selected, select first result
                if (isInputFocused || activeIndex === -1) {
                    e.preventDefault();
                    setActiveIndex(0);
                    containerRef.current?.focus();
                }
            }
            else if (e.key === 'ArrowUp') {
                // If first result is selected, go back to search box
                if (activeIndex === 0) {
                    e.preventDefault();
                    setActiveIndex(-1);
                    // Find and focus the search input
                    const searchInput = document.querySelector('input[type="text"], input[type="search"]');
                    searchInput?.focus();
                }
            }
        };
        document.addEventListener('keydown', handleGlobalKeyDown);
        return () => document.removeEventListener('keydown', handleGlobalKeyDown);
    }, [enableKeyboardNavigation, activeIndex]);
    // Keyboard navigation handler
    const handleKeyDown = useCallback((e) => {
        if (!enableKeyboardNavigation)
            return;
        // We need to get the result count dynamically
        const resultElements = containerRef.current?.querySelectorAll('[data-result-index]');
        const maxIndex = resultElements ? resultElements.length - 1 : -1;
        switch (e.key) {
            case 'ArrowDown':
                e.preventDefault();
                setActiveIndex(prev => Math.min(prev + 1, maxIndex));
                break;
            case 'ArrowUp':
                e.preventDefault();
                setActiveIndex(prev => Math.max(prev - 1, -1));
                break;
            case 'Enter':
                e.preventDefault();
                if (activeIndex >= 0) {
                    // Trigger click on active item
                    const activeEl = containerRef.current?.querySelector(`[data-result-index="${activeIndex}"]`);
                    if (activeEl) {
                        activeEl.click();
                    }
                }
                break;
            case 'Escape':
                setActiveIndex(-1);
                containerRef.current?.blur();
                break;
            case 'Home':
                e.preventDefault();
                setActiveIndex(0);
                break;
            case 'End':
                e.preventDefault();
                setActiveIndex(maxIndex);
                break;
        }
    }, [enableKeyboardNavigation, activeIndex]);
    const defaultRenderResultList = (result, index, isActive = false) => {
        const handleClick = async () => {
            // Track analytics event if enabled
            if (enableAnalytics && result.id) {
                try {
                    const results = resultsProp || stateResults;
                    const state = { currentPage, itemsPerPage: stateItemsPerPage };
                    // Calculate absolute position (1-based) accounting for pagination
                    const absolutePosition = (state.currentPage - 1) * state.itemsPerPage + index + 1;
                    const searchContext = results?.context;
                    if (client.trackClick) {
                        await client.trackClick(result.id, absolutePosition, searchContext);
                    }
                    else {
                        await client.trackEvent?.({
                            event_name: 'product_click',
                            clicked_item_id: result.id,
                            metadata: { result, position: absolutePosition },
                        }, searchContext);
                    }
                }
                catch (err) {
                    const error = err instanceof Error ? err : new Error(String(err));
                    log.error('SearchResults: Error tracking click', { resultId: result.id, error: error.message });
                }
            }
            // Call user-provided callback
            if (onResultClick) {
                onResultClick(result, index);
            }
        };
        return (React.createElement("div", { key: result.id || index, "data-result-index": index, className: clsx(searchResultsTheme.resultItem, isActive && searchResultsTheme.resultItemHover), onClick: handleClick, onMouseEnter: () => enableKeyboardNavigation && setActiveIndex(index), style: {
                padding: theme.spacing.medium,
                border: `1px solid ${theme.colors.border}`,
                borderBottom: `1px solid ${theme.colors.border}`,
                borderRadius: 0,
                marginBottom: 0,
                cursor: onResultClick ? 'pointer' : 'default',
                transition: theme.transitions?.normal || '250ms ease-in-out',
                backgroundColor: isActive ? theme.colors.hover : theme.colors.background,
                display: 'flex',
                alignItems: 'flex-start',
                gap: theme.spacing.medium,
                outline: isActive ? `2px solid ${theme.colors.primary}` : 'none',
                outlineOffset: '-2px',
            } },
            result.image && (React.createElement("img", { src: result.image, alt: result.title, className: searchResultsTheme.resultImage, style: {
                    width: '100px',
                    height: '100px',
                    objectFit: 'cover',
                    borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium,
                    flexShrink: 0,
                } })),
            React.createElement("div", { style: { flex: 1, minWidth: 0 } },
                React.createElement("h3", { className: searchResultsTheme.resultTitle, style: {
                        fontSize: theme.typography.fontSize.large,
                        fontWeight: 'bold',
                        margin: 0,
                        marginBottom: theme.spacing.small,
                        color: theme.colors.text,
                    } }, result.title),
                result.description && (React.createElement("p", { className: searchResultsTheme.resultDescription, style: {
                        fontSize: theme.typography.fontSize.medium,
                        color: theme.colors.text,
                        margin: 0,
                        marginBottom: theme.spacing.small,
                        opacity: 0.8,
                    } }, result.description)),
                result.price && (React.createElement("div", { className: searchResultsTheme.resultPrice, style: {
                        fontSize: theme.typography.fontSize.medium,
                        fontWeight: 'bold',
                        color: theme.colors.primary,
                    } }, result.price)))));
    };
    const defaultRenderResultCard = (result, index, isActive = false) => {
        const handleClick = async () => {
            // Track analytics event if enabled
            if (enableAnalytics && result.id) {
                try {
                    const results = resultsProp || stateResults;
                    const state = { currentPage, itemsPerPage: stateItemsPerPage };
                    // Calculate absolute position (1-based) accounting for pagination
                    const absolutePosition = (state.currentPage - 1) * state.itemsPerPage + index + 1;
                    const searchContext = results?.context;
                    if (client.trackClick) {
                        await client.trackClick(result.id, absolutePosition, searchContext);
                    }
                    else {
                        await client.trackEvent?.({
                            event_name: 'product_click',
                            clicked_item_id: result.id,
                            metadata: { result, position: absolutePosition },
                        }, searchContext);
                    }
                }
                catch (err) {
                    const error = err instanceof Error ? err : new Error(String(err));
                    log.error('SearchResults: Error tracking click', { resultId: result.id, error: error.message });
                }
            }
            // Call user-provided callback
            if (onResultClick) {
                onResultClick(result, index);
            }
        };
        // Use widget view fields if available, otherwise fall back to regular fields
        const primaryText = result.primaryText || result.title;
        const secondaryText = result.secondaryText || result.description;
        const tertiaryText = result.tertiaryText || result.price;
        const imageUrl = result.imageUrl || result.image;
        return (React.createElement("div", { key: result.id || index, "data-result-index": index, className: clsx(searchResultsTheme.resultItem, isActive && searchResultsTheme.resultItemHover), onClick: handleClick, onMouseEnter: () => enableKeyboardNavigation && setActiveIndex(index), style: {
                border: `1px solid ${isActive ? theme.colors.primary : theme.colors.border}`,
                borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium,
                overflow: 'hidden',
                cursor: onResultClick ? 'pointer' : 'default',
                transition: theme.transitions?.normal || '250ms ease-in-out',
                backgroundColor: isActive ? theme.colors.hover : theme.colors.background,
                display: 'flex',
                flexDirection: 'column',
                padding: theme.spacing.medium,
                boxShadow: isActive ? theme.shadows.medium : theme.shadows.small,
                outline: isActive ? `2px solid ${theme.colors.primary}` : 'none',
                outlineOffset: '-2px',
            } },
            imageUrl && (React.createElement("div", { style: {
                    width: '100%',
                    aspectRatio: '16/9',
                    overflow: 'hidden',
                    backgroundColor: theme.colors.hover,
                } },
                React.createElement("img", { src: imageUrl, alt: primaryText, style: {
                        width: '100%',
                        height: '100%',
                        objectFit: 'cover',
                    } }))),
            React.createElement("div", { style: { padding: theme.spacing.medium } },
                primaryText && (React.createElement("h3", { className: searchResultsTheme.resultTitle, style: {
                        fontSize: theme.typography.fontSize.large,
                        fontWeight: 'bold',
                        margin: 0,
                        marginBottom: theme.spacing.small,
                        color: theme.colors.text,
                    } }, primaryText)),
                secondaryText && (React.createElement("p", { className: searchResultsTheme.resultDescription, style: {
                        fontSize: theme.typography.fontSize.medium,
                        color: theme.colors.text,
                        margin: 0,
                        marginBottom: theme.spacing.small,
                        opacity: 0.8,
                        display: '-webkit-box',
                        WebkitLineClamp: 2,
                        WebkitBoxOrient: 'vertical',
                        overflow: 'hidden',
                    } }, secondaryText)),
                tertiaryText && (React.createElement("div", { className: searchResultsTheme.resultPrice, style: {
                        fontSize: theme.typography.fontSize.medium,
                        fontWeight: 'bold',
                        color: theme.colors.primary,
                        marginTop: 'auto',
                    } }, tertiaryText)))));
    };
    const defaultRenderResult = viewMode === 'card' || viewMode === 'grid'
        ? defaultRenderResultCard
        : defaultRenderResultList;
    const defaultRenderEmpty = () => (React.createElement("div", { className: searchResultsTheme.emptyState, style: {
            padding: theme.spacing.large,
            textAlign: 'center',
            color: theme.colors.text,
        } }, "No results found"));
    const defaultRenderError = (err) => (React.createElement("div", { className: searchResultsTheme.errorState, style: {
            padding: theme.spacing.large,
            textAlign: 'center',
            color: theme.colors.error,
        } },
        "Error: ",
        err.message));
    // Extract results array from response
    let rawResults = [];
    if (extractResults) {
        // Use custom extraction function if provided
        rawResults = extractResults(results) || [];
    }
    else if (results) {
        const res = results;
        if (Array.isArray(res.results) && res.results.length > 0) {
            rawResults = res.results;
        }
        else if (res.data && Array.isArray(res.data.results) && res.data.results.length > 0) {
            rawResults = res.data.results;
        }
        else if (res.data?.data && Array.isArray(res.data.data.results) && res.data.data.results.length > 0) {
            rawResults = res.data.data.results;
        }
        else if (Array.isArray(results)) {
            rawResults = results;
        }
        else if (Array.isArray(res.results)) {
            rawResults = res.results;
        }
    }
    // Default field mapping (can be overridden via props)
    const defaultFieldMapping = {
        title: 'document.productName',
        description: 'document.brandDesc',
        image: 'document.image',
        price: 'document.mrp',
        url: 'document.url',
        id: 'id',
        ...fieldMapping,
    };
    // Extract field value using dot notation path
    const extractField = (item, path) => {
        if (!path)
            return undefined;
        return getNestedValue(item, path);
    };
    const resultItems = rawResults.map((item, index) => {
        try {
            // Widget view fields (when widget_mode is enabled) - check these first
            const primaryText = extractField(item, defaultFieldMapping.primaryText);
            const secondaryText = extractField(item, defaultFieldMapping.secondaryText);
            const tertiaryText = extractField(item, defaultFieldMapping.tertiaryText);
            const imageUrl = extractField(item, defaultFieldMapping.imageUrl);
            // Use primaryText as fallback for title if title is not found
            const title = extractField(item, defaultFieldMapping.title) || primaryText || 'Untitled';
            const description = extractField(item, defaultFieldMapping.description) || secondaryText;
            const image = extractField(item, defaultFieldMapping.image) || imageUrl;
            const priceValue = extractField(item, defaultFieldMapping.price) || tertiaryText;
            const url = extractField(item, defaultFieldMapping.url);
            const id = extractField(item, defaultFieldMapping.id) || String(index);
            // Format price if it's a number
            const price = priceValue !== undefined ? formatPrice(priceValue) : undefined;
            // Extract custom fields if configured
            const customFields = {};
            if (defaultFieldMapping.custom) {
                Object.entries(defaultFieldMapping.custom).forEach(([key, path]) => {
                    customFields[key] = extractField(item, path);
                });
            }
            const resultItem = {
                id,
                title,
                description,
                url,
                image,
                price,
                metadata: item,
                ...customFields,
                // Widget view fields
                ...(primaryText && { primaryText }),
                ...(secondaryText && { secondaryText }),
                ...(tertiaryText && { tertiaryText }),
                ...(imageUrl && { imageUrl }),
                // Include original item for full access
                _raw: item,
            };
            return resultItem;
        }
        catch (err) {
            const error = err instanceof Error ? err : new Error(String(err));
            log.warn('SearchResults: Error extracting result item', {
                index,
                error: error.message,
                item: item?.id || 'unknown',
            });
            // Return a fallback result item
            return {
                id: String(index),
                title: 'Error loading result',
                metadata: item,
            };
        }
    });
    // Determine container style based on view mode
    const containerStyle = {
        minHeight: `var(--seekora-results-min-height, ${minHeight})`,
        minWidth: `var(--seekora-results-min-width, ${minWidth})`,
        ...style,
    };
    // Determine results list style based on view mode
    const resultsListStyle = {
        ...(viewMode === 'grid' && {
            display: 'grid',
            gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))',
            gap: theme.spacing.medium,
        }),
        ...(viewMode === 'card' && {
            display: 'grid',
            gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))',
            gap: theme.spacing.medium,
        }),
    };
    // Log results extraction
    log.verbose('SearchResults: Extracted results', {
        rawResultsCount: rawResults.length,
        resultItemsCount: resultItems.length,
        viewMode,
        hasError: !!error,
        isLoading: loading,
    });
    if (error) {
        log.error('SearchResults: Rendering error state', {
            error: error.message,
            stack: error.stack,
        });
        return (React.createElement("div", { className: clsx(searchResultsTheme.container, className), style: containerStyle }, renderError ? renderError(error) : defaultRenderError(error)));
    }
    if (!results || resultItems.length === 0) {
        log.verbose('SearchResults: No results to display');
        return (React.createElement("div", { className: clsx(searchResultsTheme.container, className), style: containerStyle }, renderEmpty ? renderEmpty() : defaultRenderEmpty()));
    }
    const renderFn = renderResult || defaultRenderResult;
    return (React.createElement("div", { ref: containerRef, className: clsx(searchResultsTheme.container, className), style: containerStyle, tabIndex: enableKeyboardNavigation ? 0 : undefined, onKeyDown: handleKeyDown, role: "listbox", "aria-label": "Search results", "aria-activedescendant": activeIndex >= 0 ? `result-${activeIndex}` : undefined },
        (results?.totalResults !== undefined || results?.data?.total_results !== undefined) && resultItems.length > 0 && (React.createElement("div", { className: searchResultsTheme.header, style: {
                marginBottom: theme.spacing.medium,
                fontSize: theme.typography.fontSize.medium,
                color: theme.colors.text,
            } },
            "Found ",
            results?.totalResults || results?.data?.total_results || 0,
            " result",
            (results?.totalResults || results?.data?.total_results || 0) !== 1 ? 's' : '')),
        React.createElement("div", { className: searchResultsTheme.resultsList, style: resultsListStyle }, resultItems.map((result, index) => renderFn(result, index, index === activeIndex)))));
};
