import { answerEvaluation, } from '../../../api/knowledge/post-answer-evaluation.js';
import { triggerSearchRequest } from '../../../api/knowledge/stream-answer-actions.js';
import { answerApi, fetchAnswer, selectAnswer, selectAnswerTriggerParams, } from '../../../api/knowledge/stream-answer-api.js';
import { warnIfUsingNextAnalyticsModeForServiceFeature } from '../../../app/engine.js';
import { resetAnswer, sendGeneratedAnswerFeedback, setCannotAnswer, updateAnswerConfigurationId, } from '../../../features/generated-answer/generated-answer-actions.js';
import { filterOutDuplicatedCitations } from '../../../features/generated-answer/utils/generated-answer-citation-utils.js';
import { queryReducer as query } from '../../../features/query/query-slice.js';
import { loadReducerError } from '../../../utils/errors.js';
import { buildCoreGeneratedAnswer, } from '../../core/generated-answer/headless-core-generated-answer.js';
const parseEvaluationDetails = (detail) => {
    if (detail === 'yes') {
        return true;
    }
    if (detail === 'no') {
        return false;
    }
    return null;
};
const parseEvaluationArguments = ({ answerApiState, feedback, query, }) => ({
    additionalNotes: feedback.details ?? null,
    answer: {
        text: answerApiState.answer,
        responseId: answerApiState.answerId,
        format: answerApiState.contentFormat ?? 'text/plain',
    },
    correctAnswerUrl: feedback.documentUrl ?? null,
    details: {
        correctTopic: parseEvaluationDetails(feedback.correctTopic),
        documented: parseEvaluationDetails(feedback.documented),
        hallucinationFree: parseEvaluationDetails(feedback.hallucinationFree),
        readable: parseEvaluationDetails(feedback.readable),
    },
    helpful: feedback.helpful,
    question: query,
});
const subscribeToSearchRequest = (engine) => {
    let lastTriggerParams;
    const strictListener = () => {
        const state = engine.state;
        const triggerParams = selectAnswerTriggerParams(state);
        if (!lastTriggerParams || triggerParams.q.length === 0) {
            lastTriggerParams = triggerParams;
        }
        if (triggerParams.q.length === 0 && !!triggerParams.cannotAnswer) {
            engine.dispatch(setCannotAnswer(false));
        }
        if (triggerParams.q.length === 0 ||
            triggerParams.requestId.length === 0 ||
            triggerParams.requestId === lastTriggerParams.requestId ||
            (triggerParams.analyticsMode === 'next' && !triggerParams.actionCause) // If analytics mode is next, we need to wait for the action cause to be set
        ) {
            return;
        }
        lastTriggerParams = triggerParams;
        engine.dispatch(triggerSearchRequest({ state, navigatorContext: engine.navigatorContext }));
    };
    engine.subscribe(strictListener);
};
/**
 *
 * @internal
 *
 * Creates a `AnswerApiGeneratedAnswer` controller instance using the Answer API stream pattern.
 *
 * @param engine - The headless engine.
 * @param props - The configurable `AnswerApiGeneratedAnswer` properties.
 * @returns A `AnswerApiGeneratedAnswer` controller instance.
 */
export function buildAnswerApiGeneratedAnswer(engine, analyticsClient, props = {}) {
    if (!loadAnswerApiReducers(engine)) {
        throw loadReducerError;
    }
    warnIfUsingNextAnalyticsModeForServiceFeature(engine.state.configuration.analytics.analyticsMode);
    const { ...controller } = buildCoreGeneratedAnswer(engine, analyticsClient, props);
    const getState = () => engine.state;
    engine.dispatch(updateAnswerConfigurationId(props.answerConfigurationId));
    subscribeToSearchRequest(engine);
    return {
        ...controller,
        get state() {
            const answerApiState = selectAnswer(engine.state, engine.navigatorContext).data;
            return {
                ...getState().generatedAnswer,
                answer: answerApiState?.answer,
                citations: filterOutDuplicatedCitations(answerApiState?.citations ?? []),
                error: {
                    message: answerApiState?.error?.message,
                    statusCode: answerApiState?.error?.code,
                },
                isLoading: answerApiState?.isLoading ?? false,
                isStreaming: answerApiState?.isStreaming ?? false,
                answerContentFormat: answerApiState?.contentFormat ?? 'text/plain',
                isAnswerGenerated: answerApiState?.generated ?? false,
            };
        },
        retry() {
            engine.dispatch(fetchAnswer(getState(), engine.navigatorContext));
        },
        reset() {
            engine.dispatch(resetAnswer());
        },
        async sendFeedback(feedback) {
            const args = parseEvaluationArguments({
                query: getState().query.q,
                feedback,
                answerApiState: selectAnswer(engine.state, engine.navigatorContext)
                    .data,
            });
            engine.dispatch(answerEvaluation.endpoints.post.initiate(args));
            engine.dispatch(sendGeneratedAnswerFeedback());
        },
    };
}
function loadAnswerApiReducers(engine) {
    engine.addReducers({ [answerApi.reducerPath]: answerApi.reducer, query });
    return true;
}
