import { ensureAtLeastOneSolutionType } from '../../../../../app/commerce-ssr-engine/common.js';
import { SolutionType, } from '../../../../../app/commerce-ssr-engine/types/common.js';
import { stateKey } from '../../../../../app/state-key.js';
import { facetRequestSelector } from '../../../../../features/commerce/facets/facet-set/facet-set-selector.js';
import { manualNumericFacetSelector } from '../../../../../features/commerce/facets/numeric-facet/manual-numeric-facet-selectors.js';
import { manualNumericFacetReducer as manualNumericFacetSet } from '../../../../../features/commerce/facets/numeric-facet/manual-numeric-facet-slice.js';
import { categoryFacetSearchStateSelector } from '../../../../../features/facets/facet-search-set/category/category-facet-search-state-selector.js';
import { specificFacetSearchStateSelector } from '../../../../../features/facets/facet-search-set/specific/specific-facet-search-state-selector.js';
import { loadReducerError } from '../../../../../utils/errors.js';
import { facetResponseSelector as listingFacetResponseSelector, isFacetLoadingResponseSelector as listingIsFacetLoadingResponseSelector, } from '../../../product-listing/facets/headless-product-listing-facet-options.js';
import { buildProductListing } from '../../../product-listing/headless-product-listing.js';
import { facetResponseSelector as searchFacetResponseSelector, isFacetLoadingResponseSelector as searchIsFacetLoadingResponseSelector, } from '../../../search/facets/headless-search-facet-options.js';
import { buildSearch } from '../../../search/headless-search.js';
import { getCategoryFacetState } from '../category/headless-commerce-category-facet.js';
import { getDateFacetState } from '../date/headless-commerce-date-facet.js';
import { getCoreFacetState } from '../headless-core-commerce-facet.js';
import { getLocationFacetState } from '../location/headless-commerce-location-facet.js';
import { getNumericFacetState } from '../numeric/headless-commerce-numeric-facet.js';
import { getRegularFacetState } from '../regular/headless-commerce-regular-facet.js';
/**
 * @group Definers
 */
export function defineFacetGenerator(options) {
    ensureAtLeastOneSolutionType(options);
    return {
        listing: true,
        search: true,
        ...options,
        build: (engine, solutionType) => buildFacetGenerator(engine, { props: { solutionType: solutionType } }),
    };
}
/**
 * Creates a `FacetGenerator` sub-controller for server-side rendering purposes (SSR).
 *
 * @param engine - The SSR commerce engine.
 * @param options - The facet generator options used internally.
 * @returns A `FacetGenerator` sub-controller.
 */
export function buildFacetGenerator(engine, options) {
    if (!loadFacetGeneratorReducers(engine)) {
        throw loadReducerError;
    }
    const getEngineState = () => engine[stateKey];
    const solutionType = options.props.solutionType;
    const getFacetResponseSelector = (facetId) => {
        return solutionType === SolutionType.listing
            ? listingFacetResponseSelector(getEngineState(), facetId)
            : searchFacetResponseSelector(getEngineState(), facetId);
    };
    const isFacetLoadingResponseSelector = solutionType === SolutionType.listing
        ? listingIsFacetLoadingResponseSelector(getEngineState())
        : searchIsFacetLoadingResponseSelector(getEngineState());
    const createFacetState = (facetResponseSelector) => {
        const facetId = facetResponseSelector.facetId;
        return getCoreFacetState(facetId, facetRequestSelector(getEngineState(), facetId), facetResponseSelector, isFacetLoadingResponseSelector);
    };
    const baseController = solutionType === SolutionType.listing
        ? buildProductListing(engine).facetGenerator()
        : buildSearch(engine).facetGenerator();
    const { state, ...restOfBaseController } = baseController;
    return {
        ...restOfBaseController,
        getFacetController: (facetId, facetType) => {
            const controller = baseController.facets.find((f) => f.state.facetId === facetId && f.type === facetType);
            return controller;
        },
        get state() {
            const facetResponseSelectors = baseController.state
                .map(getFacetResponseSelector)
                .filter((selector) => selector !== undefined);
            return facetResponseSelectors.map((selector) => {
                const facetResponseSelector = selector;
                const facetId = facetResponseSelector.facetId;
                switch (facetResponseSelector.type) {
                    case 'hierarchical':
                        return getCategoryFacetState(createFacetState(facetResponseSelector), categoryFacetSearchStateSelector(getEngineState(), facetId), facetRequestSelector(getEngineState(), facetId));
                    case 'dateRange':
                        return getDateFacetState(createFacetState(facetResponseSelector));
                    case 'numericalRange':
                        return getNumericFacetState(createFacetState(facetResponseSelector), facetResponseSelector, manualNumericFacetSelector(getEngineState(), facetId));
                    case 'regular':
                        return getRegularFacetState(createFacetState(facetResponseSelector), specificFacetSearchStateSelector(getEngineState(), facetId));
                    case 'location':
                        return getLocationFacetState(createFacetState(facetResponseSelector));
                }
            });
        },
    };
}
function loadFacetGeneratorReducers(engine) {
    engine.addReducers({ manualNumericFacetSet });
    return true;
}
