import { MULTIPLAYER_TRACE_DEBUG_PREFIX, MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX, ATTR_MULTIPLAYER_HTTP_REQUEST_BODY, ATTR_MULTIPLAYER_HTTP_REQUEST_HEADERS, ATTR_MULTIPLAYER_HTTP_RESPONSE_BODY, ATTR_MULTIPLAYER_HTTP_RESPONSE_HEADERS, } from '@multiplayer-app/session-recorder-common';
/**
 * Checks if the trace should be processed based on trace ID prefixes
 */
export function shouldProcessTrace(traceId) {
    return (traceId.startsWith(MULTIPLAYER_TRACE_DEBUG_PREFIX) ||
        traceId.startsWith(MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX));
}
/**
 * Processes request and response body based on trace type and configuration
 */
export function processBody(payload, config, span) {
    var _a, _b;
    const { captureBody, masking } = config;
    const traceId = span.spanContext().traceId;
    if (!captureBody) {
        return {};
    }
    let { requestBody, responseBody } = payload;
    if (requestBody !== undefined && requestBody !== null) {
        requestBody = JSON.parse(JSON.stringify(requestBody));
    }
    if (responseBody !== undefined && responseBody !== null) {
        responseBody = JSON.parse(JSON.stringify(responseBody));
    }
    // Apply masking for debug traces
    if (traceId.startsWith(MULTIPLAYER_TRACE_DEBUG_PREFIX) ||
        traceId.startsWith(MULTIPLAYER_TRACE_CONTINUOUS_DEBUG_PREFIX)) {
        if (masking.isContentMaskingEnabled) {
            requestBody = requestBody && ((_a = masking.maskBody) === null || _a === void 0 ? void 0 : _a.call(masking, requestBody, span));
            responseBody = responseBody && ((_b = masking.maskBody) === null || _b === void 0 ? void 0 : _b.call(masking, responseBody, span));
        }
    }
    // Convert to string if needed
    if (typeof requestBody !== 'string') {
        requestBody = JSON.stringify(requestBody);
    }
    if (typeof responseBody !== 'string') {
        responseBody = JSON.stringify(responseBody);
    }
    return {
        requestBody: (requestBody === null || requestBody === void 0 ? void 0 : requestBody.length) ? requestBody : undefined,
        responseBody: (responseBody === null || responseBody === void 0 ? void 0 : responseBody.length) ? responseBody : undefined,
    };
}
/**
 * Processes request and response headers based on configuration
 */
export function processHeaders(payload, config, span) {
    var _a, _b, _c, _d, _e;
    const { captureHeaders, masking } = config;
    if (!captureHeaders) {
        return {};
    }
    let { requestHeaders = {}, responseHeaders = {} } = payload;
    // Handle header filtering
    if (!((_a = masking.headersToInclude) === null || _a === void 0 ? void 0 : _a.length) &&
        !((_b = masking.headersToExclude) === null || _b === void 0 ? void 0 : _b.length)) {
        // Add null checks to prevent JSON.parse error when headers is undefined
        if (requestHeaders !== undefined && requestHeaders !== null) {
            requestHeaders = JSON.parse(JSON.stringify(requestHeaders));
        }
        if (responseHeaders !== undefined && responseHeaders !== null) {
            responseHeaders = JSON.parse(JSON.stringify(responseHeaders));
        }
    }
    else {
        if (masking.headersToInclude) {
            const _requestHeaders = {};
            const _responseHeaders = {};
            for (const headerName of masking.headersToInclude) {
                if (requestHeaders[headerName]) {
                    _requestHeaders[headerName] = requestHeaders[headerName];
                }
                if (responseHeaders[headerName]) {
                    _responseHeaders[headerName] = responseHeaders[headerName];
                }
            }
            requestHeaders = _requestHeaders;
            responseHeaders = _responseHeaders;
        }
        if ((_c = masking.headersToExclude) === null || _c === void 0 ? void 0 : _c.length) {
            for (const headerName of masking.headersToExclude) {
                delete requestHeaders[headerName];
                delete responseHeaders[headerName];
            }
        }
    }
    // Apply masking
    const maskedRequestHeaders = ((_d = masking.maskHeaders) === null || _d === void 0 ? void 0 : _d.call(masking, requestHeaders, span)) || requestHeaders;
    const maskedResponseHeaders = ((_e = masking.maskHeaders) === null || _e === void 0 ? void 0 : _e.call(masking, responseHeaders, span)) || responseHeaders;
    // Convert to string
    const requestHeadersStr = typeof maskedRequestHeaders === 'string'
        ? maskedRequestHeaders
        : JSON.stringify(maskedRequestHeaders);
    const responseHeadersStr = typeof maskedResponseHeaders === 'string'
        ? maskedResponseHeaders
        : JSON.stringify(maskedResponseHeaders);
    return {
        requestHeaders: (requestHeadersStr === null || requestHeadersStr === void 0 ? void 0 : requestHeadersStr.length) ? requestHeadersStr : undefined,
        responseHeaders: (responseHeadersStr === null || responseHeadersStr === void 0 ? void 0 : responseHeadersStr.length) ? responseHeadersStr : undefined,
    };
}
/**
 * Processes HTTP payload (body and headers) and sets span attributes
 */
