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 normalizeAllowedCharactersToken(value) {
    if (typeof value === 'string') {
        const token = value.trim();
        return token || undefined;
    }
    if (!value || typeof value !== 'object' || Array.isArray(value)) {
        return undefined;
    }
    const row = value;
    if (typeof row.source === 'string' && row.source.trim()) {
        return row.source.trim();
    }
    return undefined;
}
function normalizeRulesForNative(rules) {
    if (!rules || typeof rules !== 'object') {
        return undefined;
    }
    const normalizedAllowed = normalizeAllowedCharactersToken(rules.allowedCharacters);
    return {
        ...rules,
        ...(normalizedAllowed ? { allowedCharacters: normalizedAllowed } : {})
    };
}
function normalizeRegistryForNative(registry) {
    if (!registry || typeof registry !== 'object') {
        return undefined;
    }
    const out = {};
    for (const [protocol, node] of Object.entries(registry)) {
        out[protocol] = {
            request: normalizeRulesForNative(node?.request),
            response: normalizeRulesForNative(node?.response)
        };
    }
    return out;
}
function parseRegistry(raw) {
    try {
        const parsed = JSON.parse(raw);
        if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
            return null;
        }
        return parsed;
    }
    catch {
        return null;
    }
}
function readNativeErrorReason(value) {
    if (value instanceof Error) {
        const text = value.message.trim();
        return text || String(value);
    }
    if (!value || typeof value !== 'object') {
        return undefined;
    }
    const row = value;
    const message = typeof row.message === 'string' ? row.message.trim() : '';
    if (message) {
        return message;
    }
    return undefined;
}
export function resolveDefaultToolGovernanceRulesWithNative() {
    const capability = 'resolveDefaultToolGovernanceRulesJson';
    const fail = (reason) => failNativeRequired(capability, reason);
    if (isNativeDisabledByEnv()) {
        return fail('native disabled');
    }
    const fn = readNativeFunction(capability);
    if (!fn) {
        return fail();
    }
    try {
        const raw = fn();
        const errorReason = readNativeErrorReason(raw);
        if (errorReason) {
            return fail(errorReason);
        }
        if (typeof raw !== 'string' || !raw) {
            return fail('empty result');
        }
        const parsed = parseRegistry(raw);
        return parsed ?? fail('invalid payload');
    }
    catch (error) {
        const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
        return fail(reason);
    }
}
export function governRequestWithNative(input) {
    const capability = 'governRequestJson';
    const fail = (reason) => failNativeRequired(capability, reason);
    if (isNativeDisabledByEnv()) {
        return fail('native disabled');
    }
    const fn = readNativeFunction(capability);
    if (!fn) {
        return fail();
    }
    const normalizedInput = {
        ...input,
        registry: normalizeRegistryForNative(input.registry)
    };
    const inputJson = safeStringify(normalizedInput);
    if (!inputJson) {
        return fail('json stringify failed');
    }
    try {
        const raw = fn(inputJson);
        const errorReason = readNativeErrorReason(raw);
        if (errorReason) {
            return fail(errorReason);
        }
        if (typeof raw !== 'string' || !raw) {
            return fail('empty result');
        }
        const parsed = JSON.parse(raw);
        if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
            return fail('invalid payload');
        }
        const row = parsed;
        if (!row.request || typeof row.request !== 'object' || Array.isArray(row.request)) {
            return fail('invalid request payload');
        }
        if (!row.summary || typeof row.summary !== 'object' || Array.isArray(row.summary)) {
            return fail('invalid summary payload');
        }
        return {
            request: row.request,
            summary: row.summary
        };
    }
    catch (error) {
        const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
        return fail(reason);
    }
}
export function governResponseWithNative(input) {
    const capability = 'governToolNameResponseJson';
    const fail = (reason) => failNativeRequired(capability, reason);
    if (isNativeDisabledByEnv()) {
        return fail('native disabled');
    }
    const fn = readNativeFunction(capability);
    if (!fn) {
        return fail();
    }
    const normalizedInput = {
        ...input,
        registry: normalizeRegistryForNative(input.registry)
    };
    const inputJson = safeStringify(normalizedInput);
    if (!inputJson) {
        return fail('json stringify failed');
    }
    try {
        const raw = fn(inputJson);
        const errorReason = readNativeErrorReason(raw);
        if (errorReason) {
            return fail(errorReason);
        }
        if (typeof raw !== 'string' || !raw) {
            return fail('empty result');
        }
        const parsed = JSON.parse(raw);
        if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
            return fail('invalid payload');
        }
        const row = parsed;
        if (!row.payload || typeof row.payload !== 'object' || Array.isArray(row.payload)) {
            return fail('invalid response payload');
        }
        if (!row.summary || typeof row.summary !== 'object' || Array.isArray(row.summary)) {
            return fail('invalid summary payload');
        }
        return {
            payload: row.payload,
            summary: row.summary
        };
    }
    catch (error) {
        const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
        return fail(reason);
    }
}
