"use strict";

// Rollbar integration helper for jso-symbolicate.
//
// Rollbar accepts a `transform` option (or `addTransform()` on the instance)
// that runs over every payload before it's posted. Use it to demangle
// function names, exception classes, and message text in-place. Mirror of
// the Sentry beforeSend pattern.
//
// Usage (browser SDK):
//
//   const Rollbar = require("rollbar");
//   const { buildLookup } = require("jso-symbolicate");
//   const { createRollbarTransform } = require("jso-symbolicate/rollbar");
//
//   const lookup = buildLookup(
//       require("./report.json").Report.GlobalIdentifierMap,
//       require("./report.json").Report.MemberIdentifierMap
//   );
//
//   const rollbar = new Rollbar({
//       accessToken: "...",
//       transform: createRollbarTransform(lookup)
//   });

const { demangleStack } = require("./index.js");

function rewriteRollbarTrace(trace, lookup) {
    if (!trace || typeof trace !== "object") return;
    const exception = trace.exception || trace.exc || null;
    if (exception) {
        if (typeof exception.class === "string") exception.class = demangleStack(exception.class, lookup);
        if (typeof exception.message === "string") exception.message = demangleStack(exception.message, lookup);
        if (typeof exception.description === "string") exception.description = demangleStack(exception.description, lookup);
    }
    if (Array.isArray(trace.frames)) {
        for (const f of trace.frames) {
            if (!f) continue;
            if (typeof f.method === "string") f.method = demangleStack(f.method, lookup);
            if (typeof f.filename === "string") f.filename = demangleStack(f.filename, lookup);
            if (typeof f.code === "string") f.code = demangleStack(f.code, lookup);
            if (Array.isArray(f.context && f.context.pre)) {
                f.context.pre = f.context.pre.map(s => demangleStack(s, lookup));
            }
            if (Array.isArray(f.context && f.context.post)) {
                f.context.post = f.context.post.map(s => demangleStack(s, lookup));
            }
        }
    }
}

/**
 * Build a Rollbar payload transform function. Pass to `new Rollbar({ transform })`.
 *
 * The transform runs over `payload.data.body.trace`, `trace_chain[]`,
 * `payload.data.body.message`, and the breadcrumbs `telemetry[]` array.
 * Errors during transformation are swallowed so a broken lookup cannot block
 * crash reporting; the un-demangled payload is sent unchanged in that case.
 */
function createRollbarTransform(lookup) {
    if (!lookup || typeof lookup !== "object") {
        return function (payload, item, callback) { if (callback) callback(null); };
    }
    return function transform(payload, item, callback) {
        try {
            const data = payload && payload.data;
            const body = data && data.body;
            if (body) {
                if (body.trace) rewriteRollbarTrace(body.trace, lookup);
                if (Array.isArray(body.trace_chain)) {
                    for (const t of body.trace_chain) rewriteRollbarTrace(t, lookup);
                }
                if (body.message && typeof body.message.body === "string") {
                    body.message.body = demangleStack(body.message.body, lookup);
                }
            }
            const telemetry = data && Array.isArray(data.telemetry) ? data.telemetry : null;
            if (telemetry) {
                for (const t of telemetry) {
                    if (t && t.body && typeof t.body.message === "string") {
                        t.body.message = demangleStack(t.body.message, lookup);
                    }
                }
            }
            if (data) {
                data.custom = data.custom || {};
                data.custom.jso_symbolicated = true;
            }
        } catch (e) {
            // Swallow — Rollbar receives the un-demangled payload, which is
            // strictly better than no report.
            if (payload && payload.data) {
                payload.data.custom = payload.data.custom || {};
                payload.data.custom.jso_symbolicate_error = String(e && e.message || e);
            }
        }
        if (typeof callback === "function") callback(null);
    };
}

module.exports = { createRollbarTransform };
