(() => {
  'use strict';

  try {
    const ROOT = globalThis;
    const MARK = Symbol.for('grax.telemetry.stub');
    const NATIVE_STUB_SOURCE = 'function () { [native code] }';
    const CALLBACK_METHODS = new Set([
      'withScope', 'configureScope', 'startSpan', 'startSpanManual',
      'startTransaction', 'onLoad', 'onReady', 'ready', 'addEventProcessor',
      'onFeatureFlags', 'onSessionId', 'onCapture'
    ]);
    const STRING_METHODS = new Set([
      'get_distinct_id', 'getDistinctId', 'get_session_id', 'getSessionId',
      'getAnonymousId', 'anonymousId', 'getUserId', 'getDeviceId'
    ]);
    const BOOLEAN_METHODS = new Set([
      'isInitialized', 'isReady', 'isSupported', 'hasLoaded', 'hasOptedOutTracking'
    ]);
    const stealthFunctions = new WeakSet();
    const nativeFunctionToStringDescriptor = Object.getOwnPropertyDescriptor(Function.prototype, 'toString');
    const nativeFunctionToString = nativeFunctionToStringDescriptor?.value;

    const mark = value => {
      try {
        Object.defineProperty(value, MARK, {
          value: true,
          configurable: true,
          enumerable: false,
          writable: false
        });
      } catch {}
      try {
        if (typeof value === 'function') stealthFunctions.add(value);
      } catch {}
      return value;
    };

    const isStealthFunction = value => {
      try {
        return typeof value === 'function' && (stealthFunctions.has(value) || value[MARK] === true);
      } catch {
        return false;
      }
    };

    const installToStringMask = () => {
      try {
        if (!nativeFunctionToString) return;
        const current = Object.getOwnPropertyDescriptor(Function.prototype, 'toString');
        if (current?.value !== nativeFunctionToString && !current?.value?.[MARK]) return;
        if (current?.value?.[MARK]) return;
        const maskedToString = mark(function toString() {
          try {
            if (isStealthFunction(this)) return NATIVE_STUB_SOURCE;
          } catch {}
          return Reflect.apply(nativeFunctionToString, this, []);
        });
        Object.defineProperty(Function.prototype, 'toString', {
          value: maskedToString,
          configurable: nativeFunctionToStringDescriptor?.configurable !== false,
          enumerable: nativeFunctionToStringDescriptor?.enumerable === true,
          writable: nativeFunctionToStringDescriptor?.writable !== false
        });
      } catch {}
    };

    const define = (name, value) => {
      try {
        const descriptor = Object.getOwnPropertyDescriptor(ROOT, name);
        let existing;
        try {
          existing = descriptor && 'value' in descriptor
            ? descriptor.value
            : descriptor?.get
              ? ROOT[name]
              : undefined;
        } catch {}
        if (existing != null && !existing?.[MARK]) return existing;
        if (descriptor?.configurable === false) return existing;
        Object.defineProperty(ROOT, name, {
          value,
          configurable: descriptor ? descriptor.configurable !== false : true,
          enumerable: descriptor?.enumerable === true,
          writable: descriptor && 'writable' in descriptor ? descriptor.writable !== false : true
        });
      } catch {}
      return value;
    };

    const nativeUtility = callback => mark(function () {
      try { return Reflect.apply(callback, this, arguments); } catch { return undefined; }
    });
    const nativeStringifier = nativeUtility(() => NATIVE_STUB_SOURCE);
    const emptyJson = nativeUtility(() => ({}));
    const zeroValue = nativeUtility(() => 0);
    const primitiveValue = nativeUtility(() => '');
    const emptyIterator = mark(function* () {});
    const emptyAsyncIterator = mark(async function* () {});

    const createRecursiveCallable = (label, options = {}) => {
      const cache = new Map();
      const queue = [];

      const make = path => {
        if (cache.has(path)) return cache.get(path);
        let proxy;
        const target = mark(function () {
          return proxy;
        });
        try {
          Object.defineProperty(target, 'name', {
            value: '', configurable: true, enumerable: false, writable: false
          });
        } catch {}

        const childFor = (targetValue, property) => {
          const child = make(`${path}.${String(property)}`);
          try {
            if (!Reflect.getOwnPropertyDescriptor(targetValue, property) && Reflect.isExtensible(targetValue)) {
              Reflect.defineProperty(targetValue, property, {
                configurable: true,
                enumerable: false,
                writable: true,
                value: child
              });
            }
          } catch {}
          return child;
        };

        proxy = new Proxy(target, {
          apply(_target, _thisArg, args) {
            try {
              if (options.queueCalls) queue.push(Array.from(args));
              const leaf = path.split('.').pop() || '';
              if (leaf === 'wrap' && typeof args[0] === 'function') return args[0];
              if (STRING_METHODS.has(leaf)) return '';
              if (BOOLEAN_METHODS.has(leaf)) return leaf !== 'hasOptedOutTracking';
              if (CALLBACK_METHODS.has(leaf)) {
                const callback = [...args].reverse().find(value => typeof value === 'function');
                if (callback) {
                  try {
                    const result = callback(proxy);
                    return result === undefined ? proxy : result;
                  } catch {
                    return proxy;
                  }
                }
              }
            } catch {}
            return proxy;
          },
          construct() { return proxy; },
          get(targetValue, property, receiver) {
            try {
              if (property === MARK) return true;
              if (property === 'then') return undefined;
              if (property === 'toJSON') return emptyJson;
              if (property === 'toString') return nativeStringifier;
              if (property === 'valueOf') return zeroValue;
              if (property === Symbol.toPrimitive) return primitiveValue;
              if (property === Symbol.iterator) return emptyIterator;
              if (property === Symbol.asyncIterator) return emptyAsyncIterator;
              if (property === '__graxQueue') return queue;
              if ((property === 'q' || property === 'queue') && options.exposeQueue) return queue;
              if (property === 'loaded' || property === 'initialized' || property === 'isLoaded') return true;
              if (property === 'version') return options.version || '1.0';
              const ownDescriptor = Reflect.getOwnPropertyDescriptor(targetValue, property);
              if (ownDescriptor) {
                const ownValue = Reflect.get(targetValue, property, receiver);
                if (ownValue !== undefined) return ownValue;
              }
              return childFor(targetValue, property);
            } catch {
              return proxy;
            }
          },
          set(targetValue, property, value, receiver) {
            try {
              if ((property === 'q' || property === 'queue') && Array.isArray(value)) {
                queue.splice(0, queue.length, ...value);
              }
              return Reflect.set(targetValue, property, value, receiver);
            } catch {
              return true;
            }
          },
          defineProperty(targetValue, property, descriptor) {
            try { return Reflect.defineProperty(targetValue, property, descriptor); } catch { return true; }
          },
          deleteProperty(targetValue, property) {
            try { return Reflect.deleteProperty(targetValue, property); } catch { return true; }
          },
          getOwnPropertyDescriptor(targetValue, property) {
            try {
              const descriptor = Reflect.getOwnPropertyDescriptor(targetValue, property);
              if (descriptor) return descriptor;
              childFor(targetValue, property);
              return Reflect.getOwnPropertyDescriptor(targetValue, property);
            } catch {
              return undefined;
            }
          },
          ownKeys(targetValue) {
            try { return Reflect.ownKeys(targetValue); } catch { return []; }
          },
          getPrototypeOf() { return Function.prototype; },
          has() { return true; }
        });

        mark(proxy);
        cache.set(path, proxy);
        return proxy;
      };

      return make(label);
    };

    installToStringMask();

    const ensureArray = name => {
      try {
        if (Array.isArray(ROOT[name])) return ROOT[name];
      } catch {}
      return define(name, mark([]));
    };

    const dataLayer = ensureArray('dataLayer');
    ensureArray('_hsq');
    ensureArray('_paq');
    ensureArray('_gaq');

    if (typeof ROOT.gtag !== 'function') {
      const gtagTarget = createRecursiveCallable('gtag', { queueCalls: true, exposeQueue: true });
      const gtag = new Proxy(gtagTarget, {
        apply(target, thisArg, args) {
          try { dataLayer?.push(Array.from(args)); } catch {}
          return Reflect.apply(target, thisArg, args);
        }
      });
      mark(gtag);
      define('gtag', gtag);
    }

    if (typeof ROOT.ga !== 'function') {
      const ga = createRecursiveCallable('ga', { queueCalls: true, exposeQueue: true });
      try { ga.l = Date.now(); } catch {}
      define('ga', ga);
    }

    if (typeof ROOT.fbq !== 'function') {
      const fbq = createRecursiveCallable('fbq', {
        queueCalls: true,
        exposeQueue: true,
        version: '2.0'
      });
      try {
        fbq.loaded = true;
        fbq.version = '2.0';
        fbq.callMethod = fbq;
      } catch {}
      define('fbq', fbq);
      define('_fbq', fbq);
    }

    for (const name of [
      'Intercom', 'hj', 'clarity', 'FS', 'FullStory', 'plausible', 'matomo',
      'mixpanel', 'analytics', 'Sentry', 'DD_RUM', 'DD_LOGS', 'datadog',
      'datadogRum', 'datadogLogs', 'HubSpotConversations', 'amplitude',
      'LogRocket', 'newrelic', 'NREUM', 'Bugsnag', 'Rollbar', 'heap',
      'posthog', 'rudderanalytics', 'Appcues', 'pendo', 'smartlook',
      'mouseflow', 'Inspectlet', 'snowplow', 'utag'
    ]) {
      let current;
      try { current = ROOT[name]; } catch {}
      if (current == null || current?.[MARK]) {
        define(name, createRecursiveCallable(name, {
          queueCalls: true,
          exposeQueue: true
        }));
      }
    }

    try {
      ROOT.dispatchEvent(new CustomEvent('__grax_telemetry_mock_ready_v1__'));
    } catch {}
  } catch {}
})();
