import { createSelector } from '@reduxjs/toolkit';
import { stateKey } from '../../../app/state-key.js';
import { clearAllCoreFacets } from '../../../features/commerce/facets/core-facet/core-facet-actions.js';
import { getFacetIdWithCommerceFieldSuggestionNamespace } from '../../../features/commerce/facets/facet-search-set/commerce-facet-search-actions.js';
import { commerceSpecificFacetSearchSetReducer as facetSearchSet } from '../../../features/commerce/facets/facet-search-set/regular/commerce-specific-facet-search-set-slice.js';
import { commerceFacetSetReducer as commerceFacetSet } from '../../../features/commerce/facets/facet-set/facet-set-slice.js';
import { fieldSuggestionsOrderReducer as fieldSuggestionsOrder } from '../../../features/commerce/facets/field-suggestions-order/field-suggestions-order-slice.js';
import { searchSerializer } from '../../../features/commerce/parameters/parameters-serializer.js';
import { updateQuery } from '../../../features/commerce/query/query-actions.js';
import { queryReducer as commerceQuery } from '../../../features/commerce/query/query-slice.js';
import { selectFacetSearchResult } from '../../../features/facets/facet-search-set/specific/specific-facet-search-actions.js';
import { loadReducerError } from '../../../utils/errors.js';
import { buildController, } from '../../controller/headless-controller.js';
import { buildRegularFacetSearch, } from '../core/facets/regular/headless-commerce-regular-facet-search.js';
/**
 * The `FilterSuggestions` controller provides methods to request and interact with facet suggestions based on a
 * specific field for a given search query.
 *
 * @alpha  This controller relies on a Commerce API functionality that is not yet generally available. If you wish to use this
 * feature in an implementation, please contact your Coveo representative.
 *
 * @param engine - The headless commerce engine.
 * @param options - The options for the `FilterSuggestions` controller.
 * @returns A `FilterSuggestions` controller instance.
 *
 * @group Buildable controllers
 * @category FilterSuggestions
 */
export function buildFilterSuggestions(engine, options) {
    if (!loadFilterSuggestionsReducers(engine)) {
        throw loadReducerError;
    }
    const { dispatch } = engine;
    const namespacedFacetId = getFacetIdWithCommerceFieldSuggestionNamespace(options.facetId);
    const facetSearch = buildRegularFacetSearch(engine, {
        options: { facetId: namespacedFacetId, ...options.facetSearch },
        select: () => { },
        exclude: () => { },
        isForFieldSuggestions: true,
    });
    const getState = () => engine[stateKey];
    const controller = buildController(engine);
    const facetForFieldSuggestionsSelector = createSelector((state) => state.fieldSuggestionsOrder, (facets) => facets.find((facet) => facet.facetId === options.facetId));
    const facetSearchStateSelector = createSelector((state) => state.facetSearchSet[namespacedFacetId], (facetSearch) => ({
        isLoading: facetSearch.isLoading,
        moreValuesAvailable: facetSearch.response.moreValuesAvailable,
        query: facetSearch.options.query,
        values: facetSearch.response.values,
    }));
    const { clear } = facetSearch;
    return {
        ...controller,
        clear,
        updateQuery: (text) => {
            facetSearch.updateText(text);
            facetSearch.search();
        },
        getSearchParameters: (value) => searchSerializer.serialize({
            q: facetSearchStateSelector(getState()).query,
            f: { [options.facetId]: [value.rawValue] },
        }),
        select: (value) => {
            dispatch(clearAllCoreFacets());
            dispatch(selectFacetSearchResult({ facetId: options.facetId, value }));
            dispatch(updateQuery({
                query: engine[stateKey].facetSearchSet[namespacedFacetId].options.query,
            }));
            dispatch(options.fetchProductsActionCreator());
        },
        get state() {
            const { displayName, field, facetId } = facetForFieldSuggestionsSelector(getState());
            return {
                displayName,
                field,
                facetId,
                ...facetSearchStateSelector(getState()),
            };
        },
        type: 'regular',
    };
}
function loadFilterSuggestionsReducers(engine) {
    engine.addReducers({
        commerceFacetSet,
        commerceQuery,
        facetSearchSet,
        fieldSuggestionsOrder,
    });
    return true;
}
