var {
  _optionalChain
} = require('@sentry/utils');

Object.defineProperty(exports, '__esModule', { value: true });

const instrumentationKoa = require('@opentelemetry/instrumentation-koa');
const semanticConventions = require('@opentelemetry/semantic-conventions');
const core = require('@sentry/core');
const utils = require('@sentry/utils');
const debugBuild = require('../../debug-build.js');
const instrument = require('../../otel/instrument.js');
const ensureIsWrapped = require('../../utils/ensureIsWrapped.js');

const INTEGRATION_NAME = 'Koa';

const instrumentKoa = instrument.generateInstrumentOnce(
  INTEGRATION_NAME,
  () =>
    new instrumentationKoa.KoaInstrumentation({
      requestHook(span, info) {
        addKoaSpanAttributes(span);

        if (core.getIsolationScope() === core.getDefaultIsolationScope()) {
          debugBuild.DEBUG_BUILD && utils.logger.warn('Isolation scope is default isolation scope - skipping setting transactionName');
          return;
        }
        const attributes = core.spanToJSON(span).data;
        const route = attributes && attributes[semanticConventions.ATTR_HTTP_ROUTE];
        // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
        const method = _optionalChain([info, 'optionalAccess', _ => _.context, 'optionalAccess', _2 => _2.request, 'optionalAccess', _3 => _3.method, 'optionalAccess', _4 => _4.toUpperCase, 'call', _5 => _5()]) || 'GET';
        if (route) {
          core.getIsolationScope().setTransactionName(`${method} ${route}`);
        }
      },
    }),
);

const _koaIntegration = (() => {
  return {
    name: INTEGRATION_NAME,
    setupOnce() {
      instrumentKoa();
    },
  };
}) ;

const koaIntegration = core.defineIntegration(_koaIntegration);

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const setupKoaErrorHandler = (app) => {
  app.use(async (ctx, next) => {
    try {
      await next();
    } catch (error) {
      core.captureException(error);
      throw error;
    }
  });

  ensureIsWrapped.ensureIsWrapped(app.use, 'koa');
};

function addKoaSpanAttributes(span) {
  span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.http.otel.koa');

  const attributes = core.spanToJSON(span).data || {};

  // this is one of: middleware, router
  const type = attributes['koa.type'];

  if (type) {
    span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, `${type}.koa`);
  }

  // Also update the name
  const name = attributes['koa.name'];
  if (typeof name === 'string') {
    // Somehow, name is sometimes `''` for middleware spans
    // See: https://github.com/open-telemetry/opentelemetry-js-contrib/issues/2220
    span.updateName(name || '< unknown >');
  }
}

exports.instrumentKoa = instrumentKoa;
exports.koaIntegration = koaIntegration;
exports.setupKoaErrorHandler = setupKoaErrorHandler;
