import { configuration } from '../../../app/common-reducers.js';
import { updateFacetOptions } from '../../../features/facet-options/facet-options-actions.js';
import { executeFacetSearch, executeFieldSuggest, } from '../../../features/facets/facet-search-set/generic/generic-facet-search-actions.js';
import { specificFacetSearchSetReducer as facetSearchSet } from '../../../features/facets/facet-search-set/specific/specific-facet-search-set-slice.js';
import { facetClearAll, facetExclude, facetSelect, logFacetClearAll, logFacetExclude, logFacetSelect, logFacetShowLess, logFacetShowMore, logFacetUpdateSort, } from '../../../features/facets/facet-set/facet-set-analytics-actions.js';
import { facetSetReducer as facetSet } from '../../../features/facets/facet-set/facet-set-slice.js';
import { getAnalyticsActionForToggleFacetExclude, getAnalyticsActionForToggleFacetSelect, getLegacyAnalyticsActionForToggleFacetExclude, getLegacyAnalyticsActionForToggleFacetSelect, } from '../../../features/facets/facet-set/facet-set-utils.js';
import { executeSearch, fetchFacetValues, } from '../../../features/search/search-actions.js';
import { searchReducer as search } from '../../../features/search/search-slice.js';
import { loadReducerError } from '../../../utils/errors.js';
import { buildCoreFacet, } from '../../core/facets/facet/headless-core-facet.js';
import { buildFacetSearch } from '../../core/facets/facet-search/specific/headless-facet-search.js';
import { facetOptionsSchema, } from './headless-facet-options.js';
/**
 * Creates a `Facet` controller instance.
 *
 * @param engine - The headless engine.
 * @param props - The configurable `Facet` properties.
 * @returns A `Facet` controller instance.
 *
 * @group Controllers
 * @category Facet
 * */
export function buildFacet(engine, props) {
    if (!loadFacetReducers(engine)) {
        throw loadReducerError;
    }
    const { dispatch } = engine;
    const coreController = buildCoreFacet(engine, {
        ...props,
        options: {
            ...props.options,
            ...(props.options.allowedValues && {
                allowedValues: {
                    type: 'simple',
                    values: props.options.allowedValues,
                },
            }),
        },
    }, facetOptionsSchema);
    const getFacetId = () => coreController.state.facetId;
    const createFacetSearch = () => {
        const { facetSearch } = props.options;
        return buildFacetSearch(engine, {
            options: { facetId: getFacetId(), ...facetSearch },
            select: (value) => {
                dispatch(updateFacetOptions());
                dispatch(executeSearch({
                    legacy: logFacetSelect({
                        facetId: getFacetId(),
                        facetValue: value.rawValue,
                    }),
                    next: facetSelect(),
                }));
            },
            exclude: (value) => {
                dispatch(updateFacetOptions());
                dispatch(executeSearch({
                    legacy: logFacetExclude({
                        facetId: getFacetId(),
                        facetValue: value.rawValue,
                    }),
                    next: facetExclude(),
                }));
            },
            isForFieldSuggestions: false,
            executeFacetSearchActionCreator: executeFacetSearch,
            executeFieldSuggestActionCreator: executeFieldSuggest,
        });
    };
    const facetSearch = createFacetSearch();
    const { state, ...restOfFacetSearch } = facetSearch;
    return {
        ...coreController,
        facetSearch: restOfFacetSearch,
        toggleSelect(selection) {
            coreController.toggleSelect(selection);
            dispatch(executeSearch({
                legacy: getLegacyAnalyticsActionForToggleFacetSelect(getFacetId(), selection),
                next: getAnalyticsActionForToggleFacetSelect(selection),
            }));
        },
        toggleExclude(selection) {
            coreController.toggleExclude(selection);
            dispatch(executeSearch({
                legacy: getLegacyAnalyticsActionForToggleFacetExclude(getFacetId(), selection),
                next: getAnalyticsActionForToggleFacetExclude(selection),
            }));
        },
        deselectAll() {
            coreController.deselectAll();
            dispatch(executeSearch({
                legacy: logFacetClearAll(getFacetId()),
                next: facetClearAll(),
            }));
        },
        sortBy(criterion) {
            coreController.sortBy(criterion);
            dispatch(executeSearch({
                legacy: logFacetUpdateSort({ facetId: getFacetId(), criterion }),
            }));
        },
        isSortedBy(criterion) {
            return this.state.sortCriterion === criterion;
        },
        showMoreValues() {
            coreController.showMoreValues();
            dispatch(fetchFacetValues({ legacy: logFacetShowMore(getFacetId()) }));
        },
        showLessValues() {
            coreController.showLessValues();
            dispatch(fetchFacetValues({ legacy: logFacetShowLess(getFacetId()) }));
        },
        get state() {
            return {
                ...coreController.state,
                facetSearch: facetSearch.state,
            };
        },
    };
}
function loadFacetReducers(engine) {
    engine.addReducers({ facetSet, configuration, facetSearchSet, search });
    return true;
}
