import * as Sentry from '@sentry/react-native';
import DeviceInfo from 'react-native-device-info';

import appPackage from './package.json';
import {hash, anonymizeYTApiEntityId} from 'util/util';

import type {ErrorEvent, EventHint} from '@sentry/core';

export const hasSentryDsn = () => appPackage.config.SENTRY_DSN.length > 0;
const getDeviceId = async () => DeviceInfo.getUniqueId();

export const initSentry = async (dsn: string) => {
  Sentry.init({
    dsn,
    sendDefaultPii: false,
    integrations: [Sentry.breadcrumbsIntegration({console: false})],
    tracesSampleRate: 0.1,
    profilesSampleRate: 0.1,
    // @ts-ignore
    beforeSend(event, hint) {
      if (isInvalidTokenError(hint) || !isAppCodeError(event)) {
        return null;
      }
      return sanitizeEventUrls(event);
    },
  });

  const deviceId = await getDeviceId();
  Sentry.setUser({
    id: hash(deviceId, 12),
    tablet: DeviceInfo.isTablet(),
    geo: {
      country_code: '',
      region: '',
      city: '',
    },
  });
};

export const captureException = (error: Error) => {
  if (hasSentryDsn()) {
    Sentry.captureException(error);
  }
};

function isAppCodeError(event: ErrorEvent) {
  const frames = event.exception?.values?.[0]?.stacktrace?.frames;
  if (Array.isArray(frames)) {
    return frames.some(frame => !frame.filename?.includes('node_modules'));
  }
  return true;
}

function isInvalidTokenError(hint: EventHint) {
  const error = hint?.originalException;
  if (!error || typeof error !== 'object') {
    return false;
  }
  if ('status' in error && typeof error.status === 'number') {
    return error.status === 401;
  }
  return false;
}

function sanitizeEventUrls(event: ErrorEvent) {
  const ev = {...event};
  if (Array.isArray(ev.breadcrumbs)) {
    ev.breadcrumbs.forEach(b => {
      if((b.category === 'xhr' || b.category === 'fetch') && b.data?.url) {
        b.data.url = anonymizeYTApiEntityId(b.data.url);
      }
    });
  }
  return ev;
}
