export function emitToOtel(trace, tracer) {
    emitSpan(trace.root, tracer);
}
function emitSpan(traceSpan, tracer, parent) {
    const span = tracer.startSpan(traceSpan.name, readFiniteTimestamp(traceSpan.startTs) !== undefined
        ? { startTime: traceSpan.startTs }
        : undefined, parent);
    try {
        const attrs = toOtelAttributes(traceSpan);
        if (Object.keys(attrs).length > 0) {
            span.setAttributes(attrs);
        }
        for (const child of traceSpan.children) {
            emitSpan(child, tracer, span);
        }
    }
    finally {
        if (readFiniteTimestamp(traceSpan.endTs) !== undefined) {
            span.end(traceSpan.endTs);
        }
        else {
            span.end();
        }
    }
}
function toOtelAttributes(span) {
    const attrs = {};
    if (span.kind === "agent") {
        attrs["gen_ai.system"] = "poe-code";
        addAttribute(attrs, "gen_ai.request.model", readAgentModel(span.name));
        addAttribute(attrs, "gen_ai.agent.name", readAgentName(span.name));
        addAttribute(attrs, "gen_ai.usage.input_tokens", span.metrics?.prompt_tokens);
        addAttribute(attrs, "gen_ai.usage.output_tokens", span.metrics?.completion_tokens);
        addAttribute(attrs, "gen_ai.usage.cached_tokens", span.metrics?.prompt_cached_tokens);
        addAttribute(attrs, "poe_code.session_id", readPrimitive(readOwnMetadata(span.metadata, "sessionId")));
        addAttribute(attrs, "poe_code.thread_id", readPrimitive(readOwnMetadata(span.metadata, "threadId")));
    }
    if (span.kind === "tool") {
        addAttribute(attrs, "gen_ai.tool.name", readToolName(span.name));
        addAttribute(attrs, "poe_code.tool_call_id", readPrimitive(readOwnMetadata(span.metadata, "toolCallId")));
    }
    addInputOutputAttribute(attrs, "poe_code.input", span.input);
    addInputOutputAttribute(attrs, "poe_code.output", span.output);
    return attrs;
}
function addInputOutputAttribute(attrs, key, value) {
    if (value === undefined) {
        return;
    }
    const primitive = readPrimitive(value);
    if (primitive !== undefined) {
        attrs[key] = primitive;
        return;
    }
    if (typeof value === "number") {
        return;
    }
    const serialized = safelySerialize(value);
    if (serialized !== undefined) {
        attrs[key] = serialized;
    }
}
function addAttribute(attrs, key, value) {
    if (value !== undefined) {
        attrs[key] = value;
    }
}
function readAgentName(name) {
    const parts = name.split(":");
    return parts[0] === "agent" && parts[1] !== "" ? parts[1] : undefined;
}
function readAgentModel(name) {
    const parts = name.split(":");
    if (parts[0] !== "agent" || parts.length < 3) {
        return undefined;
    }
    const model = parts.slice(2).join(":");
    return model === "" ? undefined : model;
}
function readToolName(name) {
    const parts = name.split(":");
    if (parts[0] !== "tool_call" || parts.length < 2) {
        return undefined;
    }
    const toolName = parts.slice(1).join(":");
    return toolName === "" ? undefined : toolName;
}
function readPrimitive(value) {
    if (typeof value === "string" || typeof value === "boolean") {
        return value;
    }
    return typeof value === "number" && Number.isFinite(value)
        ? value
        : undefined;
}
function readOwnMetadata(metadata, key) {
    return metadata !== undefined && Object.hasOwn(metadata, key)
        ? metadata[key]
        : undefined;
}
function readFiniteTimestamp(value) {
    return typeof value === "number" && Number.isFinite(value) ? value : undefined;
}
function safelySerialize(value) {
    try {
        return JSON.stringify(value);
    }
    catch {
        return undefined;
    }
}
