import { NumberValue } from '@coveo/bueno';
import { createAsyncThunk } from '@reduxjs/toolkit';
import HistoryStore from '../../../api/analytics/coveo.analytics/history-store.js';
import { requiredNonEmptyString, validatePayload, } from '../../../utils/validate-payload.js';
import { logInstantResultsSearch } from '../../instant-results/instant-result-analytics-actions.js';
import { updateInstantResultsQuery, } from '../../instant-results/instant-results-actions.js';
import { buildSearchAndFoldingLoadCollectionRequest } from '../../search-and-folding/legacy/search-and-folding-request.js';
import { updateSearchAction } from '../search-actions.js';
import { logFetchMoreResults } from '../search-analytics-actions.js';
import { mapSearchRequest, } from '../search-mappings.js';
import { AsyncSearchThunkProcessor, } from './search-actions-thunk-processor.js';
import { buildSearchRequest } from './search-request.js';
export const executeSearch = createAsyncThunk('search/executeSearch', async (searchAction, config) => {
    const state = config.getState();
    return await legacyExecuteSearch(state, config, searchAction);
});
export const fetchPage = createAsyncThunk('search/fetchPage', async (searchAction, config) => {
    const state = config.getState();
    return await legacyFetchPage(state, config, searchAction);
});
export const fetchMoreResults = createAsyncThunk('search/fetchMoreResults', async (_, config) => {
    const state = config.getState();
    return await legacyFetchMoreResults(config, state);
});
export const fetchFacetValues = createAsyncThunk('search/fetchFacetValues', async (searchAction, config) => {
    const state = config.getState();
    return await legacyFetchFacetValues(config, searchAction, state);
});
export const fetchInstantResults = createAsyncThunk('search/fetchInstantResults', async (payload, config) => {
    return legacyFetchInstantResults(payload, config);
});
const buildFetchMoreRequest = async (state, eventDescription) => {
    const mappedRequest = await buildSearchRequest(state, eventDescription);
    mappedRequest.request = {
        ...mappedRequest.request,
        firstResult: (state.pagination?.firstResult ?? 0) +
            (state.search?.results.length ?? 0),
    };
    return mappedRequest;
};
const buildInstantResultSearchRequest = async (state, q, numberOfResults) => {
    const sharedWithFoldingRequest = await buildSearchAndFoldingLoadCollectionRequest(state);
    return mapSearchRequest({
        ...sharedWithFoldingRequest,
        ...(state.didYouMean && {
            enableDidYouMean: state.didYouMean.enableDidYouMean,
        }),
        numberOfResults,
        q,
    });
};
const buildFetchFacetValuesRequest = async (state, eventDescription) => {
    const mappedRequest = await buildSearchRequest(state, eventDescription);
    // Specifying a numberOfResults of 0 will not log the query as a full fledged query in the API
    // it will also alleviate the load on the index
    mappedRequest.request.numberOfResults = 0;
    return mappedRequest;
};
const addEntryInActionsHistory = (state) => {
    if (state.configuration.analytics.enabled) {
        HistoryStore.getInstance().addElement({
            name: 'Query',
            ...(state.query?.q && {
                value: state.query.q,
            }),
            time: JSON.stringify(new Date()),
        });
    }
};
export async function legacyFetchInstantResults(payload, 
// biome-ignore lint/suspicious/noExplicitAny: <>
config) {
    validatePayload(payload, {
        id: requiredNonEmptyString,
        q: requiredNonEmptyString,
        maxResultsPerQuery: new NumberValue({
            required: true,
            min: 1,
        }),
        cacheTimeout: new NumberValue(),
    });
    const { q, maxResultsPerQuery } = payload;
    const state = config.getState();
    const processor = new AsyncSearchThunkProcessor({ ...config, analyticsAction: logInstantResultsSearch() }, (modification) => {
        config.dispatch(updateInstantResultsQuery({ q: modification, id: payload.id }));
    });
    const request = await buildInstantResultSearchRequest(state, q, maxResultsPerQuery);
    const fetched = await processor.fetchFromAPI(request, {
        origin: 'instantResults',
        disableAbortWarning: true,
    });
    const processed = await processor.process(fetched);
    if ('response' in processed) {
        return {
            results: processed.response.results,
            searchUid: processed.response.searchUid,
            analyticsAction: processed.analyticsAction,
            totalCountFiltered: processed.response.totalCountFiltered,
            duration: processed.duration,
        };
    }
    return processed;
}
export async function legacyFetchPage(state, 
// biome-ignore lint/suspicious/noExplicitAny: <>
config, searchAction) {
    addEntryInActionsHistory(state);
    const { analyticsClientMiddleware, preprocessRequest, logger } = config.extra;
    const { description: eventDescription } = await searchAction.prepare({
        getState: () => config.getState(),
        analyticsClientMiddleware,
        preprocessRequest,
        logger,
    });
    const processor = new AsyncSearchThunkProcessor({
        ...config,
        analyticsAction: searchAction,
    });
    const request = await buildSearchRequest(state, eventDescription);
    const fetched = await processor.fetchFromAPI(request, { origin: 'mainSearch' });
    return await processor.process(fetched);
}
export async function legacyFetchMoreResults(
// biome-ignore lint/suspicious/noExplicitAny: <>
config, state) {
    const { analyticsClientMiddleware, preprocessRequest, logger } = config.extra;
    const { description: eventDescription } = await logFetchMoreResults().prepare({
        getState: () => config.getState(),
        analyticsClientMiddleware,
        preprocessRequest,
        logger,
    });
    const processor = new AsyncSearchThunkProcessor({
        ...config,
        analyticsAction: logFetchMoreResults(),
    });
    const request = await buildFetchMoreRequest(state, eventDescription);
    const fetched = await processor.fetchFromAPI(request, { origin: 'mainSearch' });
    return await processor.process(fetched);
}
async function legacyFetchFacetValues(
// biome-ignore lint/suspicious/noExplicitAny: <>
config, searchAction, state) {
    const { analyticsClientMiddleware, preprocessRequest, logger } = config.extra;
    const { description: eventDescription } = await searchAction.prepare({
        getState: () => config.getState(),
        analyticsClientMiddleware,
        preprocessRequest,
        logger,
    });
    const processor = new AsyncSearchThunkProcessor({ ...config, analyticsAction: searchAction });
    const request = await buildFetchFacetValuesRequest(state, eventDescription);
    const fetched = await processor.fetchFromAPI(request, {
        origin: 'facetValues',
    });
    return await processor.process(fetched);
}
export async function legacyExecuteSearch(state, 
// biome-ignore lint/suspicious/noExplicitAny: <>
config, searchAction) {
    addEntryInActionsHistory(state);
    const { analyticsClientMiddleware, preprocessRequest, logger } = config.extra;
    const { description: eventDescription } = await searchAction.prepare({
        getState: () => config.getState(),
        analyticsClientMiddleware,
        preprocessRequest,
        logger,
    });
    if (eventDescription?.actionCause) {
        config.dispatch(updateSearchAction({
            actionCause: eventDescription.actionCause,
        }));
    }
    const request = await buildSearchRequest(state, eventDescription);
    const processor = new AsyncSearchThunkProcessor({ ...config, analyticsAction: searchAction });
    const fetched = await processor.fetchFromAPI(request, { origin: 'mainSearch' });
    return await processor.process(fetched);
}
