import { useEffect } from 'react';
import {
  createRoutesFromChildren,
  matchRoutes,
  useLocation,
  useNavigationType,
} from 'react-router-dom';

import {
  getGlobalScope,
  setTags,
  setUser as setUserBrowser,
} from '@sentry/browser';
import {
  captureException,
  httpContextIntegration,
  init,
  reactRouterV6BrowserTracingIntegration,
} from '@sentry/react';

import { SENTRY_NOISY_URLS } from 'src/constants/sentry';
import { type MeInstance } from 'src/types/instance';
import { type MeUser } from 'src/types/user';
import { getAbsoluteUrlPath, getEmailDomain, getUrlHost } from 'src/utils/text';

const apiKey = import.meta.env.VITE_SENTRY_DSN;

if (apiKey) {
  init({
    dsn: apiKey,
    environment: import.meta.env.VITE_SENTRY_ENV,
    release: import.meta.env.VITE_SENTRY_RELEASE,
    beforeSend: event => {
      const path = getAbsoluteUrlPath(event.request?.url || '');
      if (path) {
        event.tags = { ...event.tags, path };
      }
      return event;
    },
    integrations: [
      reactRouterV6BrowserTracingIntegration({
        useEffect,
        useLocation,
        useNavigationType,
        createRoutesFromChildren,
        matchRoutes,
        shouldCreateSpanForRequest: (url: string) =>
          !SENTRY_NOISY_URLS.test(url),
        onRequestSpanStart: (span: any, request: any) => {
          if (request?.headers?.get('X-Request-Id')) {
            span._attributes['X-request-id'] =
              request?.headers?.get('X-Request-Id');
          }
          if (request?.headers?.get('X-Call-Site')) {
            span._attributes['X-Call-Site'] =
              request?.headers?.get('X-Call-Site');
          }

          return span;
        },
      }),
      httpContextIntegration(),
    ],
    beforeSendTransaction(event) {
      if (event.request?.url?.includes('/conversation')) {
        return event;
      }
      return null;
    },
    tracesSampleRate: 0.1,
    profilesSampleRate: 0,
    ignoreErrors: ['Request failed with status code'],
    sendDefaultPii: true,
    attachStacktrace: true,
    enableLogs: true,
  });

  document.body.addEventListener(
    'error',
    (event: ErrorEvent) => {
      if (!event.target || Math.random() > 0.01) return; // 1% chance of logging

      const target = event.target as HTMLElement;
      const error = new Error();
      error.name = `Failed to load resource: ${target.tagName}`;
      const urlHost =
        getUrlHost((target as HTMLImageElement).src) || 'Invalid URL';

      if (target.tagName === 'IMG') {
        const imgElement = target as HTMLImageElement;
        error.message = `Failed to load image: ${urlHost}`;
        captureException(error, {
          extra: {
            resource_type: 'image',
            resource_url: imgElement.src,
            alt_text: imgElement.alt,
            element_id: imgElement.id,
            parent_component: (
              imgElement.closest('[data-component]') as HTMLElement
            )?.dataset?.component,
          },
          tags: {
            resource_url: imgElement.src,
            resource_url_host: urlHost,
          },
        });
      } else if (target.tagName === 'VIDEO') {
        const videoElement = target as HTMLVideoElement;
        error.message = `Failed to load video: ${urlHost}`;
        captureException(error, {
          extra: {
            resource_type: 'video',
            resource_url: videoElement.src,
            element_id: videoElement.id,
          },
          tags: {
            resource_url: videoElement.src,
            resource_url_host: urlHost,
          },
        });
      }
    },
    true,
  );
}

export const setUser = (user?: MeUser, instance?: MeInstance) => {
  if (apiKey) {
    const domain = getEmailDomain({
      email: user?.email || undefined,
      employeeInternalId: user?.employeeInternalId || '',
    });

    setUserBrowser({
      username: user?.employeeInternalId,
      id: user?.id.toString(),
      email: user?.email || undefined,
      instanceId: instance?.id,
      instanceName: instance?.name,
    });

    setTags({
      community: instance?.name,
      domain,
    });

    getGlobalScope().setAttributes({
      instance_id: instance?.id?.toString() ?? '',
      instance_name: instance?.name ?? '',
      domain,
      user_id: user?.id?.toString() ?? '',
      employee_internal_id: user?.employeeInternalId ?? '',
    });
  }
};

export const clearUser = () => {
  if (apiKey) {
    setUserBrowser(null);
    getGlobalScope().setAttributes({
      instance_id: '',
      instance_name: '',
      domain: '',
      user_id: '',
      employee_internal_id: '',
    });
  }
};