export function processHttpPayload(payload, config, span) {
    const traceId = span.spanContext().traceId;
    if (!shouldProcessTrace(traceId)) {
        return;
    }
    const { requestBody, responseBody } = processBody(payload, config, span);
    const { requestHeaders, responseHeaders } = processHeaders(payload, config, span);
    // Set span attributes
    if (requestBody) {
        span.setAttribute(ATTR_MULTIPLAYER_HTTP_REQUEST_BODY, requestBody);
    }
    if (responseBody) {
        span.setAttribute(ATTR_MULTIPLAYER_HTTP_RESPONSE_BODY, responseBody);
    }
    if (requestHeaders) {
        span.setAttribute(ATTR_MULTIPLAYER_HTTP_REQUEST_HEADERS, requestHeaders);
    }
    if (responseHeaders) {
        span.setAttribute(ATTR_MULTIPLAYER_HTTP_RESPONSE_HEADERS, responseHeaders);
    }
}
/**
 * Converts Headers object to plain object
 */
export function headersToObject(headers) {
    const result = {};
    if (!headers) {
        return result;
    }
    if (headers instanceof Headers) {
        headers.forEach((value, key) => {
            result[key] = value;
        });
    }
    else if (Array.isArray(headers)) {
        // Handle array of [key, value] pairs
        for (const [key, value] of headers) {
            if (typeof key === 'string' && typeof value === 'string') {
                result[key] = value;
            }
        }
    }
    else if (typeof headers === 'object' && !Array.isArray(headers)) {
        for (const [key, value] of Object.entries(headers)) {
            if (typeof key === 'string' && typeof value === 'string') {
                result[key] = value;
            }
        }
    }
    return result;
}
/**
 * Extracts response body as string from Response object
 */
export async function extractResponseBody(response) {
    if (!response.body) {
        return null;
    }
    try {
        if (response.body instanceof ReadableStream) {
            // Check if response body is already consumed
            if (response.bodyUsed) {
                return null;
            }
            const responseClone = response.clone();
            return responseClone.text();
        }
        else {
            return JSON.stringify(response.body);
        }
    }
    catch (error) {
        // If cloning fails (body already consumed), return null
        // eslint-disable-next-line no-console
        console.warn('[MULTIPLAYER_SESSION_RECORDER] Failed to extract response body:', error);
        return null;
    }
}
export const getExporterEndpoint = (exporterEndpoint) => {
    const hasPath = exporterEndpoint && (() => {
        try {
            const url = new URL(exporterEndpoint);
            return url.pathname !== '/' && url.pathname !== '';
        }
        catch (_a) {
            return false;
        }
    })();
    if (hasPath) {
        return exporterEndpoint;
    }
    const trimmedExporterEndpoint = new URL(exporterEndpoint).origin;
    return `${trimmedExporterEndpoint}/v1/traces`;
};
export const getElementTextContent = (element) => {
    return String(element.textContent || element.ariaLabel || '').trim();
};
//# sourceMappingURL=helpers.js.map