import { buildProductListing } from '../../../controllers/commerce/product-listing/headless-product-listing.js';
import { buildSearch } from '../../../controllers/commerce/search/headless-search.js';
import { augmentPreprocessRequestWithForwardedFor } from '../../common/augment-preprocess-request.js';
import { composeFunction } from '../../common/controller-utils.js';
import { createStaticState } from '../controller-utils.js';
import { SolutionType } from '../types/controller-constants.js';
import { buildFactory, } from './build-factory.js';
function findAndExecuteMethod(controllers, methodName) {
    for (const controller of Object.values(controllers)) {
        if (typeof Object.getOwnPropertyDescriptor(controller, methodName)?.value ===
            'function') {
            controller[methodName]();
            return true;
        }
    }
    return false;
}
function executeFirstRequestForListing(controllers, engine) {
    const controllerExecuted = findAndExecuteMethod(controllers, 'executeFirstRequest');
    if (!controllerExecuted) {
        buildProductListing(engine).executeFirstRequest();
    }
}
function executeFirstSearchForSearch(controllers, engine) {
    const controllerExecuted = findAndExecuteMethod(controllers, 'executeFirstSearch');
    if (!controllerExecuted) {
        buildSearch(engine).executeFirstSearch();
    }
}
export const fetchStaticStateFactory = (controllerDefinitions, options) => (solutionType) => composeFunction(async (...params) => {
    const solutionTypeBuild = await buildFactory(controllerDefinitions, {
        ...options,
    })(solutionType);
    const buildResult = await solutionTypeBuild(...params);
    options.configuration.preprocessRequest =
        augmentPreprocessRequestWithForwardedFor({
            preprocessRequest: options.configuration.preprocessRequest,
            navigatorContextProvider: options.navigatorContextProvider,
            loggerOptions: options.loggerOptions,
        });
    const staticStateBuild = await fetchStaticStateFactory(controllerDefinitions, options)(solutionType);
    const staticState = await staticStateBuild.fromBuildResult({
        buildResult,
    });
    return staticState;
}, {
    fromBuildResult: async (...params) => {
        const [{ buildResult: { engine, controllers }, },] = params;
        switch (solutionType) {
            case SolutionType.listing:
                executeFirstRequestForListing(controllers, engine);
                break;
            case SolutionType.search:
                executeFirstSearchForSearch(controllers, engine);
                break;
        }
        const searchActions = await Promise.all(engine.waitForRequestCompletedAction());
        return createStaticState({
            searchActions,
            controllers,
        });
    },
});
