import {GrowthBookProvider} from '@growthbook/growthbook-react';
import {PayPalScriptProvider} from '@paypal/react-paypal-js';
import * as Sentry from '@sentry/react';
import Analytics from '@/utils/Analytics';
import Environment from '@/utils/Environment';
import {growthBook, setupGrowthbook} from '@/utils/growthbook';
import Identity from '@/utils/Identity';
import {getPayPalCurrency, getUserCountry} from '@/utils/locale';
import {useEffectOnce} from '@/utils/useEffectOnce';
import {lazy, Suspense} from 'react';
import ReactDOM from 'react-dom/client';
import ReactPixel from 'react-facebook-pixel';
import {BrowserRouter} from 'react-router-dom';
import packageJson from '../package.json';
import reportWebVitals from './reportWebVitals';

// Handle Vite CSS preload errors gracefully — but NOT JS module failures.
// Suppressing JS module preload errors prevents handleChunkLoadError from firing,
// causing React.lazy to receive undefined and crash with:
// "TypeError: undefined is not an object (evaluating 'e._result.default')"
window.addEventListener('vite:preloadError', event => {
  const err = (event as CustomEvent & {payload?: Error}).payload;
  if (err?.message?.includes('CSS') || err?.message?.includes('css')) {
    event.preventDefault();
  }
});

// Handle chunk loading failures by reloading the page (once) to get fresh assets
// This commonly happens after deployments when users have stale HTML referencing old chunks
const CHUNK_RELOAD_KEY = 'chunk_load_reload';
const handleChunkLoadError = (error: Error): never => {
  const hasReloaded = sessionStorage.getItem(CHUNK_RELOAD_KEY);
  if (!hasReloaded) {
    sessionStorage.setItem(CHUNK_RELOAD_KEY, 'true');
    window.location.reload();
  }
  // If we've already reloaded once, throw the error to show error state
  throw error;
};

// Clear the reload flag on successful page load
window.addEventListener('load', () => {
  sessionStorage.removeItem(CHUNK_RELOAD_KEY);
});

const V2App = lazy(() => import('v2/src/App').catch(handleChunkLoadError));

import('v2/src/styles/index.css');

// Set up Sentry user context with web_funnel_anon_id
const anonId = Identity.ensureAnonymousID();
Sentry.setUser({
  web_funnel_anon_id: anonId,
});

Sentry.init({
  environment: Environment.isProduction ? 'production' : 'test',
  release: `rise-web-funnel@${packageJson.version}`,
  dsn: 'https://e9e809f7580fb64ecb1d02c5d4f540a5@o107506.ingest.us.sentry.io/4507862165553152',
  integrations: [
    Sentry.browserTracingIntegration(),
    Sentry.replayIntegration({
      maskAllText: false,
      blockAllMedia: false,
      maskAllInputs: true,
    }),
  ],
  // Tracing
  tracesSampleRate: 1.0, //  Capture 100% of the transactions
  // Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled
  // tracePropagationTargets: ["localhost", /^https:\/\/yourserver\.io\/api/],
  // Session Replay
  replaysSessionSampleRate: Environment.isProduction ? 0.1 : 1.0, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
  replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.

  beforeSend(event) {
    const error = event.exception?.values?.[0];

    // Filter out errors from iOS in-app browsers (Instagram, Facebook) injecting
    // webkit message handler bridge code that fails outside the native app context.
    // These are not caused by our code and account for ~68% of error volume.
    if (error?.value?.includes('webkit.messageHandlers')) {
      return null;
    }

    // Track error in Analytics
    if (error) {
      const frames = error.stacktrace?.frames ?? [];
      const topFrames = frames
        .slice(-10)
        .map(f => `${f.filename ?? '?'}:${f.lineno ?? '?'}:${f.colno ?? '?'} ${f.function ?? ''}`)
        .join('\n');
      Analytics.track('Error Captured', {
        error_type: error.type,
        error_value: error.value,
        error_stack: topFrames.slice(0, 2000),
        environment: Environment.isProduction ? 'production' : 'test',
      });
    }
    return event;
  },
});

const options = {
  autoConfig: true, // set pixel's autoConfig. More info: https://developers.facebook.com/docs/facebook-pixel/advanced/
  debug: false, // enable logs
};

ReactPixel.init('689199994939883', undefined, options);

ReactPixel.pageView(); // For tracking page view

const _payPalOptions = {
  clientId: 'ATOpBcQQXFZHgIamIabQJYQLF4J7CW3XGMeBFMpMNOEVQ4-9yfX_kTLSMGdu92yDYfrXqhJ5NS62wPJG',
  currency: getPayPalCurrency(),
  intent: 'capture',
  vault: true,
};

Analytics.setLoadStartTime();

// Set anon ID attribute synchronously so inline experiments can hash immediately.
// ensureAnonymousID() reads/generates from localStorage — no async needed.
growthBook.setAttributes({web_funnel_anon_id: Identity.ensureAnonymousID()});

// Kick off the full GB init (CDN fetch, Segment ID reconciliation) in the background.
// Remote feature flags will resolve async; inline experiments work immediately.
setupGrowthbook();

const AppRoot = () => {
  useEffectOnce(() => {
    const {
      countryCode: country,
      userLanguages,
      timezone,
      timezoneStrategy,
      countryByTimezone,
      localeToFormatCurrency,
    } = getUserCountry();

    Analytics.track('Country Code Determined', {
      country,
      userLanguages,
      timezone,
      timezoneStrategy,
      countryByTimezone,
      localeToFormatCurrency,
    });

    Analytics.identify({
      web_country_code: country,
      web_timezone: timezone,
      web_locale_to_format_currency: localeToFormatCurrency,
    });
  });

  return (
    <GrowthBookProvider growthbook={growthBook}>
      <PayPalScriptProvider options={_payPalOptions}>
        <BrowserRouter>
          <Suspense fallback={<div />}>
            <V2App />
          </Suspense>
        </BrowserRouter>
      </PayPalScriptProvider>
    </GrowthBookProvider>
  );
};

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(<AppRoot />);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals(console.log);
