import { createRoot } from 'react-dom/client';
import React from 'react';
=======
import React from 'react';
>>>>>>> 9e4a9bcd (Create test-rakshit branch with current updates)
>>>>>>> origin/main
import { HelmetProvider } from 'react-helmet-async';
import { BrowserRouter } from 'react-router-dom';
import { AppProvider } from './AppInitializer';
import { ErrorBoundary } from './components/ErrorBoundary';
import { AppProviders } from './components/providers/AppProviders';
import env from './config/env';
import './index.css';
import { logger } from './lib/logging/logger';
import { captureError, initSentry } from './lib/monitoring/sentry';
import { AuthProvider } from './providers/AuthProvider';
import { FeaturePolicyProvider } from './providers/FeaturePolicyProvider';
import { initPerformanceTracker } from './services/performance/PerformanceTracker';
import { RenderQualityManager } from './utils/gpuQuality';
import { safeguards } from './utils/productionSafeguards';
// Static import to ensure all App deps are in Vite module graph from start,
// preventing mid-session dep re-optimization that causes duplicate React instances.
import App from './App';

import { SubscriptionProvider } from './hooks/useSubscription';

/** Error boundary that catches SubscriptionProvider crashes (e.g., React hooks mismatch during HMR) and renders children without subscription context */
class SafeSubscriptionProvider extends React.Component<{children: React.ReactNode}, {hasError: boolean}> {
  override state = { hasError: false };
  static getDerivedStateFromError() { return { hasError: true }; }
  override render() {
    if (this.state.hasError) {
      // On error, render children without subscription context (graceful degradation)
      return <>{this.props.children}</>;
    }
    return <SubscriptionProvider>{this.props.children}</SubscriptionProvider>;
  }
}

/** Same safety wrapper for FeaturePolicyProvider — prevents HMR hook crashes from breaking the app */
class SafeFeaturePolicyProvider extends React.Component<{children: React.ReactNode}, {hasError: boolean}> {
  override state = { hasError: false };
  static getDerivedStateFromError() { return { hasError: true }; }
  override render() {
    if (this.state.hasError || (import.meta.env.DEV && typeof window !== 'undefined' && window.location.hostname === 'localhost')) return <>{this.props.children}</>;
    return <FeaturePolicyProvider>{this.props.children}</FeaturePolicyProvider>;
  }
}

