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 parseFormatEnvelopePayload(raw, direction, fallbackProtocol, fallbackPayload) {
    try {
        const parsed = JSON.parse(raw);
        if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
            return null;
        }
        const row = parsed;
        const envelope = row.envelope;
        if (!envelope || typeof envelope !== 'object' || Array.isArray(envelope)) {
            return null;
        }
        const env = envelope;
        const protocol = typeof env.format === 'string' && env.format.trim().length
            ? env.format.trim()
            : fallbackProtocol;
        const payload = env.payload && typeof env.payload === 'object' && !Array.isArray(env.payload)
            ? env.payload
            : fallbackPayload;
        const out = {
            protocol,
            direction,
            payload
        };
        if (env.metadata && typeof env.metadata === 'object' && !Array.isArray(env.metadata)) {
            out.meta = env.metadata;
        }
        return out;
    }
    catch {
        return null;
    }
}
function parseOptionalString(raw) {
    try {
        const parsed = JSON.parse(raw);
        if (parsed === null) {
            return undefined;
        }
        if (typeof parsed !== 'string') {
            return null;
        }
        const trimmed = parsed.trim();
        return trimmed ? trimmed : undefined;
    }
    catch {
        return null;
    }
}
function parseBoolean(raw) {
    try {
        const parsed = JSON.parse(raw);
        return typeof parsed === 'boolean' ? parsed : null;
    }
    catch {
        return null;
    }
}
export function sanitizeFormatEnvelopeWithNative(candidate) {
    const capability = 'sanitizeFormatEnvelopeJson';
    const fail = (reason) => failNativeRequired(capability, reason);
    if (isNativeDisabledByEnv()) {
        return fail('native disabled');
    }
    const fn = readNativeFunction('sanitizeFormatEnvelopeJson');
    if (!fn) {
        return fail();
    }
    const candidateJson = safeStringify(candidate);
    if (!candidateJson) {
        return fail('json stringify failed');
    }
    try {
        const raw = fn(candidateJson);
        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);
    }
}
export function sanitizeChatCompletionLikeWithNative(candidate) {
    const capability = 'sanitizeChatCompletionLikeJson';
    const fail = (reason) => failNativeRequired(capability, reason);
    if (isNativeDisabledByEnv()) {
        return fail('native disabled');
    }
    const fn = readNativeFunction('sanitizeChatCompletionLikeJson');
    if (!fn) {
        return fail();
    }
    const candidateJson = safeStringify(candidate);
    if (!candidateJson) {
        return fail('json stringify failed');
    }
    try {
        const raw = fn(candidateJson);
        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);
    }
}
export function stripPrivateFieldsWithNative(payload) {
    const capability = 'stripPrivateFieldsJson';
    const fail = (reason) => failNativeRequired(capability, reason);
    if (isNativeDisabledByEnv()) {
        return fail('native disabled');
    }
    const fn = readNativeFunction('stripPrivateFieldsJson');
    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 = parseRecord(raw);
        return parsed ?? fail('invalid payload');
    }
    catch (error) {
        const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
        return fail(reason);
    }
}
export function resolveCompatProfileWithNative(adapterContext, explicitProfile) {
    const capability = 'resolveCompatProfileJson';
    const fail = (reason) => failNativeRequired(capability, reason);
    if (isNativeDisabledByEnv()) {
        return fail('native disabled');
    }
    const fn = readNativeFunction('resolveCompatProfileJson');
    if (!fn) {
        return fail();
    }
    const adapterContextJson = safeStringify(adapterContext);
    const explicitJson = safeStringify(explicitProfile ?? null);
    if (!adapterContextJson || !explicitJson) {
        return fail('json stringify failed');
    }
    try {
        const raw = fn(adapterContextJson, explicitJson);
        if (typeof raw !== 'string' || !raw) {
            return fail('empty result');
        }
        const parsed = parseOptionalString(raw);
        return parsed === null ? fail('invalid payload') : parsed;
    }
    catch (error) {
        const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
        return fail(reason);
    }
}
export function resolveSseStreamModeWithNative(wantsStream, clientProtocol) {
    const capability = 'resolveSseStreamModeJson';
    const fail = (reason) => failNativeRequired(capability, reason);
    if (isNativeDisabledByEnv()) {
        return fail('native disabled');
    }
    const fn = readNativeFunction('resolveSseStreamModeJson');
    if (!fn) {
        return fail();
    }
    try {
        const raw = fn(Boolean(wantsStream), String(clientProtocol || ''));
        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);
    }
}
export function parseReqInboundFormatEnvelopeWithNative(input) {
    const capability = 'parseFormatEnvelopeJson';
    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 = parseFormatEnvelopePayload(raw, 'request', input.protocol, input.rawRequest);
        return parsed ?? fail('invalid payload');
    }
    catch (error) {
        const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
        return fail(reason);
    }
}
export function parseRespInboundFormatEnvelopeWithNative(input) {
    const capability = 'parseRespFormatEnvelopeJson';
    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 = parseFormatEnvelopePayload(raw, 'response', input.protocol, input.payload);
        return parsed ?? fail('invalid payload');
    }
    catch (error) {
        const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
        return fail(reason);
    }
}
export function validateChatEnvelopeWithNative(chatEnvelope, options) {
    const capability = 'validateChatEnvelopeJson';
    const fail = (reason) => failNativeRequired(capability, reason);
    if (isNativeDisabledByEnv()) {
        return fail('native disabled');
    }
    const fn = readNativeFunction(capability);
    if (!fn) {
        return fail();
    }
    const envelopeJson = safeStringify(chatEnvelope);
    if (!envelopeJson) {
        return fail('json stringify failed');
    }
    const isChatEnvelopeValidationError = (message) => typeof message === 'string' && message.includes('ChatEnvelopeValidationError(');
    try {
        const raw = fn(envelopeJson, String(options.stage || ''), String(options.direction || ''), options.source);
        const nativeErrorMessage = raw instanceof Error
            ? raw.message
            : raw && typeof raw === 'object' && 'message' in raw
                ? (() => {
                    const candidate = raw.message;
                    return typeof candidate === 'string' ? candidate : '';
                })()
                : '';
        if (nativeErrorMessage) {
            if (isChatEnvelopeValidationError(nativeErrorMessage)) {
                throw new Error(nativeErrorMessage);
            }
            return fail(nativeErrorMessage);
        }
        if (typeof raw !== 'string' || !raw) {
            return fail('empty result');
        }
        const parsed = parseBoolean(raw);
        if (parsed !== true) {
            return fail('invalid payload');
        }
    }
    catch (error) {
        const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
        if (isChatEnvelopeValidationError(reason)) {
            throw error instanceof Error ? error : new Error(reason);
        }
        return fail(reason);
    }
}
