import { createSelector } from '@reduxjs/toolkit';
import { stateKey } from '../../../../app/state-key.js';
import { clearAllCoreFacets, deselectAllValuesInCoreFacet, updateCoreFacetFreezeCurrentValues, } from '../../../../features/commerce/facets/core-facet/core-facet-actions.js';
import { toggleExcludeDateFacetValue, toggleSelectDateFacetValue, } from '../../../../features/commerce/facets/date-facet/date-facet-actions.js';
import { commerceFacetOrderReducer as facetOrder } from '../../../../features/commerce/facets/facet-order/commerce-facet-order-slice.js';
import { commerceFacetSetReducer as commerceFacetSet } from '../../../../features/commerce/facets/facet-set/facet-set-slice.js';
import { toggleSelectLocationFacetValue } from '../../../../features/commerce/facets/location-facet/location-facet-actions.js';
import { toggleExcludeNumericFacetValue, toggleSelectNumericFacetValue, } from '../../../../features/commerce/facets/numeric-facet/numeric-facet-actions.js';
import { toggleExcludeFacetValue, toggleSelectFacetValue, } from '../../../../features/commerce/facets/regular-facet/regular-facet-actions.js';
import { findActiveValueAncestry } from '../../../../features/facets/category-facet-set/category-facet-utils.js';
import { loadReducerError } from '../../../../utils/errors.js';
import { buildController } from '../../../controller/headless-controller.js';
const actions = {
    regular: {
        toggleSelectActionCreator: toggleSelectFacetValue,
        toggleExcludeActionCreator: toggleExcludeFacetValue,
    },
    numericalRange: {
        toggleSelectActionCreator: toggleSelectNumericFacetValue,
        toggleExcludeActionCreator: toggleExcludeNumericFacetValue,
    },
    dateRange: {
        toggleSelectActionCreator: toggleSelectDateFacetValue,
        toggleExcludeActionCreator: toggleExcludeDateFacetValue,
    },
    location: {
        toggleSelectActionCreator: toggleSelectLocationFacetValue,
    },
    hierarchical: {
        toggleSelectActionCreator: deselectAllValuesInCoreFacet,
    },
};
/**
 * @internal
 * Creates a `BreadcrumbManager` sub-controller.
 *
 * @param engine - The headless commerce engine.
 * @param options - The `BreadcrumbManager` options used internally.
 * @returns A `BreadcrumbManager` sub-controller.
 **/
export function buildCoreBreadcrumbManager(engine, options) {
    if (!loadCommerceBreadcrumbManagerReducers(engine)) {
        throw loadReducerError;
    }
    const controller = buildController(engine);
    const { dispatch } = engine;
    const createBreadcrumb = (facet) => ({
        facetId: facet.facetId,
        facetDisplayName: facet.displayName,
        field: facet.field,
        type: facet.type,
        values: facet.type === 'hierarchical'
            ? getValuesForCategoryFacet(facet)
            : getValuesForNonCategoryFacet(facet),
    });
    const getValuesForNonCategoryFacet = (facet) => {
        return facet.values
            .filter((value) => value.state !== 'idle')
            .map((selection) => ({
            value: selection,
            deselect: () => {
                if (selection.state === 'selected') {
                    dispatch(actions[facet.type].toggleSelectActionCreator({
                        facetId: facet.facetId,
                        selection,
                    }));
                    if (facet.type !== 'location') {
                        dispatch(updateCoreFacetFreezeCurrentValues({
                            facetId: facet.facetId,
                            freezeCurrentValues: false,
                        }));
                    }
                    dispatch(options.fetchProductsActionCreator());
                }
                else if (selection.state === 'excluded' &&
                    facet.type !== 'location') {
                    dispatch(actions[facet.type].toggleExcludeActionCreator({
                        facetId: facet.facetId,
                        selection,
                    }));
                    dispatch(updateCoreFacetFreezeCurrentValues({
                        facetId: facet.facetId,
                        freezeCurrentValues: false,
                    }));
                    dispatch(options.fetchProductsActionCreator());
                }
            },
        }));
    };
    const getValuesForCategoryFacet = (facet) => {
        const ancestry = findActiveValueAncestry(facet.values);
        const activeValue = ancestry.length > 0 ? ancestry[ancestry.length - 1] : undefined;
        if (activeValue === undefined) {
            return [];
        }
        return [
            {
                value: activeValue,
                deselect: () => {
                    dispatch(actions.hierarchical.toggleSelectActionCreator({
                        facetId: facet.facetId,
                    }));
                    dispatch(options.fetchProductsActionCreator());
                },
            },
        ];
    };
    const hasActiveValue = (facet) => {
        if (!facet) {
            return false;
        }
        if (facet.values.length === 0) {
            return false;
        }
        if (facet.type === 'hierarchical') {
            return findActiveValueAncestry(facet.values).length > 0;
        }
        return facet.values.some((value) => value.state !== 'idle');
    };
    const commerceFacetSelector = createSelector((state) => state.facetOrder, (facetOrder) => {
        const breadcrumbs = facetOrder.flatMap((facetId) => {
            const facet = options.facetResponseSelector(engine[stateKey], facetId);
            if (hasActiveValue(facet)) {
                return [createBreadcrumb(facet)];
            }
            return [];
        });
        return {
            facetBreadcrumbs: breadcrumbs,
            hasBreadcrumbs: breadcrumbs.length > 0,
        };
    });
    return {
        ...controller,
        deselectAll: () => {
            dispatch(clearAllCoreFacets());
            dispatch(options.fetchProductsActionCreator());
        },
        get state() {
            return commerceFacetSelector(engine[stateKey]);
        },
    };
}
function loadCommerceBreadcrumbManagerReducers(engine) {
    engine.addReducers({ facetOrder, commerceFacetSet });
    return true;
}
