import { isNullOrUndefined } from '@coveo/bueno';
import { isErrorResponse, } from '../../../api/commerce/commerce-api-client.js';
import { buildFilterableCommerceAPIRequest, } from '../common/filterable-commerce-api-request-builder.js';
import { updateQuery } from '../query/query-actions.js';
import { applyQueryTriggerModification, updateIgnoreQueryTrigger, } from '../triggers/triggers-actions.js';
import { queryExecutedFromResponseSelector } from './search-selectors.js';
export class AsyncSearchThunkProcessor {
    config;
    constructor(config) {
        this.config = config;
    }
    async process(fetched) {
        return (this.processQueryErrorOrContinue(fetched) ??
            (await this.processQueryCorrectionsOrContinue(fetched)) ??
            (await this.processQueryTriggersOrContinue(fetched)) ??
            this.processSuccessResponse(fetched));
    }
    async fetchFromAPI(request) {
        const startedAt = Date.now();
        const response = await this.extra.apiClient.search(request);
        const duration = Date.now() - startedAt;
        const queryExecuted = this.getState().commerceQuery.query || '';
        return { response, duration, queryExecuted, requestExecuted: request };
    }
    processSuccessResponse(fetched) {
        return {
            ...fetched,
            response: this.getSuccessResponse(fetched),
            originalQuery: this.getCurrentQuery(),
        };
    }
    processQueryErrorOrContinue(fetched) {
        if (isErrorResponse(fetched.response)) {
            return this.rejectWithValue(fetched.response.error);
        }
        return null;
    }
    async processQueryCorrectionsOrContinue(fetched) {
        const state = this.getState();
        const successResponse = this.getSuccessResponse(fetched);
        if (!successResponse || !state.didYouMean) {
            return null;
        }
        const { queryCorrection } = successResponse;
        const shouldExecuteQueryCorrection = !isNullOrUndefined(queryCorrection) &&
            !isNullOrUndefined(queryCorrection.correctedQuery);
        if (!shouldExecuteQueryCorrection) {
            return null;
        }
        const { correctedQuery, originalQuery } = successResponse.queryCorrection;
        this.onUpdateQueryForCorrection(correctedQuery ?? '');
        return {
            ...fetched,
            response: {
                ...successResponse,
            },
            queryExecuted: queryExecutedFromResponseSelector(state, successResponse),
            originalQuery: originalQuery ?? '',
        };
    }
    async processQueryTriggersOrContinue(fetched) {
        const successResponse = this.getSuccessResponse(fetched);
        if (!successResponse) {
            return null;
        }
        const correctedQuery = successResponse.triggers.find((trigger) => trigger.type === 'query')
            ?.content || '';
        if (!correctedQuery) {
            return null;
        }
        const ignored = this.getState().triggers?.queryModification.queryToIgnore;
        if (ignored === correctedQuery) {
            this.dispatch(updateIgnoreQueryTrigger({ q: '' }));
            return null;
        }
        const originalQuery = this.getCurrentQuery();
        const retried = await this.automaticallyRetryQueryWithTriggerModification(correctedQuery);
        if (isErrorResponse(retried.response)) {
            return this.rejectWithValue(retried.response.error);
        }
        return {
            ...retried,
            response: {
                ...retried.response.success,
            },
            originalQuery,
        };
    }
    async automaticallyRetryQueryWithTriggerModification(modified) {
        this.dispatch(applyQueryTriggerModification({
            newQuery: modified,
            originalQuery: this.getCurrentQuery(),
        }));
        this.onUpdateQueryForCorrection(modified);
        const fetched = await this.fetchFromAPI({
            ...buildFilterableCommerceAPIRequest(this.getState(), this.navigatorContext),
            query: modified,
        });
        return fetched;
    }
    get dispatch() {
        return this.config.dispatch;
    }
    get rejectWithValue() {
        return this.config.rejectWithValue;
    }
    getState() {
        return this.config.getState();
    }
    get navigatorContext() {
        return this.config.extra.navigatorContext;
    }
    getCurrentQuery() {
        const state = this.getState();
        return state.commerceQuery.query !== undefined
            ? state.commerceQuery.query
            : '';
    }
    getSuccessResponse(fetched) {
        if (isErrorResponse(fetched.response)) {
            return null;
        }
        return fetched.response.success;
    }
    get extra() {
        return this.config.extra;
    }
    onUpdateQueryForCorrection(modification) {
        this.dispatch(updateQuery({ query: modification }));
    }
}
