import { getRelayInstanceFromState } from '../api/analytics/analytics-relay-client.js';
import { answerApi } from '../api/knowledge/stream-answer-api.js';
import { disableAnalytics, enableAnalytics, updateAnalyticsConfiguration, updateBasicConfiguration, } from '../features/configuration/configuration-actions.js';
import { versionReducer as version } from '../features/debug/version-slice.js';
import { doNotTrack } from '../utils/utils.js';
import { analyticsMiddleware } from './analytics-middleware.js';
import { configuration } from './common-reducers.js';
import { instantlyCallableThunkActionMiddleware } from './instantly-callable-middleware.js';
import { createGenerateAnswerListener } from './listener-middleware/generate-answer-listener-middleware.js';
import { logActionErrorMiddleware } from './logger-middlewares.js';
import { getNavigatorContext, } from './navigator-context-provider.js';
import { createReducerManager } from './reducer-manager.js';
import { createRenewAccessTokenMiddleware } from './renew-access-token-middleware.js';
import { stateKey } from './state-key.js';
import { configureStore } from './store.js';
function getUpdateAnalyticsConfigurationPayload(configuration, logger) {
    const { analytics } = configuration;
    const { analyticsClientMiddleware: _, ...payload } = analytics ?? {};
    const payloadWithURL = {
        ...payload,
        ...(analytics?.proxyBaseUrl && {
            apiBaseUrl: analytics.proxyBaseUrl,
            nexApiBaseUrl: analytics.proxyBaseUrl,
        }),
    };
    // TODO KIT-2844
    if (payloadWithURL.analyticsMode !== 'next' && doNotTrack()) {
        logger.info('Analytics disabled since doNotTrack is active.');
        return {
            ...payloadWithURL,
            enabled: false,
        };
    }
    return payloadWithURL;
}
export function buildEngine(options, thunkExtraArguments) {
    const reducers = {
        ...options.reducers,
        configuration,
        version,
    };
    const engine = buildCoreEngine({ ...options, reducers }, thunkExtraArguments, configuration);
    const { accessToken, environment, organizationId } = options.configuration;
    engine.dispatch(updateBasicConfiguration({
        accessToken,
        environment,
        organizationId,
    }));
    const analyticsPayload = getUpdateAnalyticsConfigurationPayload(options.configuration, engine.logger);
    if (analyticsPayload) {
        engine.dispatch(updateAnalyticsConfiguration(analyticsPayload));
    }
    return engine;
}
export function buildCoreEngine(options, thunkExtraArguments, configurationReducer) {
    const { reducers, navigatorContextProvider } = options;
    const reducerManager = createReducerManager({ ...reducers, configurationReducer }, options.preloadedState ?? {});
    if (options.crossReducer) {
        reducerManager.addCrossReducer(options.crossReducer);
    }
    const logger = thunkExtraArguments.logger;
    const thunkExtraArgumentsWithRelay = {
        ...thunkExtraArguments,
        get relay() {
            return getRelayInstanceFromState(engine.state, navigatorContextProvider);
        },
        get navigatorContext() {
            return getNavigatorContext(this.relay, navigatorContextProvider);
        },
    };
    const store = createStore(options, thunkExtraArgumentsWithRelay, reducerManager);
    const engine = {
        addReducers(reducers) {
            if (reducerManager.containsAll(reducers)) {
                return;
            }
            reducerManager.add(reducers);
            store.replaceReducer(reducerManager.combinedReducer);
        },
        dispatch: store.dispatch,
        subscribe: store.subscribe,
        enableAnalytics() {
            store.dispatch(enableAnalytics());
        },
        disableAnalytics() {
            store.dispatch(disableAnalytics());
        },
        get state() {
            return store.getState();
        },
        get relay() {
            return getRelayInstanceFromState(this.state, navigatorContextProvider);
        },
        get navigatorContext() {
            return getNavigatorContext(this.relay, navigatorContextProvider);
        },
        logger,
        store,
    };
    return engine;
}
function createStore(options, thunkExtraArguments, reducerManager) {
    const { preloadedState, configuration } = options;
    const name = configuration.name || 'coveo-headless';
    const middlewares = createMiddleware(options, thunkExtraArguments.logger, () => thunkExtraArguments.navigatorContext);
    return configureStore({
        preloadedState,
        reducer: reducerManager.combinedReducer,
        middlewares,
        thunkExtraArguments,
        name,
    });
}
function createMiddleware(options, logger, getNavigatorContext) {
    const { renewAccessToken } = options.configuration;
    const renewTokenMiddleware = createRenewAccessTokenMiddleware(logger, renewAccessToken);
    const generateAnswerListener = createGenerateAnswerListener({
        getNavigatorContext,
    });
    return [
        instantlyCallableThunkActionMiddleware,
        renewTokenMiddleware,
        logActionErrorMiddleware(logger),
        analyticsMiddleware,
    ].concat(answerApi.middleware, generateAnswerListener.middleware, options.middlewares || []);
}
export const nextAnalyticsUsageWithServiceFeatureWarning = '[Warning] A component from the Coveo Headless library has been instantiated with the Analytics Mode: "Next".\n' +
    'However, this mode is not available for Coveo for Service features, and this configuration may not work as expected.\n' +
    'Please switch back to the "legacy" analytics mode to ensure proper functionality.\n' +
    'For more information, refer to the documentation: https://docs.coveo.com/en/o3r90189/build-a-search-ui/event-protocol';
export function warnIfUsingNextAnalyticsModeForServiceFeature(analyticsMode) {
    if (analyticsMode === 'next') {
        console.warn(nextAnalyticsUsageWithServiceFeatureWarning);
    }
}
