import * as Sentry from '@sentry/react';
import type { ReactElement, ReactNode } from 'react';

declare const __BUGSINK_DSN__: string | undefined;
declare const __BUGSINK_ENVIRONMENT__: string | undefined;
declare const __BUGSINK_RELEASE__: string | undefined;
declare const __BUGSINK_SEND_DEFAULT_PII__: boolean | undefined;

interface BugsinkConfig {
  dsn?: string;
  environment?: string;
  release?: string;
  sendDefaultPii?: boolean;
}

declare global {
  interface Window {
    __PERFECT_POSTCODE_BUGSINK__?: BugsinkConfig;
  }
}

function nonempty(value: unknown): string | undefined {
  if (typeof value !== 'string') {
    return undefined;
  }
  const trimmed = value.trim();
  return trimmed.length > 0 ? trimmed : undefined;
}

function readBuildTimeString(value: unknown): string | undefined {
  return nonempty(value);
}

function readBuildTimeBoolean(value: unknown): boolean {
  return typeof value === 'boolean' ? value : false;
}

function readRuntimeConfig(): BugsinkConfig {
  if (typeof document === 'undefined') {
    return {};
  }

  const element = document.getElementById('perfect-postcode-bugsink-config');
  const json = element?.textContent?.trim();
  if (!json || json === '__PERFECT_POSTCODE_BUGSINK_CONFIG__') {
    return window.__PERFECT_POSTCODE_BUGSINK__ ?? {};
  }

  try {
    const config = JSON.parse(json) as BugsinkConfig;
    window.__PERFECT_POSTCODE_BUGSINK__ = config;
    return config;
  } catch {
    return window.__PERFECT_POSTCODE_BUGSINK__ ?? {};
  }
}

export function initBugsink(): boolean {
  const runtimeConfig = readRuntimeConfig();
  const dsn =
    nonempty(runtimeConfig.dsn) ??
    readBuildTimeString(typeof __BUGSINK_DSN__ === 'string' ? __BUGSINK_DSN__ : undefined);

  if (!dsn) {
    return false;
  }

  Sentry.init({
    dsn,
    environment:
      nonempty(runtimeConfig.environment) ??
      readBuildTimeString(
        typeof __BUGSINK_ENVIRONMENT__ === 'string' ? __BUGSINK_ENVIRONMENT__ : undefined
      ),
    release:
      nonempty(runtimeConfig.release) ??
      readBuildTimeString(
        typeof __BUGSINK_RELEASE__ === 'string' ? __BUGSINK_RELEASE__ : undefined
      ),
    sendDefaultPii:
      runtimeConfig.sendDefaultPii ??
      readBuildTimeBoolean(
        typeof __BUGSINK_SEND_DEFAULT_PII__ === 'boolean' ? __BUGSINK_SEND_DEFAULT_PII__ : undefined
      ),
    tracesSampleRate: 0,
  });
  Sentry.setTag('app', 'frontend');

  return true;
}

export function BugsinkErrorBoundary({
  children,
  fallback,
}: {
  children: ReactNode;
  fallback: ReactElement;
}) {
  return <Sentry.ErrorBoundary fallback={fallback}>{children}</Sentry.ErrorBoundary>;
}
