import { stateKey } from '../../../../app/state-key.js';
import { deselectAllValuesInCoreFacet, updateCoreFacetIsFieldExpanded, updateCoreFacetNumberOfValues, } from '../../../../features/commerce/facets/core-facet/core-facet-actions.js';
import { facetRequestSelector } from '../../../../features/commerce/facets/facet-set/facet-set-selector.js';
import { commerceFacetSetReducer as commerceFacetSet } from '../../../../features/commerce/facets/facet-set/facet-set-slice.js';
import { loadReducerError } from '../../../../utils/errors.js';
import { buildController } from '../../../controller/headless-controller.js';
export function buildCoreCommerceFacet(engine, props) {
    if (!loadCommerceFacetReducers(engine)) {
        throw loadReducerError;
    }
    const { dispatch } = engine;
    const controller = buildController(engine);
    const facetId = props.options.facetId;
    const getEngineState = () => engine[stateKey];
    const getRequest = () => facetRequestSelector(getEngineState(), facetId);
    const getResponse = () => props.options.facetResponseSelector(getEngineState(), facetId);
    const getIsLoading = () => props.options.isFacetLoadingResponseSelector(getEngineState());
    const getNumberOfActiveValues = () => {
        return getRequest()?.values?.filter((v) => v.state !== 'idle').length ?? 0;
    };
    return {
        ...controller,
        toggleSelect: (selection) => {
            dispatch(props.options.toggleSelectActionCreator({
                selection,
                facetId,
            }));
            dispatch(props.options.fetchProductsActionCreator());
        },
        toggleExclude: (selection) => {
            // TODO CAPI-409: Rework facet type definitions
            if (!props.options.toggleExcludeActionCreator) {
                engine.logger.warn('No toggle exclude action creator provided; calling #toggleExclude had no effect.');
                return;
            }
            dispatch(props.options.toggleExcludeActionCreator({ selection, facetId }));
            dispatch(props.options.fetchProductsActionCreator());
        },
        // Must use a function here to properly support inheritance with `this`.
        toggleSingleSelect: function (selection) {
            if (selection.state === 'idle') {
                dispatch(deselectAllValuesInCoreFacet({ facetId }));
            }
            this.toggleSelect(selection);
        },
        // Must use a function here to properly support inheritance with `this`.
        toggleSingleExclude: function (selection) {
            // TODO CAPI-409: Rework facet type definitions
            if (!props.options.toggleExcludeActionCreator) {
                engine.logger.warn('No toggle exclude action creator provided; calling #toggleSingleExclude had no effect.');
                return;
            }
            if (selection.state === 'idle') {
                dispatch(deselectAllValuesInCoreFacet({ facetId }));
            }
            this.toggleExclude(selection);
        },
        isValueSelected: (value) => {
            return value.state === 'selected';
        },
        isValueExcluded: (value) => {
            return value.state === 'excluded';
        },
        deselectAll() {
            dispatch(deselectAllValuesInCoreFacet({ facetId }));
            dispatch(props.options.fetchProductsActionCreator());
        },
        showMoreValues() {
            const numberInState = getRequest()?.numberOfValues ?? 0;
            const initialNumberOfValues = getRequest()?.initialNumberOfValues ?? 0;
            const numberToNextMultipleOfConfigured = initialNumberOfValues - (numberInState % initialNumberOfValues);
            const numberOfValues = numberInState + numberToNextMultipleOfConfigured;
            dispatch(updateCoreFacetNumberOfValues({ facetId, numberOfValues }));
            dispatch(updateCoreFacetIsFieldExpanded({ facetId, isFieldExpanded: true }));
            dispatch(props.options.fetchProductsActionCreator());
        },
        showLessValues() {
            const initialNumberOfValues = getRequest()?.initialNumberOfValues ?? 0;
            const newNumberOfValues = Math.max(initialNumberOfValues, getNumberOfActiveValues());
            dispatch(updateCoreFacetNumberOfValues({
                facetId,
                numberOfValues: newNumberOfValues,
            }));
            dispatch(updateCoreFacetIsFieldExpanded({ facetId, isFieldExpanded: false }));
            dispatch(props.options.fetchProductsActionCreator());
        },
        get state() {
            return getCoreFacetState(facetId, getRequest(), getResponse(), getIsLoading());
        },
    };
}
function loadCommerceFacetReducers(engine) {
    engine.addReducers({ commerceFacetSet });
    return true;
}
const canShowLessValues = (request) => {
    if (!request) {
        return false;
    }
    const initialNumberOfValues = request.initialNumberOfValues;
    const hasIdleValues = !!request.values.find((v) => v.state === 'idle');
    return ((initialNumberOfValues ?? 0) < (request.numberOfValues ?? 0) &&
        hasIdleValues);
};
export const getCoreFacetState = (facetId, request, response, isLoading) => {
    return {
        canShowLessValues: canShowLessValues(request),
        canShowMoreValues: response?.moreValuesAvailable ?? false,
        displayName: response?.displayName ?? '',
        facetId: facetId,
        field: response?.field ?? '',
        hasActiveValues: !response || response.type === 'hierarchical'
            ? false
            : response.values.some((v) => v.state !== 'idle'),
        isLoading,
        type: response?.type ?? 'regular',
        values: response?.values ? response.values : [],
    };
};
