/* eslint-disable react-refresh/only-export-components */
import './bootstrap';
import '../css/app.css';

import { createRoot, hydrateRoot } from 'react-dom/client';

import type { ComponentType, ReactNode } from 'react';
import { Suspense, lazy } from 'react';

import { createInertiaApp } from '@inertiajs/react';

import { ThemeProvider } from '@/Components/theme';
import { ErrorBoundary } from '@/Components/ui/error-boundary';
import { loadAnalytics } from '@/lib/analytics';

// Initialize analytics on load if consent already given (re-used by CookieConsentBanner on grant)
loadAnalytics();

// Verify analytics infrastructure is loaded after a brief delay
import('@/lib/analytics')
  .then(({ checkAnalyticsHealth }) => checkAnalyticsHealth())
  .catch(() => {});

// Initialize Sentry for client-side error tracking (no-op when DSN not set)
import('@/lib/sentry').then(({ initSentry }) => initSentry()).catch(() => {});

// Loading fallback for lazy-loaded pages
const PageLoader = () => (
  <div className="flex h-screen items-center justify-center">
    <div className="h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent" />
  </div>
);

const appName = import.meta.env.VITE_APP_NAME || 'Laravel';

// Exclude test files from production build - they were adding ~598KB (Vitest + test files)
const pages = import.meta.glob(['./Pages/**/*.{tsx,jsx}', '!**/*.test.{tsx,jsx}']);

const LazyTooltipProvider = lazy(async () => {
  const module = await import('@/Components/ui/tooltip');
  return { default: module.TooltipProvider };
});

const LazyToaster = lazy(async () => {
  const module = await import('@/Components/ui/sonner');
  return { default: module.Toaster };
});

const LazyFlashToasts = lazy(async () => {
  const { useFlashToasts } = await import('@/hooks/useFlashToasts');
  return {
    default: function FlashToasts() {
      useFlashToasts();
      return null;
    },
  };
});

createInertiaApp({
  title: (title) => (title ? `${title} | ${appName}` : appName),
  resolve: (name) => {
    const tsxPath = `./Pages/${name}.tsx`;
    const jsxPath = `./Pages/${name}.jsx`;
    const page = pages[tsxPath] || pages[jsxPath];

    if (!page) {
      throw new Error(`Page not found: ${tsxPath} or ${jsxPath}`);
    }

    return page();
  },
  setup({ el, App, props }) {
    const renderApp = (
      <ErrorBoundary>
      <App {...props}>
        {({ Component, props: pageProps, key }) => {
          const page = <Component key={key} {...pageProps} />;
          const content: ReactNode =
            typeof Component.layout === 'function'
              ? (Component.layout as (page: ReactNode) => ReactNode)(page)
              : Array.isArray(Component.layout)
                ? (Component.layout as ComponentType<{ children: ReactNode }>[])
                    .concat(page as unknown as ComponentType<{ children: ReactNode }>)
                    .reverse()
                    .reduce<ReactNode>(
                      (children, Layout) => <Layout {...pageProps}>{children}</Layout>,
                      null,
                    )
                : page;

          const shouldDisableGlobalUi =
            (Component as { disableGlobalUi?: boolean }).disableGlobalUi === true;

          const renderPageContent = () => <Suspense fallback={<PageLoader />}>{content}</Suspense>;

          return (
            <ThemeProvider>
              {shouldDisableGlobalUi ? (
                renderPageContent()
              ) : (
                <Suspense fallback={renderPageContent()}>
                  <LazyTooltipProvider>
                    {renderPageContent()}
                    <LazyFlashToasts />
                    <LazyToaster richColors position="top-right" />
                  </LazyTooltipProvider>
                </Suspense>
              )}
            </ThemeProvider>
          );
        }}
      </App>
      </ErrorBoundary>
    );

    // If SSR rendered content exists, hydrate; otherwise create new root
    if (el.hasChildNodes()) {
      hydrateRoot(el, renderApp);
    } else {
      createRoot(el).render(renderApp);
    }
  },
  progress: {
    color: '#1e6dd9', // Primary brand color
  },
});