/** Safety wrapper for AppProvider — catches duplicate-React hook crashes from dep re-optimization */
class SafeAppProvider extends React.Component<{children: React.ReactNode}, {hasError: boolean}> {
  override state = { hasError: false };
  static getDerivedStateFromError() { return { hasError: true }; }
  override componentDidCatch(error: Error) {
    if (import.meta.env.DEV) {
      console.warn('[SafeAppProvider] AppProvider crashed, rendering without initialization context. This is usually caused by Vite dep re-optimization creating duplicate React instances. Try: rm -rf node_modules/.vite && restart dev server.', error.message);
    }
  }
  override render() {
    if (this.state.hasError) return <>{this.props.children}</>;
    return <AppProvider>{this.props.children}</AppProvider>;

/** Error boundary that catches SubscriptionProvider crashes (e.g., React hooks mismatch during HMR) and renders children without subscription context */
class SafeSubscriptionProvider extends React.Component<{children: React.ReactNode}, {hasError: boolean}> {
  override state = { hasError: false };
  static getDerivedStateFromError() { return { hasError: true }; }
  override render() {
    // Always bypass SubscriptionProvider in dev to avoid React hooks mismatch during Vite dep optimization.
    // In production, SubscriptionProvider would be loaded here via dynamic import.
    // For now, feature gating is handled by PAYMENT_CONFIG.billingBypass in env.ts.
    return <>{this.props.children}</>;
  }
}

/** Same safety wrapper for FeaturePolicyProvider — prevents HMR hook crashes from breaking the app */
class SafeFeaturePolicyProvider extends React.Component<{children: React.ReactNode}, {hasError: boolean}> {
  override state = { hasError: false };
  static getDerivedStateFromError() { return { hasError: true }; }
  override render() {
    if (this.state.hasError || (import.meta.env.DEV && typeof window !== 'undefined' && window.location.hostname === 'localhost')) return <>{this.props.children}</>;
    return <FeaturePolicyProvider>{this.props.children}</FeaturePolicyProvider>;
>>>>>>> origin/main
  }
}

// ─── Global Unhandled Promise Rejection Handler ─────────────────────────────
// Prevents unhandled async errors from crashing the app. Logs to console and
// reports to Sentry when available.
window.addEventListener('unhandledrejection', (event: PromiseRejectionEvent) => {
  const error = event.reason;
  const errorMessage = error instanceof Error ? error.message : String(error);

  logger.error('[UnhandledRejection] Unhandled promise rejection caught', {
    error: errorMessage,
    stack: error instanceof Error ? error.stack : undefined,
  });

  // Report to Sentry if available (non-blocking)
  try {
    captureError(
      error instanceof Error ? error : new Error(`Unhandled rejection: ${errorMessage}`),
      { source: 'unhandledrejection' },
    );
  } catch {
    // Sentry may not be initialized yet — ignore
  }

  // Prevent the default browser behavior (console error is already logged above)
  event.preventDefault();
});

// Setup root element error display (XSS-safe: uses textContent, not innerHTML)
function showRootError(message: string, details?: string) {
  const rootElement = document.getElementById('root');
  if (rootElement) {
    // Clear existing content
    rootElement.textContent = '';

    const container = document.createElement('div');
    container.style.cssText =
      'padding: 40px; background: radial-gradient(circle at top right, #102347 0%, #060d1d 40%, #050a18 100%); color: #e9f1ff; min-height: 100vh; font-family: Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif;';

    const heading = document.createElement('h1');
    heading.style.cssText = 'color: #ffd0d0; font-size: 1.35rem; margin: 0 0 12px 0; letter-spacing: 0.01em;';
    heading.textContent = `⚠️ ${message}`;
    container.appendChild(heading);

    if (!details) {
      const subtitle = document.createElement('p');
      subtitle.style.cssText = 'color: #b7c9ec; margin: 0; max-width: 68ch; line-height: 1.5;';
      subtitle.textContent = 'Please wait while we bootstrap BeamLab. If this persists, refresh the page.';
      container.appendChild(subtitle);
    }

    if (details) {
      const pre = document.createElement('pre');
      pre.style.cssText =
        'background: rgba(10, 18, 36, 0.92); border: 1px solid #2a3d60; padding: 20px; border-radius: 10px; color: #ffc1c1; overflow: auto; white-space: pre-wrap; margin-top: 20px; line-height: 1.45;';
      pre.textContent = details;
      container.appendChild(pre);
    }

    rootElement.appendChild(container);
  }
}

// Lazy load App to catch import errors
const initializeApp = async () => {
  try {
    // Validate environment configuration INSIDE try-catch
    logger.info('Validating environment');
    const envResult = env.validate();
    logger.info('Environment validation passed', { warnings: envResult.warnings.length, errors: envResult.errors.length });

    // Add explicit debug logging
    logger.info('App initialization starting');

    // Initialize Sentry for error tracking via canonical monitoring module.
    try {
      if (env.monitoring.isSentryEnabled) logger.info('Loading Sentry');
      initSentry();
      if (env.monitoring.isSentryEnabled) logger.info('Sentry initialized');
    } catch (sentryError) {
      logger.warn('Sentry initialization failed', { error: sentryError });
      // Continue anyway, Sentry is optional
    }

    // Initialize production safeguards (wrapped in try-catch)
    try {
      logger.info('Initializing safeguards');
      safeguards.initialize();
      logger.info('Safeguards initialized');
    } catch (safeguardsError) {
      logger.warn('Safeguards initialization failed', { error: safeguardsError });
      // Continue anyway, safeguards are optional
    }

    // Start GPU quality detection early (non-blocking)
    RenderQualityManager.init().catch(() => {
      logger.warn('GPU quality detection failed, using defaults');
    });

    // Initialize Core Web Vitals tracking
    initPerformanceTracker();

    // Track Core Web Vitals (LCP, FID, CLS, FCP, TTFB)
    try {
      const { trackWebVitals } = await import('./lib/performance');
      trackWebVitals((metric) => {
        logger.info(`[WebVitals] ${metric.name}: ${metric.value.toFixed(1)}ms (${metric.rating})`);
      });
    } catch {
      logger.warn('Web Vitals tracking unavailable');
    }

    // App is now statically imported at the top of the file
    // (see static import above)
    logger.info('App ready (statically imported)');

    const rootElement = document.getElementById('root');
    if (!rootElement) {
      throw new Error('Root element not found');
    }

    logger.info('Rendering App with providers');

    // Remove the initial static loader now that React is taking over
    const initialLoader = document.getElementById('initial-loader');
    if (initialLoader) {
      initialLoader.remove();
    }
    // Signal to the timeout checker that the app loaded
    (window as any).__beamlab_loaded__ = true;

    // Use unified AuthProvider which handles both Clerk and in-house auth
    // SubscriptionProvider provides subscription/tier context for feature gating
    // ErrorBoundary catches and displays any runtime errors gracefully
    // AppProviders adds: NotificationProvider, ConfirmProvider, CommandPalette (⌘K), KeyboardShortcuts (⌘/)
    // NOTE: StrictMode is intentionally NOT used here.
    // React 18 StrictMode double-invokes effects in development, which causes
    // the R3F Canvas to create and immediately destroy WebGL contexts.
    // Browsers allow only 8-16 WebGL contexts per page; double-mounting
    // exhausts this budget and leaves the 3D viewport blank/black.
    // Strict-mode linting is enforced via ESLint (react-hooks plugin) instead.
    createRoot(rootElement).render(
      <ErrorBoundary
        onError={(error, errorInfo) => {
          logger.error('App error caught by ErrorBoundary', { error });
          logger.error('Component stack trace', { componentStack: errorInfo?.componentStack });
          // captureError is also called inside ErrorBoundary.componentDidCatch,
          // but we call it here too in case the boundary's internal call fails.
          try {
            captureError(error, {
              source: 'root-error-boundary',
              componentStack: errorInfo?.componentStack ?? undefined,
            });
          } catch {
            // Sentry may not be initialized
          }
        }}
      >
        <BrowserRouter>
          <HelmetProvider>
          <AuthProvider>
            <SafeSubscriptionProvider>
              <SafeFeaturePolicyProvider>
                <SafeAppProvider>
                  <AppProviders>
                    <App />
                  </AppProviders>
                </SafeAppProvider>
              </SafeFeaturePolicyProvider>
            </SafeSubscriptionProvider>
          </AuthProvider>
          </HelmetProvider>
        </BrowserRouter>
      </ErrorBoundary>,
    );

    logger.info('App rendered with AuthProvider and SubscriptionProvider');
  } catch (error) {
    logger.error('Failed to initialize app', { error });

    // Show error in DOM
    const errorMessage = error instanceof Error ? error.message : String(error);
    const errorStack = error instanceof Error ? error.stack : '';
    showRootError('App Failed to Load', `Error: ${errorMessage}\n\n${errorStack}`);
  }
};

initializeApp();
