import { createToolCallIdTransformerWithNative, normalizeFunctionCallIdWithNative, normalizeFunctionCallOutputIdWithNative, normalizeResponsesCallIdWithNative } from '../../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
import { sanitizeResponsesFunctionNameWithNative } from '../../router/virtual-router/engine-selection/native-hub-pipeline-resp-semantics.js';
function assertResponsesToolUtilsNativeAvailable() {
    if (typeof createToolCallIdTransformerWithNative !== 'function' ||
        typeof normalizeFunctionCallIdWithNative !== 'function' ||
        typeof normalizeFunctionCallOutputIdWithNative !== 'function' ||
        typeof normalizeResponsesCallIdWithNative !== 'function' ||
        typeof sanitizeResponsesFunctionNameWithNative !== 'function') {
        throw new Error('[responses-tool-utils] native bindings unavailable');
    }
}
export function createToolCallIdTransformer(style) {
    assertResponsesToolUtilsNativeAvailable();
    if (style !== 'fc') {
        return null;
    }
    const state = createToolCallIdTransformerWithNative(style);
    return {
        normalizeCallId(raw) {
            return normalizeResponsesCallIdWithNative({
                callId: typeof raw === 'string' && raw.trim().length ? raw.trim() : undefined,
                fallback: transformCounter(state, 'call')
            });
        },
        normalizeItemId(raw, callId) {
            return normalizeFunctionCallIdWithNative({
                callId: typeof raw === 'string' && raw.trim().length ? raw.trim() : callId,
                fallback: transformCounter(state, 'item')
            });
        },
        normalizeOutputId(callId, raw) {
            return normalizeFunctionCallOutputIdWithNative({
                callId,
                fallback: typeof raw === 'string' && raw.trim().length ? raw.trim() : transformCounter(state, 'tool')
            });
        }
    };
}
function transformCounter(state, prefix) {
    const current = typeof state.__counter === 'number' ? state.__counter : 0;
    const next = current + 1;
    state.__counter = next;
    return `${prefix}_${next}`;
}
function isStableToolCallId(raw) {
    return /^((fc|call)_[A-Za-z0-9_-]+)$/i.test(raw);
}
export function normalizeResponsesToolCallIds(payload) {
    assertResponsesToolUtilsNativeAvailable();
    if (!payload || typeof payload !== 'object') {
        return;
    }
    let counter = 0;
    const aliasMap = new Map();
    const nextFallback = (prefix) => `${prefix}_${++counter}`;
    const normalizeCallId = (raw, fallbackPrefix) => {
        const trimmed = typeof raw === 'string' ? raw.trim() : '';
        if (trimmed) {
            const cached = aliasMap.get(trimmed);
            if (cached)
                return cached;
        }
        const normalized = trimmed && isStableToolCallId(trimmed)
            ? trimmed
            : normalizeFunctionCallIdWithNative({
                callId: trimmed || undefined,
                fallback: nextFallback(fallbackPrefix)
            });
        if (trimmed) {
            aliasMap.set(trimmed, normalized);
        }
        return normalized;
    };
    const output = Array.isArray(payload.output) ? payload.output : [];
    for (const item of output) {
        if (!item || typeof item !== 'object')
            continue;
        const type = typeof item.type === 'string' ? String(item.type).toLowerCase() : '';
        if (type === 'function_call') {
            const normalizedCallId = normalizeCallId(item.call_id ?? item.tool_call_id ?? item.id, 'fc_call');
            item.call_id = normalizedCallId;
            if (item.tool_call_id !== undefined) {
                item.tool_call_id = normalizedCallId;
            }
            const rawOutputId = typeof item.id === 'string' ? item.id : undefined;
            item.id = normalizeFunctionCallOutputIdWithNative({
                callId: normalizedCallId,
                fallback: rawOutputId ?? nextFallback('fc')
            });
            continue;
        }
        if (type === 'function_call_output' || type === 'tool_result' || type === 'tool_message') {
            const normalizedCallId = normalizeCallId(item.call_id ?? item.tool_call_id ?? item.id, 'fc_call');
            item.call_id = normalizedCallId;
            if (item.tool_call_id !== undefined) {
                item.tool_call_id = normalizedCallId;
            }
            const rawOutputId = typeof item.id === 'string' ? item.id : undefined;
            item.id = normalizeFunctionCallOutputIdWithNative({
                callId: normalizedCallId,
                fallback: rawOutputId ?? nextFallback('fc')
            });
            continue;
        }
        if (Array.isArray(item.tool_calls)) {
            for (const call of item.tool_calls) {
                if (!call || typeof call !== 'object')
                    continue;
                const normalizedCallId = normalizeCallId(call.id ?? call.tool_call_id ?? call.call_id, 'fc_call');
                call.id = normalizedCallId;
                if (call.tool_call_id !== undefined) {
                    call.tool_call_id = normalizedCallId;
                }
                if (call.call_id !== undefined) {
                    call.call_id = normalizedCallId;
                }
            }
        }
    }
    const submitCalls = payload?.required_action?.submit_tool_outputs?.tool_calls;
    if (Array.isArray(submitCalls)) {
        for (const call of submitCalls) {
            if (!call || typeof call !== 'object')
                continue;
            const normalizedCallId = normalizeCallId(call.tool_call_id ?? call.id ?? call.call_id, 'fc_call');
            call.tool_call_id = normalizedCallId;
            call.id = normalizedCallId;
            if (call.call_id !== undefined) {
                call.call_id = normalizedCallId;
            }
        }
    }
}
export function resolveToolCallIdStyle(metadata) {
    if (!metadata)
        return 'fc';
    const raw = metadata.toolCallIdStyle;
    if (typeof raw === 'string') {
        const lowered = raw.trim().toLowerCase();
        if (lowered === 'fc') {
            return 'fc';
        }
        if (lowered === 'preserve') {
            return 'preserve';
        }
    }
    return 'fc';
}
const RAW_SYSTEM_SENTINEL = '__rcc_raw_system';
export function stripInternalToolingMetadata(metadata) {
    if (!metadata || typeof metadata !== 'object')
        return;
    const record = metadata;
    if ('toolCallIdStyle' in record) {
        delete record.toolCallIdStyle;
    }
    if (RAW_SYSTEM_SENTINEL in record) {
        delete record[RAW_SYSTEM_SENTINEL];
    }
    if (record.extraFields && typeof record.extraFields === 'object') {
        prunePrivateExtraFields(record.extraFields);
        if (!Object.keys(record.extraFields).length) {
            delete record.extraFields;
        }
    }
}
function prunePrivateExtraFields(target) {
    for (const key of Object.keys(target)) {
        const value = target[key];
        if (typeof key === 'string' && key.startsWith('__rcc_')) {
            delete target[key];
            continue;
        }
        if (value && typeof value === 'object') {
            prunePrivateExtraFields(value);
            if (!Object.keys(value).length) {
                delete target[key];
            }
        }
    }
}
export function sanitizeResponsesFunctionName(rawName) {
    assertResponsesToolUtilsNativeAvailable();
    return sanitizeResponsesFunctionNameWithNative(rawName);
}
export function enforceToolCallIdStyle(input, transformer) {
    assertResponsesToolUtilsNativeAvailable();
    for (const entry of input) {
        if (!entry || typeof entry !== 'object')
            continue;
        const type = typeof entry.type === 'string' ? entry.type.toLowerCase() : '';
        if (type === 'function_call') {
            const normalizedCallId = transformer.normalizeCallId(entry.call_id ?? entry.id);
            entry.call_id = normalizedCallId;
            entry.id = transformer.normalizeItemId(entry.id ?? normalizedCallId, normalizedCallId);
            continue;
        }
        if (type === 'function_call_output' || type === 'tool_result' || type === 'tool_message') {
            const normalizedCallId = transformer.normalizeCallId(entry.call_id ?? entry.tool_call_id ?? entry.id);
            entry.call_id = normalizedCallId;
            if (entry.tool_call_id !== undefined) {
                delete entry.tool_call_id;
            }
            entry.id = transformer.normalizeOutputId(normalizedCallId, entry.id);
        }
    }
}
