import { createBridgeActionState, runBridgeActionPipeline } from '../../bridge-actions.js';
import { resolveBridgePolicy, resolvePolicyActions } from '../../bridge-policies.js';
import { normalizeProviderProtocolTokenWithNative } from '../../../router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.js';
const INBOUND_BRIDGE_SPECS = {
    'openai-chat': { protocol: 'openai-chat', stage: 'request_inbound', messages: 'chat_envelope' },
    // Keep parity with the legacy semantic mapper behavior: do not pass messages[] into the action state
    // for openai-responses, since the bridge actions here are used as metadata hooks only.
    'openai-responses': { protocol: 'openai-responses', stage: 'request_inbound', messages: 'none', includeCapturedToolResults: true, moduleType: 'openai-responses' },
    'anthropic-messages': { protocol: 'anthropic-messages', stage: 'request_inbound', messages: 'chat_envelope' },
    'gemini-chat': { protocol: 'gemini-chat', stage: 'request_inbound', messages: 'chat_envelope' }
};
const OUTBOUND_BRIDGE_SPECS = {
    'openai-chat': { protocol: 'openai-chat', stage: 'request_outbound', messages: 'format_payload_messages', includeCapturedToolResults: true },
    // Keep parity: openai-responses outbound actions should not touch normalized messages.
    'openai-responses': { protocol: 'openai-responses', stage: 'request_outbound', messages: 'none', moduleType: 'openai-responses' },
    'anthropic-messages': { protocol: 'anthropic-messages', stage: 'request_outbound', messages: 'none', includeCapturedToolResults: true },
    // Keep parity with legacy gemini mapper: outbound hooks operate on ChatEnvelope.messages (not Gemini contents).
    'gemini-chat': { protocol: 'gemini-chat', stage: 'request_outbound', messages: 'chat_envelope', includeCapturedToolResults: true }
};
function isSupportedProtocol(protocol) {
    const normalizedProtocol = normalizeProviderProtocolTokenWithNative(protocol) ?? protocol;
    return normalizedProtocol === 'openai-chat' ||
        normalizedProtocol === 'openai-responses' ||
        normalizedProtocol === 'anthropic-messages' ||
        normalizedProtocol === 'gemini-chat';
}
function extractPayloadMessages(payload) {
    const value = payload?.messages;
    if (!Array.isArray(value)) {
        return undefined;
    }
    return value;
}
function buildCapturedToolResults(toolOutputs) {
    if (!Array.isArray(toolOutputs) || toolOutputs.length === 0) {
        return undefined;
    }
    return toolOutputs.map((entry) => ({
        tool_call_id: entry.tool_call_id,
        output: entry.content,
        name: entry.name
    }));
}
function applyBridgePolicy(spec, options) {
    const bridgePolicy = resolveBridgePolicy({ protocol: spec.protocol, moduleType: spec.moduleType ?? spec.protocol });
    const actions = resolvePolicyActions(bridgePolicy, spec.stage);
    if (!actions?.length) {
        return;
    }
    const metadata = options.chatEnvelope.metadata;
    const messages = spec.messages === 'chat_envelope'
        ? options.chatEnvelope.messages
        : spec.messages === 'format_payload_messages'
            ? extractPayloadMessages(options.payload)
            : undefined;
    const capturedToolResults = spec.includeCapturedToolResults
        ? buildCapturedToolResults(options.chatEnvelope.toolOutputs)
        : undefined;
    const actionState = createBridgeActionState({
        ...(messages ? { messages } : {}),
        rawRequest: options.payload,
        metadata,
        ...(capturedToolResults ? { capturedToolResults } : {})
    });
    runBridgeActionPipeline({
        stage: spec.stage,
        actions,
        protocol: bridgePolicy?.protocol ?? spec.protocol,
        moduleType: bridgePolicy?.moduleType ?? spec.moduleType ?? spec.protocol,
        requestId: options.requestId,
        state: actionState
    });
    if (spec.messages === 'chat_envelope') {
        options.chatEnvelope.messages = actionState.messages;
    }
}
function normalizeToolContent(value) {
    if (typeof value === 'string')
        return value;
    if (value == null)
        return '';
    try {
        return JSON.stringify(value);
    }
    catch {
        return String(value ?? '');
    }
}
function rebuildGeminiToolOutputsFromMessages(chatEnvelope) {
    const messages = Array.isArray(chatEnvelope.messages) ? chatEnvelope.messages : [];
    const missing = Array.isArray(chatEnvelope.metadata?.missingFields) ? chatEnvelope.metadata.missingFields : undefined;
    const outputs = [];
    messages.forEach((msg, index) => {
        if (!msg || typeof msg !== 'object')
            return;
        if (msg.role !== 'tool')
            return;
        const callId = msg.tool_call_id || msg.id;
        if (typeof callId !== 'string' || !callId.trim()) {
            if (missing) {
                missing.push({ path: `messages[${index}].tool_call_id`, reason: 'missing_tool_call_id' });
            }
            return;
        }
        outputs.push({
            tool_call_id: callId.trim(),
            content: normalizeToolContent(msg.content),
            name: typeof msg.name === 'string' ? msg.name : undefined
        });
    });
    chatEnvelope.toolOutputs = outputs.length ? outputs : undefined;
}
export function applyHubOperationTableInbound(options) {
    const protocol = normalizeProviderProtocolTokenWithNative(options.formatEnvelope.protocol)
        ?? options.formatEnvelope.protocol;
    if (!isSupportedProtocol(protocol)) {
        return;
    }
    const payload = (options.formatEnvelope.payload ?? {});
    const spec = INBOUND_BRIDGE_SPECS[protocol];
    applyBridgePolicy(spec, {
        requestId: options.adapterContext.requestId,
        chatEnvelope: options.chatEnvelope,
        payload,
        adapterContext: options.adapterContext
    });
    if (protocol === 'gemini-chat') {
        // Keep parity: gemini mapper rebuilds toolOutputs after inbound policy adjustments.
        rebuildGeminiToolOutputsFromMessages(options.chatEnvelope);
    }
}
export function applyHubOperationTableOutboundPreMap(options) {
    if (options.protocol !== 'anthropic-messages' && options.protocol !== 'gemini-chat') {
        return Promise.resolve();
    }
    // Ensure tool_use/tool_result ordering and per-session history for protocols that depend on it.
    return (async () => {
        try {
            const { applyToolSessionCompat } = await import('../tool-session-compat.js');
            await applyToolSessionCompat(options.chatEnvelope, options.adapterContext);
        }
        catch {
            // best-effort compat; never block outbound mapping
        }
    })();
}
export function applyHubOperationTableOutboundPostMap(options) {
    const protocol = normalizeProviderProtocolTokenWithNative(options.formatEnvelope.protocol)
        ?? options.formatEnvelope.protocol;
    if (!isSupportedProtocol(protocol)) {
        return;
    }
    const payload = (options.formatEnvelope.payload ?? {});
    const spec = OUTBOUND_BRIDGE_SPECS[protocol];
    applyBridgePolicy(spec, {
        requestId: options.adapterContext.requestId,
        chatEnvelope: options.chatEnvelope,
        payload,
        adapterContext: options.adapterContext
    });
    options.formatEnvelope.payload = payload;
}
