import { SpanKind as SpanKinds, SpanStatusCode } from './types.js';
import { appendBounded, buildSpanId, normalizeTraceId, } from './api-helpers.js';
export function ingestExternalTelemetryLogs(input) {
    const resourceLogs = Array.isArray(input.payload['resourceLogs']) ? input.payload['resourceLogs'] : [];
    for (const resource of resourceLogs) {
        const scopeLogs = listNestedArray(resource, 'scopeLogs');
        for (const scope of scopeLogs) {
            const logRecords = listNestedArray(scope, 'logRecords');
            for (const logRecord of logRecords) {
                const entry = objectRecord(logRecord);
                const record = buildIngestedTelemetryRecord('OTLP_LOG_INGEST', entry, input.nextSequence);
                appendBounded(input.records, record, input.eventLimit);
                input.recordEvent('OTLP_LOG_INGEST', record);
            }
        }
    }
}
export function ingestExternalTelemetryTraces(input) {
    const resourceSpans = Array.isArray(input.payload['resourceSpans']) ? input.payload['resourceSpans'] : [];
    let spansAppended = 0;
    for (const resource of resourceSpans) {
        const scopeSpans = listNestedArray(resource, 'scopeSpans');
        for (const scope of scopeSpans) {
            const spans = listNestedArray(scope, 'spans');
            for (const spanPayload of spans) {
                const entry = objectRecord(spanPayload);
                const traceId = typeof entry['traceId'] === 'string' ? entry['traceId'] : normalizeTraceId(undefined);
                const spanId = typeof entry['spanId'] === 'string' ? entry['spanId'] : buildSpanId(`otlp:${input.peekSequence()}`);
                const name = typeof entry['name'] === 'string' ? entry['name'] : 'otlp.span';
                const startMs = typeof entry['startTimeUnixNano'] === 'number'
                    ? Math.floor(entry['startTimeUnixNano'] / 1_000_000)
                    : Date.now();
                const endMs = typeof entry['endTimeUnixNano'] === 'number'
                    ? Math.floor(entry['endTimeUnixNano'] / 1_000_000)
                    : startMs;
                appendBounded(input.spans, {
                    name,
                    kind: SpanKinds.INTERNAL,
                    spanContext: { traceId, spanId, isValid: true },
                    startTimeMs: startMs,
                    endTimeMs: endMs,
                    durationMs: endMs - startMs,
                    attributes: {},
                    events: [],
                    status: { code: SpanStatusCode.UNSET },
                    instrumentationScope: 'otlp-ingest',
                }, input.spanLimit);
                spansAppended += 1;
            }
        }
    }
    if (spansAppended === 0)
        return;
    const record = buildIngestedTelemetryRecord('OTLP_TRACE_INGEST', input.payload, input.nextSequence);
    appendBounded(input.records, record, input.eventLimit);
    input.recordEvent('OTLP_TRACE_INGEST', record);
}
export function ingestExternalTelemetryMetrics(input) {
    const resourceMetrics = Array.isArray(input.payload['resourceMetrics']) ? input.payload['resourceMetrics'] : [];
    let datapointsFound = 0;
    for (const resource of resourceMetrics) {
        const scopeMetrics = listNestedArray(resource, 'scopeMetrics');
        for (const scope of scopeMetrics) {
            const metrics = listNestedArray(scope, 'metrics');
            for (const metric of metrics) {
                const metricRecord = objectRecord(metric);
                for (const signalKey of ['sum', 'gauge', 'histogram', 'exponentialHistogram', 'summary']) {
                    const signal = metricRecord[signalKey];
                    if (typeof signal !== 'object' || signal === null)
                        continue;
                    const dataPoints = signal['dataPoints'];
                    if (Array.isArray(dataPoints))
                        datapointsFound += dataPoints.length;
                }
            }
        }
    }
    if (datapointsFound === 0)
        return;
    const record = buildIngestedTelemetryRecord('OTLP_METRICS_INGEST', input.payload, input.nextSequence);
    appendBounded(input.records, record, input.eventLimit);
    input.recordEvent('OTLP_METRICS_INGEST', record);
}
function buildIngestedTelemetryRecord(type, payload, nextSequence) {
    const domain = 'ops';
    const now = Date.now();
    const seq = nextSequence();
    return {
        id: `${domain}:${type}:${now}:${seq}`,
        domain,
        type,
        timestamp: now,
        severity: 'info',
        traceId: normalizeTraceId(undefined),
        sessionId: '',
        source: 'otlp-ingest',
        message: `OTLP ingest: ${type}`,
        payload,
        attributes: {},
    };
}
function listNestedArray(value, key) {
    return typeof value === 'object' && value !== null && Array.isArray(value[key])
        ? value[key]
        : [];
}
function objectRecord(value) {
    return typeof value === 'object' && value !== null ? value : {};
}
