import { failNativeRequired, isNativeDisabledByEnv } from './native-router-hotpath-policy.js';
import { loadNativeRouterHotpathBindingForInternalUse } from './native-router-hotpath.js';
function readNativeFunction(name) {
    const binding = loadNativeRouterHotpathBindingForInternalUse();
    const fn = binding?.[name];
    return typeof fn === 'function' ? fn : null;
}
function safeStringify(value) {
    try {
        return JSON.stringify(value);
    }
    catch {
        return undefined;
    }
}
function parseRecord(raw) {
    try {
        const parsed = JSON.parse(raw);
        if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
            return null;
        }
        return parsed;
    }
    catch {
        return null;
    }
}
function parseNormalizedToolDefinitions(candidate) {
    if (!Array.isArray(candidate)) {
        return null;
    }
    const tools = [];
    for (const entry of candidate) {
        if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
            continue;
        }
        const row = entry;
        if (row.type !== 'function') {
            continue;
        }
        const fn = row.function;
        if (!fn || typeof fn !== 'object' || Array.isArray(fn)) {
            continue;
        }
        const fnRow = fn;
        const name = typeof fnRow.name === 'string' && fnRow.name.trim() ? fnRow.name.trim() : '';
        if (!name) {
            continue;
        }
        const description = typeof fnRow.description === 'string' ? fnRow.description : undefined;
        const strict = typeof fnRow.strict === 'boolean' ? fnRow.strict : undefined;
        const parameters = fnRow.parameters ?? { type: 'object', properties: {} };
        tools.push({
            type: 'function',
            function: {
                name,
                ...(description ? { description } : {}),
                parameters,
                ...(strict !== undefined ? { strict } : {})
            }
        });
    }
    return tools;
}
function parseReqOutboundContextMergePlan(raw) {
    try {
        const parsed = JSON.parse(raw);
        if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
            return null;
        }
        const row = parsed;
        const out = {};
        const mergedToolOutputs = row.mergedToolOutputs;
        if (mergedToolOutputs !== undefined) {
            if (!Array.isArray(mergedToolOutputs)) {
                return null;
            }
            const normalized = [];
            for (const entry of mergedToolOutputs) {
                if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
                    return null;
                }
                const rowEntry = entry;
                const toolCallId = typeof rowEntry.tool_call_id === 'string'
                    ? rowEntry.tool_call_id.trim()
                    : typeof rowEntry.toolCallId === 'string'
                        ? rowEntry.toolCallId.trim()
                        : '';
                const content = typeof rowEntry.content === 'string' ? rowEntry.content : undefined;
                if (!toolCallId || content === undefined) {
                    return null;
                }
                const name = typeof rowEntry.name === 'string' && rowEntry.name.trim() ? rowEntry.name.trim() : undefined;
                normalized.push({ tool_call_id: toolCallId, content, ...(name ? { name } : {}) });
            }
            out.mergedToolOutputs = normalized;
        }
        const normalizedTools = row.normalizedTools;
        if (normalizedTools !== undefined) {
            const parsedTools = parseNormalizedToolDefinitions(normalizedTools);
            if (parsedTools === null) {
                return null;
            }
            out.normalizedTools = parsedTools;
        }
        return out;
    }
    catch {
        return null;
    }
}
function parseReqOutboundContextSnapshotPatch(raw) {
    try {
        const parsed = JSON.parse(raw);
        if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
            return null;
        }
        const row = parsed;
        const out = {};
        const toolOutputs = row.toolOutputs;
        if (toolOutputs !== undefined) {
            if (!Array.isArray(toolOutputs)) {
                return null;
            }
            const normalized = [];
            for (const entry of toolOutputs) {
                if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
                    return null;
                }
                const rowEntry = entry;
                const toolCallId = typeof rowEntry.tool_call_id === 'string'
                    ? rowEntry.tool_call_id.trim()
                    : typeof rowEntry.toolCallId === 'string'
                        ? rowEntry.toolCallId.trim()
                        : '';
                const content = typeof rowEntry.content === 'string' ? rowEntry.content : undefined;
                if (!toolCallId || content === undefined) {
                    return null;
                }
                const name = typeof rowEntry.name === 'string' && rowEntry.name.trim() ? rowEntry.name.trim() : undefined;
                normalized.push({ tool_call_id: toolCallId, content, ...(name ? { name } : {}) });
            }
            out.toolOutputs = normalized;
        }
        const toolsRaw = row.tools;
        if (toolsRaw !== undefined) {
            const parsedTools = parseNormalizedToolDefinitions(toolsRaw);
            if (parsedTools === null) {
                return null;
            }
            out.tools = parsedTools;
        }
        return out;
    }
    catch {
        return null;
    }
}
function parseReqOutboundCompatOutput(raw) {
    try {
        const parsed = JSON.parse(raw);
        if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
            return null;
        }
        const row = parsed;
        const payloadRaw = row.payload;
        if (!payloadRaw || typeof payloadRaw !== 'object' || Array.isArray(payloadRaw)) {
            return null;
        }
        const payload = payloadRaw;
        const appliedProfileRaw = row.appliedProfile;
        const appliedProfile = typeof appliedProfileRaw === 'string' && appliedProfileRaw.trim()
            ? appliedProfileRaw.trim()
            : undefined;
        const nativeAppliedRaw = row.nativeApplied;
        if (typeof nativeAppliedRaw !== 'boolean') {
            return null;
        }
        const nativeApplied = nativeAppliedRaw;
        const rateLimitDetectedRaw = row.rateLimitDetected;
        const rateLimitDetected = typeof rateLimitDetectedRaw === 'boolean' ? rateLimitDetectedRaw : undefined;
        return {
            payload,
            ...(appliedProfile ? { appliedProfile } : {}),
            nativeApplied,
            ...(rateLimitDetected !== undefined ? { rateLimitDetected } : {})
        };
    }
    catch {
        return null;
    }
}
function parseToolSessionCompatOutput(raw) {
    try {
        const parsed = JSON.parse(raw);
        if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
            return null;
        }
        const row = parsed;
        const messagesRaw = row.messages;
        if (!Array.isArray(messagesRaw)) {
            return null;
        }
        const out = {
            messages: messagesRaw
        };
        if (Object.prototype.hasOwnProperty.call(row, 'toolOutputs')) {
            if (row.toolOutputs == null) {
                out.toolOutputs = undefined;
            }
            else if (Array.isArray(row.toolOutputs)) {
                out.toolOutputs = row.toolOutputs;
            }
            else {
                return null;
            }
        }
        return out;
    }
    catch {
        return null;
    }
}
function parseToolSessionHistoryUpdateOutput(raw) {
    try {
        const parsed = JSON.parse(raw);
        if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
            return null;
        }
        const row = parsed;
        const recordsCount = typeof row.recordsCount === 'number' && Number.isFinite(row.recordsCount)
            ? row.recordsCount
            : null;
        if (recordsCount === null) {
            return null;
        }
        const output = { recordsCount };
        if (row.history !== undefined) {
            if (!row.history || typeof row.history !== 'object' || Array.isArray(row.history)) {
                return null;
            }
            output.history = row.history;
        }
        return output;
    }
    catch {
        return null;
    }
}
function parseJsonObject(raw) {
    try {
        const parsed = JSON.parse(raw);
        if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
            return null;
        }
        return parsed;
    }
    catch {
        return null;
    }
}
function parseReqOutboundFormatBuildOutput(raw) {
    try {
        const parsed = JSON.parse(raw);
        if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
            return null;
        }
        const row = parsed;
        const payload = row.payload;
        if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
            return null;
        }
        return payload;
    }
    catch {
        return null;
    }
}
export function resolveReqOutboundContextMergePlanWithNative(input) {
    const capability = 'resolveReqOutboundContextMergePlanJson';
    const fail = (reason) => failNativeRequired(capability, reason);
    if (isNativeDisabledByEnv()) {
        return fail('native disabled');
    }
    const fn = readNativeFunction('resolveReqOutboundContextMergePlanJson');
    if (!fn) {
        return fail();
    }
    const inputJson = safeStringify(input);
    if (!inputJson) {
        return fail('json stringify failed');
    }
    try {
        const raw = fn(inputJson);
        if (typeof raw !== 'string' || !raw) {
            return fail('empty result');
        }
        const parsed = parseReqOutboundContextMergePlan(raw);
        return parsed ?? fail('invalid payload');
    }
    catch (error) {
        const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
        return fail(reason);
    }
}
export function buildReqOutboundFormatPayloadWithNative(input) {
    const capability = 'buildFormatRequestJson';
    const fail = (reason) => failNativeRequired(capability, reason);
    if (isNativeDisabledByEnv()) {
        return fail('native disabled');
    }
    const fn = readNativeFunction(capability);
    if (!fn) {
        return fail();
    }
    const inputJson = safeStringify({
        formatEnvelope: input.formatEnvelope,
        protocol: input.protocol
    });
    if (!inputJson) {
        return fail('json stringify failed');
    }
    try {
        const raw = fn(inputJson);
        if (typeof raw !== 'string' || !raw) {
            return fail('empty result');
        }
        const parsed = parseReqOutboundFormatBuildOutput(raw);
        return parsed ?? fail('invalid payload');
    }
    catch (error) {
        const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
        return fail(reason);
    }
}
export function applyReqOutboundContextSnapshotWithNative(input) {
    const capability = 'applyReqOutboundContextSnapshotJson';
    const fail = (reason) => failNativeRequired(capability, reason);
    if (isNativeDisabledByEnv()) {
        return fail('native disabled');
    }
    const fn = readNativeFunction('applyReqOutboundContextSnapshotJson');
    if (!fn) {
        return fail();
    }
    const inputJson = safeStringify(input);
    if (!inputJson) {
        return fail('json stringify failed');
    }
    try {
        const raw = fn(inputJson);
        if (typeof raw !== 'string' || !raw) {
            return fail('empty result');
        }
        const parsed = parseReqOutboundContextSnapshotPatch(raw);
        return parsed ?? fail('invalid payload');
    }
    catch (error) {
        const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
        return fail(reason);
    }
}
export function runReqOutboundStage3CompatWithNative(input) {
    const capability = 'runReqOutboundStage3CompatJson';
    const fail = (reason) => failNativeRequired(capability, reason);
    if (isNativeDisabledByEnv()) {
        return fail('native disabled');
    }
    const fn = readNativeFunction('runReqOutboundStage3CompatJson');
    if (!fn) {
        return fail();
    }
    const inputJson = safeStringify(input);
    if (!inputJson) {
        return fail('json stringify failed');
    }
    try {
        const raw = fn(inputJson);
        if (typeof raw !== 'string' || !raw) {
            return fail('empty result');
        }
        const parsed = parseReqOutboundCompatOutput(raw);
        return parsed ?? fail('invalid payload');
    }
    catch (error) {
        const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
        return fail(reason);
    }
}
export function runRespInboundStage3CompatWithNative(input) {
    const capability = 'runRespInboundStage3CompatJson';
    const fail = (reason) => failNativeRequired(capability, reason);
    if (isNativeDisabledByEnv()) {
        return fail('native disabled');
    }
    const fn = readNativeFunction('runRespInboundStage3CompatJson');
    if (!fn) {
        return fail();
    }
    const inputJson = safeStringify(input);
    if (!inputJson) {
        return fail('json stringify failed');
    }
    try {
        const raw = fn(inputJson);
        if (typeof raw !== 'string' || !raw) {
            return fail('empty result');
        }
        const parsed = parseReqOutboundCompatOutput(raw);
        return parsed ?? fail('invalid payload');
    }
    catch (error) {
        const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
        return fail(reason);
    }
}
export function normalizeToolSessionMessagesWithNative(input) {
    const capability = 'normalizeToolSessionMessagesJson';
    const fail = (reason) => failNativeRequired(capability, reason);
    if (isNativeDisabledByEnv()) {
        return fail('native disabled');
    }
    const fn = readNativeFunction(capability);
    if (!fn) {
        return fail();
    }
    const inputJson = safeStringify(input);
    if (!inputJson) {
        return fail('json stringify failed');
    }
    try {
        const raw = fn(inputJson);
        if (typeof raw !== 'string' || !raw) {
            return fail('empty result');
        }
        const parsed = parseToolSessionCompatOutput(raw);
        return parsed ?? fail('invalid payload');
    }
    catch (error) {
        const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
        return fail(reason);
    }
}
export function updateToolSessionHistoryWithNative(input) {
    const capability = 'updateToolSessionHistoryJson';
    const fail = (reason) => failNativeRequired(capability, reason);
    if (isNativeDisabledByEnv()) {
        return fail('native disabled');
    }
    const fn = readNativeFunction(capability);
    if (!fn) {
        return fail();
    }
    const inputJson = safeStringify(input);
    if (!inputJson) {
        return fail('json stringify failed');
    }
    try {
        const raw = fn(inputJson);
        if (typeof raw !== 'string' || !raw) {
            return fail('empty result');
        }
        const parsed = parseToolSessionHistoryUpdateOutput(raw);
        return parsed ?? fail('invalid payload');
    }
    catch (error) {
        const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
        return fail(reason);
    }
}
export function applyClaudeThinkingToolSchemaCompatWithNative(payload) {
    const capability = 'applyClaudeThinkingToolSchemaCompatJson';
    const fail = (reason) => failNativeRequired(capability, reason);
    if (isNativeDisabledByEnv()) {
        return fail('native disabled');
    }
    const fn = readNativeFunction(capability);
    if (!fn) {
        return fail();
    }
    const payloadJson = safeStringify(payload);
    if (!payloadJson) {
        return fail('json stringify failed');
    }
    try {
        const raw = fn(payloadJson);
        if (typeof raw !== 'string' || !raw) {
            return fail('empty result');
        }
        const parsed = parseJsonObject(raw);
        return parsed ?? fail('invalid payload');
    }
    catch (error) {
        const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
        return fail(reason);
    }
}
export function standardizedToChatEnvelopeWithNative(input) {
    const capability = 'standardizedToChatEnvelopeJson';
    const fail = (reason) => failNativeRequired(capability, reason);
    if (isNativeDisabledByEnv()) {
        return fail('native disabled');
    }
    const fn = readNativeFunction(capability);
    if (!fn) {
        return fail();
    }
    const requestJson = safeStringify(input.request);
    const adapterContextJson = safeStringify(input.adapterContext);
    if (!requestJson || !adapterContextJson) {
        return fail('json stringify failed');
    }
    try {
        const raw = fn(requestJson, adapterContextJson);
        if (raw instanceof Error) {
            return fail(raw.message || 'native error');
        }
        if (raw && typeof raw === 'object' && 'message' in raw) {
            const message = raw.message;
            if (typeof message === 'string' && message.trim().length) {
                return fail(message.trim());
            }
        }
        if (typeof raw !== 'string' || !raw) {
            return fail('empty result');
        }
        const parsed = parseRecord(raw);
        return parsed ?? fail('invalid payload');
    }
    catch (error) {
        const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
        return fail(reason);
    }
}
function parseBoolean(raw) {
    try {
        const parsed = JSON.parse(raw);
        return typeof parsed === 'boolean' ? parsed : null;
    }
    catch {
        return null;
    }
}
export function shouldAttachReqOutboundContextSnapshotWithNative(hasSnapshot, contextMetadataKey) {
    const capability = 'shouldAttachReqOutboundContextSnapshotJson';
    const fail = (reason) => failNativeRequired(capability, reason);
    if (isNativeDisabledByEnv()) {
        return fail('native disabled');
    }
    const fn = readNativeFunction('shouldAttachReqOutboundContextSnapshotJson');
    if (!fn) {
        return fail();
    }
    try {
        const contextMetadataKeyJson = JSON.stringify(contextMetadataKey ?? null);
        if (typeof contextMetadataKeyJson !== 'string') {
            return fail('json stringify failed');
        }
        const raw = fn(hasSnapshot, contextMetadataKeyJson);
        if (typeof raw !== 'string' || !raw) {
            return fail('empty result');
        }
        const parsed = parseBoolean(raw);
        return parsed === null ? fail('invalid payload') : parsed;
    }
    catch (error) {
        const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
        return fail(reason);
    }
}
