"use strict";

// Raygun4JS / Raygun4Node integration helper for jso-symbolicate.
//
// Raygun's `onBeforeSend` callback receives the payload before it ships.
// Use it to demangle the error class, message, and stack-trace frames.
//
// Usage (Raygun4JS):
//
//   const rg4js = require("raygun4js");
//   const { buildLookup } = require("jso-symbolicate");
//   const { createRaygunBeforeSend } = require("jso-symbolicate/raygun");
//
//   const lookup = buildLookup(
//       require("./report.json").Report.GlobalIdentifierMap,
//       require("./report.json").Report.MemberIdentifierMap
//   );
//
//   rg4js("onBeforeSend", createRaygunBeforeSend(lookup));

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

/**
 * Build a Raygun onBeforeSend callback. The callback MUST return the
 * (possibly modified) payload — returning false would drop the event, and
 * symbolication errors should never silently drop crash reports.
 */
function createRaygunBeforeSend(lookup) {
    if (!lookup || typeof lookup !== "object") {
        return function (payload) { return payload; };
    }
    return function onBeforeSend(payload) {
        try {
            if (!payload || typeof payload !== "object") return payload;
            const details = payload.Details || payload.details || payload;
            const error = details && (details.Error || details.error);
            if (error && typeof error === "object") {
                if (typeof error.Message === "string") error.Message = demangleStack(error.Message, lookup);
                if (typeof error.message === "string") error.message = demangleStack(error.message, lookup);
                if (typeof error.ClassName === "string") error.ClassName = demangleStack(error.ClassName, lookup);
                if (typeof error.className === "string") error.className = demangleStack(error.className, lookup);
                if (typeof error.StackString === "string") error.StackString = demangleStack(error.StackString, lookup);
                if (typeof error.stackString === "string") error.stackString = demangleStack(error.stackString, lookup);
                const trace = error.StackTrace || error.stackTrace || error.stack;
                if (Array.isArray(trace)) {
                    for (const frame of trace) {
                        if (!frame) continue;
                        if (typeof frame.MethodName === "string") frame.MethodName = demangleStack(frame.MethodName, lookup);
                        if (typeof frame.methodName === "string") frame.methodName = demangleStack(frame.methodName, lookup);
                        if (typeof frame.FileName === "string") frame.FileName = demangleStack(frame.FileName, lookup);
                        if (typeof frame.fileName === "string") frame.fileName = demangleStack(frame.fileName, lookup);
                        if (typeof frame.ClassName === "string") frame.ClassName = demangleStack(frame.ClassName, lookup);
                    }
                }
            }
            const userCustomData = (details && (details.UserCustomData || details.userCustomData)) || null;
            if (userCustomData && typeof userCustomData === "object") {
                userCustomData.jso_symbolicated = true;
            }
        } catch (e) {
            // Don't swallow the report. Return whatever we have.
        }
        return payload;
    };
}

module.exports = { createRaygunBeforeSend };
