/**
 * SortBy Component
 *
 * Displays sort options for search results in multiple display variants:
 * - dropdown (default) — native select element
 * - button-group — horizontal row of toggle buttons
 * - radio-group — vertical list of radio inputs
 *
 * Integrates with SearchStateManager for automatic state sync.
 *
 * CSS Variables (apply on a parent element to customize):
 * --seekora-sort-bg           — background color
 * --seekora-sort-color        — text color
 * --seekora-sort-border       — border color
 * --seekora-sort-active-bg    — active item background
 * --seekora-sort-active-color — active item text color
 */
import React, { useCallback, useEffect, useId } from 'react';
import { useSearchContext } from './SearchProvider';
import { useSearchState } from '../hooks/useSearchState';
import { clsx } from 'clsx';
import { CustomSelect } from './primitives/CustomSelect';
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
/** Map a size token to theme fontSize and spacing values. */
function sizeStyles(size, theme) {
    switch (size) {
        case 'small':
            return { fontSize: theme.typography.fontSize.small, padding: theme.spacing.small };
        case 'large':
            return { fontSize: theme.typography.fontSize.large, padding: theme.spacing.medium };
        case 'medium':
        default:
            return { fontSize: theme.typography.fontSize.medium, padding: theme.spacing.small };
    }
}
function resolveBorderRadius(br) {
    return typeof br === 'string' ? br : br.medium;
}
// ---------------------------------------------------------------------------
// Component
// ---------------------------------------------------------------------------
export const SortBy = ({ options, value: valueProp, defaultValue, onSortChange, renderSelect, className, style, theme: customTheme, placeholder = 'Sort by...', syncWithState = true, variant = 'dropdown', label, showLabel, size = 'medium', }) => {
    const { theme } = useSearchContext();
    const { sortBy: stateManagerSortBy, setSortBy } = useSearchState();
    const sortByTheme = customTheme || {};
    const instanceId = useId();
    // Determine whether the label should render.
    const shouldShowLabel = showLabel !== undefined ? showLabel : !!label;
    // ------ State ----------------------------------------------------------
    const [internalValue, setInternalValue] = React.useState(defaultValue || options[0]?.value || '');
    // Sync with StateManager on mount if defaultValue is set
    useEffect(() => {
        if (syncWithState && defaultValue && !stateManagerSortBy) {
            setSortBy(defaultValue, false); // Don't trigger search on initial sync
        }
    }, []); // eslint-disable-line react-hooks/exhaustive-deps
    // Determine the current value: controlled prop > StateManager > internal
    const value = valueProp !== undefined
        ? valueProp
        : syncWithState && stateManagerSortBy
            ? stateManagerSortBy
            : internalValue;
    // ------ Handlers -------------------------------------------------------
    const handleChange = (e) => {
        applyValue(e.target.value);
    };
    const applyValue = useCallback((newValue) => {
        setInternalValue(newValue);
        if (syncWithState) {
            setSortBy(newValue);
        }
        if (onSortChange) {
            onSortChange(newValue);
        }
    }, [syncWithState, setSortBy, onSortChange]);
    // ------ Derived styles -------------------------------------------------
    const { fontSize, padding } = sizeStyles(size, theme);
    const borderRadius = resolveBorderRadius(theme.borderRadius);
    const cssVarStyle = {
        '--seekora-sort-bg': theme.colors.background,
        '--seekora-sort-color': theme.colors.text,
        '--seekora-sort-border': theme.colors.border,
        '--seekora-sort-active-bg': theme.colors.primary,
        '--seekora-sort-active-color': theme.colors.background,
    };
    // ------ Label ----------------------------------------------------------
    const labelElement = shouldShowLabel && label ? (React.createElement("span", { className: clsx(sortByTheme.label), style: {
            display: 'block',
            marginBottom: theme.spacing.small,
            fontSize,
            color: 'var(--seekora-sort-color)',
            fontWeight: 500,
        } }, label)) : null;
    // ------ Dropdown variant (original) ------------------------------------
    if (variant === 'dropdown') {
        if (renderSelect) {
            return (React.createElement("div", { className: clsx(sortByTheme.container, className), style: { ...cssVarStyle, ...style } },
                labelElement,
                renderSelect({
                    value,
                    onChange: handleChange,
                    options,
                })));
        }
        return (React.createElement("div", { className: clsx(sortByTheme.container, className), style: { ...cssVarStyle, ...style } },
            labelElement,
            React.createElement(CustomSelect, { value: value, onChange: applyValue, options: options, placeholder: placeholder, "aria-label": label || 'Sort results', className: clsx(sortByTheme.select), style: {
                    width: '100%',
                    '--seekora-select-font-size': fontSize,
                    '--seekora-select-border': 'var(--seekora-sort-border)',
                    '--seekora-select-radius': borderRadius,
                    '--seekora-select-bg': 'var(--seekora-sort-bg)',
                    '--seekora-select-color': 'var(--seekora-sort-color)',
                } })));
    }
    // ------ Button group variant -------------------------------------------
    if (variant === 'button-group') {
        return (React.createElement("div", { className: clsx(sortByTheme.container, className), style: { ...cssVarStyle, ...style } },
            labelElement,
            React.createElement("div", { role: "group", "aria-label": label || 'Sort results', className: clsx(sortByTheme.buttonGroup), style: {
                    display: 'inline-flex',
                    borderRadius,
                    overflow: 'hidden',
                    border: '1px solid var(--seekora-sort-border)',
                } }, options.map((option, index) => {
                const isActive = option.value === value;
                return (React.createElement("button", { key: option.value, type: "button", role: "button", "aria-pressed": isActive, onClick: () => applyValue(option.value), className: clsx(sortByTheme.buttonGroupItem, isActive && sortByTheme.buttonGroupItemActive), style: {
                        padding,
                        fontSize,
                        border: 'none',
                        borderRight: index < options.length - 1
                            ? '1px solid var(--seekora-sort-border)'
                            : 'none',
                        backgroundColor: isActive
                            ? 'var(--seekora-sort-active-bg)'
                            : 'var(--seekora-sort-bg)',
                        color: isActive
                            ? 'var(--seekora-sort-active-color)'
                            : 'var(--seekora-sort-color)',
                        cursor: 'pointer',
                        fontWeight: isActive ? 600 : 400,
                        transition: 'background-color 0.15s ease, color 0.15s ease',
                        outline: 'none',
                    } }, option.label));
            }))));
    }
    // ------ Radio group variant --------------------------------------------
    if (variant === 'radio-group') {
        const radioName = `seekora-sort-${instanceId}`;
        return (React.createElement("div", { className: clsx(sortByTheme.container, className), style: { ...cssVarStyle, ...style } },
            labelElement,
            React.createElement("div", { role: "radiogroup", "aria-label": label || 'Sort results', className: clsx(sortByTheme.radioGroup), style: {
                    display: 'flex',
                    flexDirection: 'column',
                    gap: theme.spacing.small,
                } }, options.map((option) => {
                const isActive = option.value === value;
                const radioId = `${radioName}-${option.value}`;
                return (React.createElement("label", { key: option.value, htmlFor: radioId, className: clsx(sortByTheme.radioItem, isActive && sortByTheme.radioItemActive), style: {
                        display: 'flex',
                        alignItems: 'center',
                        gap: theme.spacing.small,
                        padding,
                        borderRadius,
                        cursor: 'pointer',
                        backgroundColor: isActive
                            ? 'var(--seekora-sort-active-bg)'
                            : 'transparent',
                        color: isActive
                            ? 'var(--seekora-sort-active-color)'
                            : 'var(--seekora-sort-color)',
                        fontWeight: isActive ? 600 : 400,
                        transition: 'background-color 0.15s ease, color 0.15s ease',
                    } },
                    React.createElement("input", { type: "radio", id: radioId, name: radioName, value: option.value, checked: isActive, onChange: () => applyValue(option.value), style: { margin: 0 } }),
                    React.createElement("span", { className: clsx(sortByTheme.radioLabel), style: { fontSize } }, option.label)));
            }))));
    }
    // Fallback — should never reach here, but satisfies TS exhaustiveness
    return null;
};
