import { createRoot } from "react-dom/client";
import { HelmetProvider } from "react-helmet-async";
import App from "./App.tsx";
import "./index.css";
import * as Sentry from "@sentry/react";

declare const __APP_VERSION__: string;

// Check if we're in test mode
const isSentryTestMode = window.location.search.includes('sentryTest=1');

// Only enable Sentry on production (custom domain), not on Lovable domains
const isProduction =
  !window.location.hostname.includes("lovable.dev") &&
  !window.location.hostname.includes("lovable.app") &&
  !window.location.hostname.includes("lovableproject.com");

// Initialize Sentry before React mounts (production or test mode)
if (isProduction || isSentryTestMode) {
  Sentry.init({
    dsn: "https://60762cd06d945321651639f2be167cab@o4510081059127296.ingest.de.sentry.io/4510228073742416",
    release: (typeof __APP_VERSION__ !== 'undefined') ? __APP_VERSION__ : undefined,
    environment: isProduction ? "production" : "development-test",
    integrations: [
      Sentry.browserTracingIntegration(),
      Sentry.browserProfilingIntegration(),
      Sentry.replayIntegration({
        maskAllText: false,
        blockAllMedia: false,
      }),
      Sentry.captureConsoleIntegration({
        levels: ["error", "warn"],
      }),
    ],
    tracesSampleRate: 1.0,
    tracePropagationTargets: ["localhost"],
    profilesSampleRate: 0.1,
    replaysSessionSampleRate: 0.1,
    replaysOnErrorSampleRate: 1.0,
    beforeSend(event) {
      const msg = event?.exception?.values?.[0]?.value || event?.message || "";
      const frames = event?.exception?.values?.[0]?.stacktrace?.frames || [];

      // Drop known rate-limit, iframe noise, Google Maps warnings, and third-party in-app browser errors
      if (
        /Rate limit exceeded/i.test(msg) ||
        /IP temporarily blocked/i.test(msg) ||
        /too many attempts/i.test(msg) ||
        /Unknown message type: iframe-pos/i.test(msg) ||
        /google\.maps\.places\.Autocomplete is not available/i.test(msg) ||
        /Please use google\.maps\.places\.PlaceAutocompleteElement/i.test(msg) ||
        /Google Maps JavaScript API has been loaded directly without loading=async/i.test(msg) ||
        /google\.maps\.places\.PlacesService is not available/i.test(msg) ||
        /Please use google\.maps\.places\.Place instead/i.test(msg) ||
        /SecurityError.*The operation is insecure/i.test(msg) ||
        /TypeError.*Load failed/i.test(msg) ||
        /Could not calculate distance: (NOT_FOUND|ZERO_RESULTS)/i.test(msg) ||
        /Distance calculation failed:/i.test(msg) ||
        /window\.webkit\.messageHandlers/i.test(msg) ||
        /hxp-modal-detection/i.test(msg) ||
        /InvalidAccessError.*postMessage/i.test(msg) ||
        /InvalidAccessError.*The object does not support/i.test(msg) ||
        /Error invoking postMessage/i.test(msg) ||
        /Java object is gone/i.test(msg) ||
        /No settings returned from WordPress/i.test(msg) ||
        /Settings loading timeout/i.test(msg) ||
        /parcel-service/i.test(event?.transaction || "") ||
        /(Failed to fetch|Load failed).*bookings\.deadline\.ie/i.test(msg) ||
        /Failed to log redirect:/i.test(msg) ||
        /Failed to log 404:/i.test(msg) ||
        /(Failed to fetch|Load failed).*rybbit/i.test(msg) ||
        // Rybbit: some browsers put the origin in the message suffix, e.g.
        // "NetworkError when attempting to fetch resource. (app.rybbit.io)"
        (/(NetworkError|Failed to fetch|Load failed)/i.test(msg) &&
          /rybbit/i.test(msg)) ||
        // App's own console label for a failed Rybbit POST (wording varies by browser)
        /Failed to send tracking data/i.test(msg) ||
        // Rybbit script: message is just "Failed to fetch", origin only visible in stack frame filename
        (/(Failed to fetch|Load failed|NetworkError)/i.test(msg) &&
          frames.some((f: { filename?: string }) => /rybbit/i.test(f?.filename || ""))) ||
        /is not an object.*responseStart/i.test(msg) ||
        /Failed to load Google (Analytics|Tag Manager)/i.test(msg) ||
        /NavigationTypeDetection/i.test(msg) ||
        /TrackerStorageType/i.test(msg) ||
        /is not a constructor.*google\.maps/i.test(msg) ||
        /Converting circular structure to JSON/i.test(msg) ||
        /Missing 'content_id' paramter/i.test(msg) ||
        /You must use an API key to authenticate/i.test(msg) ||
        /Object Not Found Matching Id:/i.test(msg) ||
        /Could not load "places_impl"/i.test(msg) ||
        /Session expired/i.test(msg)
      ) {
        return null;
      }

      // Filter out DOM removeChild/insertBefore errors caused by browser translation/extensions
      if (
        /removeChild/i.test(msg) ||
        /NotFoundError/i.test(msg) ||
        /insertBefore/i.test(msg)
      ) {
        return null;
      }

      // Filter out AbortError (video.play, navigation, tab close)
      if (
        /AbortError/i.test(msg) ||
        event.exception?.values?.[0]?.type === 'AbortError'
      ) {
        return null;
      }

      // Filter out stale chunk errors (user on old cached version)
      if (
        /Failed to fetch dynamically imported module/i.test(msg) ||
        /Loading chunk[\s\S]*?failed/i.test(msg) ||
        /error loading dynamically imported module/i.test(msg)
      ) {
        return null;
      }

      // Filter out cross-origin frame errors
      if (
        /cross-origin frame/i.test(msg) ||
        /Blocked a frame with origin/i.test(msg)
      ) {
        return null;
      }

      // Filter out InvalidAccessError from Sentry Replay in restricted WebViews
      if (
        event.exception?.values?.[0]?.type === 'InvalidAccessError' ||
        (msg.includes('does not support the operation or argument') &&
          frames.some((f: { filename?: string }) => f?.filename?.includes('/assets/index-')))
      ) {
        return null;
      }

      // Suppress OneTrust otSDKStub JSON parse errors (third-party/browser extension noise)
      const isOneTrustError = frames.some((f: { filename?: string }) => /otSDKStub/i.test(f?.filename || ""));
      if (/Unexpected end of JSON input/i.test(msg) && isOneTrustError) {
        return null;
      }

      // Filter out DuckDuckGo privacy-script noise
      if (
        /Failed to get initial setup/i.test(msg) ||
        frames.some((f: { filename?: string }) => f?.filename?.includes('user-script:'))
      ) {
        return null;
      }

      // Filter out "Maximum call stack size exceeded" originating outside our bundle
      // (Chrome iOS translate, GTM/Ads pixel chains — captured via window.onerror with no useful frames)
      if (/Maximum call stack size exceeded/i.test(msg)) {
        const hasAppFrame = frames.some((f: { filename?: string }) =>
          (f?.filename || '').includes('/assets/')
        );
        if (!hasAppFrame) {
          return null;
        }
      }

      // Filter out third-party scripts and browser extensions
      const hasThirdPartyScript = frames.some((f: { filename?: string }) => {
        const filename = f?.filename || '';
        return (
          filename.includes('flock.js') ||
          filename.includes('/~') ||
          filename.includes('extension://') ||
          filename.includes('chrome-extension://') ||
          filename.includes('moz-extension://') ||
          filename.includes('safari-extension://')
        );
      });
      if (hasThirdPartyScript) {
        return null;
      }

      // Filter out Facebook in-app browser injected script errors
      if (
        /enableDidUserTypeOnKeyboardLogging/i.test(msg) ||
        frames.length > 0 &&
        frames.some((f: { filename?: string }) => {
          const filename = f?.filename || '';
          return filename === window.location.origin + '/' || filename === '/';
        }) &&
        !frames.some((f: { filename?: string }) => {
          const filename = f?.filename || '';
          return filename.includes('/assets/');
        })
      ) {
        return null;
      }

      return event;
    },
  });
}

const rootEl = document.getElementById("root")!;

if (isProduction || isSentryTestMode) {
  createRoot(rootEl).render(
    <HelmetProvider>
      <Sentry.ErrorBoundary fallback={
        <div className="min-h-screen flex items-center justify-center p-4">
          <div className="text-center">
            <h1 className="text-2xl font-bold mb-2">Something went wrong</h1>
            <p className="text-muted-foreground mb-4">Please refresh the page</p>
            <button onClick={() => window.location.reload()} className="px-4 py-2 bg-primary text-primary-foreground rounded-md">
              Reload Page
            </button>
          </div>
        </div>
      }>
        <App />
      </Sentry.ErrorBoundary>
    </HelmetProvider>
  );
} else {
  createRoot(rootEl).render(
    <HelmetProvider>
      <App />
    </HelmetProvider>
  );
}
