import App from '@app/App';
import store, { persistor } from '@app/store';
import MobileErrorBoundary from '@components/core/mobile-error-boundary';
import SnackbarDismissButton from '@components/core/snackbar-dismiss-button';
import YupLocaleProvider from '@components/core/yup-locale-provider';
import { Config } from '@config/index';
import CssBaseline from '@mui/material/CssBaseline';
import { StyledEngineProvider, ThemeProvider } from '@mui/material/styles';
import theme from '@styles/theme';
import { postAppLoadHooks, preAppLoadHooks } from '@utils/globalHooks';
import '@utils/i18n';
import { defineYupValidators } from '@utils/validation';
import { SnackbarKey, SnackbarProvider } from 'notistack';
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import './index.css';

// Every toast carries a dismiss control: durations now scale with message length
// and can reach 12s, and a long message the reader cannot close is worse than one
// that vanishes too fast (WCAG 2.2.1 Timing Adjustable). Declared once here so no
// future toast can ship without it.
//
// Defined at module scope so the `action` prop keeps a stable identity across
// renders rather than handing notistack a new function every time.
const renderSnackbarDismiss = (key: SnackbarKey) => <SnackbarDismissButton snackbarKey={key} />;

defineYupValidators();

// Sentry ships in its own chunk and initializes after the page is idle: replay +
// tracing cost ~100KB gz and none of it helps first paint (perf H0.5). Nothing is
// lost in the gap: these listeners run from the first module execution, queue any
// pre-init error, and an error PULLS the SDK in immediately so boot crashes are
// reported without waiting for idle. The queue replays into Sentry after init.
const bootErrors: Array<{ error?: unknown; message: string }> = [];
const queueBootError = (event: ErrorEvent) => {
  bootErrors.push({ error: event.error, message: event.message || 'Unknown boot error' });
  void startSentry();
};
const queueBootRejection = (event: PromiseRejectionEvent) => {
  bootErrors.push({ error: event.reason, message: 'Unhandled rejection before Sentry init' });
  void startSentry();
};
let sentryStarted = false;
const startSentry = () => {
  if (sentryStarted) return Promise.resolve();
  sentryStarted = true;
  return import('@tracking/error/bootstrap').then((m) => {
    window.removeEventListener('error', queueBootError);
    window.removeEventListener('unhandledrejection', queueBootRejection);
    m.initSentry(bootErrors.splice(0));
  });
};
if (import.meta.env.PROD) {
  window.addEventListener('error', queueBootError);
  window.addEventListener('unhandledrejection', queueBootRejection);
  window.addEventListener('load', () => {
    if ('requestIdleCallback' in window) window.requestIdleCallback(() => startSentry(), { timeout: 4000 });
    else setTimeout(startSentry, 2500);
  });
}

preAppLoadHooks();
ReactDOM.createRoot(document.getElementById('root')!).render(
  // HINT: StrictMode double renders the app in development mode, which is
  // useful for detecting issues.
  // See: https://reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects
  <React.StrictMode>
    <MobileErrorBoundary>
      <Provider store={store}>
        <PersistGate loading={null} persistor={persistor}>
          <YupLocaleProvider>
            <StyledEngineProvider injectFirst>
              <ThemeProvider theme={theme} defaultMode="light">
                <SnackbarProvider
                  maxSnack={Config.snackbarStackLimit}
                  classes={{ containerRoot: 'notistackContainer' }}
                  action={renderSnackbarDismiss}
                >
                  <CssBaseline enableColorScheme={false} />
                  <App />
                </SnackbarProvider>
              </ThemeProvider>
            </StyledEngineProvider>
          </YupLocaleProvider>
        </PersistGate>
      </Provider>
    </MobileErrorBoundary>
  </React.StrictMode>
);
postAppLoadHooks();
