import { isJsonObject, jsonClone, } from "../../../../types/json.js";
import { applyHubOperationTableInbound } from "../../../../operation-table/operation-table-runner.js";
import { recordStage } from "../../../stages/utils.js";
import { liftReqInboundSemantics } from "./semantic-lift.js";
import { validateChatEnvelopeWithNative } from "../../../../../../router/virtual-router/engine-selection/native-hub-pipeline-edge-stage-semantics.js";
import { chatEnvelopeToStandardizedWithNative } from "../../../../../../router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.js";
import { logHubStageTiming } from "../../../hub-stage-timing.js";
export async function runReqInboundStage2SemanticMap(options) {
    const requestId = options.adapterContext.requestId || "unknown";
    logHubStageTiming(requestId, "req_inbound.stage2_semantic_mapper_toChat", "start");
    const toChatStart = Date.now();
    const chatEnvelope = await options.semanticMapper.toChat(options.formatEnvelope, options.adapterContext);
    logHubStageTiming(requestId, "req_inbound.stage2_semantic_mapper_toChat", "completed", { elapsedMs: Date.now() - toChatStart });
    const preservedResponsesContext = (() => {
        if (!chatEnvelope.semantics || typeof chatEnvelope.semantics !== "object") {
            return undefined;
        }
        const semantics = chatEnvelope.semantics;
        const responsesNode = isJsonObject(semantics.responses)
            ? semantics.responses
            : undefined;
        const contextNode = responsesNode && isJsonObject(responsesNode.context)
            ? responsesNode.context
            : undefined;
        return contextNode ? jsonClone(contextNode) : undefined;
    })();
    applyHubOperationTableInbound({
        formatEnvelope: options.formatEnvelope,
        chatEnvelope,
        adapterContext: options.adapterContext,
    });
    // Semantic Gate (request): before entering chat_process, lift any mappable protocol semantics
    // into ChatEnvelope.semantics. Do not persist these in metadata.
    liftReqInboundSemantics({
        chatEnvelope,
        formatEnvelope: options.formatEnvelope,
        adapterContext: options.adapterContext,
        responsesResume: options.responsesResume,
    });
    if (preservedResponsesContext) {
        const currentSemantics = chatEnvelope.semantics;
        if (!currentSemantics || typeof currentSemantics !== "object") {
            chatEnvelope.semantics = {
                responses: { context: jsonClone(preservedResponsesContext) },
            };
        }
        else {
            const semantics = currentSemantics;
            const responsesNode = isJsonObject(semantics.responses)
                ? semantics.responses
                : {};
            if (!isJsonObject(responsesNode.context)) {
                chatEnvelope.semantics = {
                    ...semantics,
                    responses: {
                        ...responsesNode,
                        context: jsonClone(preservedResponsesContext),
                    },
                };
            }
        }
    }
    validateChatEnvelopeWithNative(chatEnvelope, {
        stage: "req_inbound",
        direction: "request",
    });
    recordStage(options.stageRecorder, "chat_process.req.stage2.semantic_map", chatEnvelope);
    logHubStageTiming(requestId, "req_inbound.stage2_to_standardized", "start");
    const stdStart = Date.now();
    const standardizedRequest = chatEnvelopeToStandardizedWithNative({
        chatEnvelope: chatEnvelope,
        adapterContext: options.adapterContext,
        endpoint: options.adapterContext.entryEndpoint,
        requestId: options.adapterContext.requestId,
    });
    logHubStageTiming(requestId, "req_inbound.stage2_to_standardized", "completed", { elapsedMs: Date.now() - stdStart });
    // Ensure responses semantics (context) survive into standardized request for VirtualRouter parsing.
    if (chatEnvelope.semantics && typeof chatEnvelope.semantics === "object") {
        const envelopeSemantics = chatEnvelope.semantics;
        const existing = standardizedRequest.semantics;
        if (!existing || typeof existing !== "object") {
            standardizedRequest.semantics = jsonClone(envelopeSemantics);
        }
        else {
            const existingObj = existing;
            const envelopeResponses = isJsonObject(envelopeSemantics.responses)
                ? envelopeSemantics.responses
                : undefined;
            const envelopeContext = envelopeResponses && isJsonObject(envelopeResponses.context)
                ? envelopeResponses.context
                : undefined;
            if (envelopeContext) {
                const nextResponses = {
                    ...(isJsonObject(existingObj.responses)
                        ? existingObj.responses
                        : {}),
                    context: jsonClone(envelopeContext),
                };
                standardizedRequest.semantics = {
                    ...existingObj,
                    responses: nextResponses,
                };
            }
        }
    }
    return {
        chatEnvelope,
        standardizedRequest,
        ...(preservedResponsesContext
            ? { responsesContext: preservedResponsesContext }
            : {}),
    };
}
