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 { commerceCategoryFacetSearchSetReducer as categoryFacetSearchSet } from '../../../features/commerce/facets/facet-search-set/category/commerce-category-facet-search-set-slice.js';
import { getFacetIdWithCommerceFieldSuggestionNamespace } from '../../../features/commerce/facets/facet-search-set/commerce-facet-search-actions.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 { selectCategoryFacetSearchResult } from '../../../features/facets/facet-search-set/category/category-facet-search-actions.js';
import { loadReducerError } from '../../../utils/errors.js';
import { buildController, } from '../../controller/headless-controller.js';
import { buildCategoryFacetSearch } from '../core/facets/category/headless-commerce-category-facet-search.js';
/**
 * The `CategoryFilterSuggestions` controller provides methods to request and interact with category 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 `CategoryFilterSuggestions` controller.
 * @returns A `CategoryFilterSuggestions` controller instance.
 *
 * @group Buildable controllers
 * @category CategoryFilterSuggestions
 */
export function buildCategoryFilterSuggestions(engine, options) {
    if (!loadCategoryFilterSuggestionsReducers(engine)) {
        throw loadReducerError;
    }
    const { dispatch } = engine;
    const namespacedFacetId = getFacetIdWithCommerceFieldSuggestionNamespace(options.facetId);
    const facetSearch = buildCategoryFacetSearch(engine, {
        options: {
            facetId: namespacedFacetId,
            ...options.facetSearch,
        },
        select: () => { },
        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.categoryFacetSearchSet[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,
            cf: { [options.facetId]: [...value.path, value.rawValue] },
        }),
        select: (value) => {
            dispatch(clearAllCoreFacets());
            dispatch(selectCategoryFacetSearchResult({ facetId: options.facetId, value }));
            dispatch(updateQuery({
                query: engine[stateKey].categoryFacetSearchSet[namespacedFacetId].options
                    .query,
            }));
            dispatch(options.fetchProductsActionCreator());
        },
        get state() {
            const { displayName, field, facetId } = facetForFieldSuggestionsSelector(getState());
            return {
                displayName,
                field,
                facetId,
                ...facetSearchStateSelector(getState()),
            };
        },
        type: 'hierarchical',
    };
}
function loadCategoryFilterSuggestionsReducers(engine) {
    engine.addReducers({
        categoryFacetSearchSet,
        commerceFacetSet,
        commerceQuery,
        fieldSuggestionsOrder,
    });
    return true;
}
