import { RecordValue, Schema } from '@coveo/bueno';
import { createSelector } from '@reduxjs/toolkit';
import { stateKey } from '../../../../app/state-key.js';
import { parametersReducer as commerceParameters } from '../../../../features/commerce/parameters/parameters-slice.js';
import { deepEqualAnyOrder } from '../../../../utils/compare-utils.js';
import { loadReducerError } from '../../../../utils/errors.js';
import { validateInitialState } from '../../../../utils/validate-payload.js';
import { buildController, } from '../../../controller/headless-controller.js';
const initialStateSchema = (parametersDefinition) => new Schema({
    parameters: new RecordValue({
        options: { required: true },
        values: parametersDefinition,
    }),
});
/**
 * @internal
 * Creates a `ParameterManager` sub-controller instance.
 *
 * @param engine - The headless commerce engine.
 * @param props - The configurable `ParameterManager` properties.
 * @returns A `ParameterManager` sub-controller instance.
 */
export function buildCoreParameterManager(engine, props) {
    if (props.excludeDefaultParameters && !loadParameterManagerReducers(engine)) {
        throw loadReducerError;
    }
    const parametersSelector = createSelector((state) => state.commerceParameters, (parameters) => parameters);
    const { dispatch } = engine;
    const controller = buildController(engine);
    if (props.initialState) {
        validateInitialState(engine, initialStateSchema(props.parametersDefinition), props.initialState, 'buildCoreParameterManager');
        dispatch(props.restoreActionCreator(props.initialState.parameters));
    }
    return {
        ...controller,
        synchronize(parameters) {
            const activeParams = props.activeParametersSelector(engine[stateKey]);
            // Always restore empty parameters or parameters that are different from the active ones.
            // We always restore empty parameters in commerce because they may correspond to navigation to a new page.
            if (Object.keys(parameters).length > 0 &&
                deepEqualAnyOrder(activeParams, parameters)) {
                return;
            }
            dispatch(props.restoreActionCreator(parameters));
            dispatch(props.fetchProductsActionCreator());
        },
        get state() {
            return {
                parameters: props.excludeDefaultParameters
                    ? parametersSelector(engine[stateKey])
                    : props.activeParametersSelector(engine[stateKey]),
            };
        },
    };
}
function loadParameterManagerReducers(engine) {
    engine.addReducers({
        commerceParameters,
    });
    return true;
}
