import { Schema } from '@coveo/bueno';
import { stateKey } from '../../../../app/state-key.js';
import { buildFieldsSortCriterion, buildRelevanceSortCriterion, SortBy, SortDirection, sortCriterionDefinition, } from '../../../../features/commerce/sort/sort.js';
import { applySort } from '../../../../features/commerce/sort/sort-actions.js';
import { sortReducer as commerceSort } from '../../../../features/commerce/sort/sort-slice.js';
import { loadReducerError } from '../../../../utils/errors.js';
import { validateInitialState } from '../../../../utils/validate-payload.js';
import { buildController, } from '../../../controller/headless-controller.js';
export { buildFieldsSortCriterion, buildRelevanceSortCriterion, SortBy, SortDirection, };
function validateSortInitialState(engine, state) {
    if (!state) {
        return;
    }
    const schema = new Schema({
        criterion: sortCriterionDefinition,
    });
    validateInitialState(engine, schema, state, 'buildSort');
}
/**
 * @internal
 * Creates a core `Sort` sub-controller instance for commerce solution types.
 *
 * @param engine - The headless commerce engine.
 * @param props - The configurable `Sort` sub-controller properties.
 * @returns A `Sort` sub-controller instance.
 */
export function buildCoreSort(engine, props) {
    if (!loadSortReducers(engine)) {
        throw loadReducerError;
    }
    const { dispatch } = engine;
    const controller = buildController(engine);
    validateSortInitialState(engine, props.initialState);
    const criterion = props.initialState?.criterion;
    if (criterion) {
        dispatch(applySort(criterion));
    }
    return {
        ...controller,
        get state() {
            return engine[stateKey].commerceSort;
        },
        sortBy(criterion) {
            dispatch(applySort(criterion));
            dispatch(props.fetchProductsActionCreator());
        },
        isSortedBy(criterion) {
            return (JSON.stringify(this.state.appliedSort) === JSON.stringify(criterion));
        },
        isAvailable(criterion) {
            return this.state.availableSorts.some((availableCriterion) => JSON.stringify(availableCriterion) === JSON.stringify(criterion));
        },
    };
}
function loadSortReducers(engine) {
    engine.addReducers({ commerceSort });
    return true;
}
