import '@fontsource-variable/geist';
import '@fontsource-variable/geist-mono';
import '../css/app.css';
import './bootstrap';

import type { Flash, PageProps } from '@/types';
import { createInertiaApp, router } from '@inertiajs/react';
import * as Sentry from '@sentry/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { useEffect, useState } from 'react';
import { type Root, createRoot, hydrateRoot } from 'react-dom/client';
import { toast, Toaster } from 'sonner';

function fireFlash(flash: Flash | undefined | null) {
    if (!flash) return;
    if (flash.success) toast.success(flash.success);
    if (flash.error) toast.error(flash.error);
    if (flash.warning) toast.warning(flash.warning);
    if (flash.info) toast.info(flash.info);
}

function AppToaster() {
    const [isDark, setIsDark] = useState(() =>
        document.documentElement.classList.contains('dark'),
    );

    useEffect(() => {
        const observer = new MutationObserver(() => {
            setIsDark(document.documentElement.classList.contains('dark'));
        });
        observer.observe(document.documentElement, {
            attributes: true,
            attributeFilter: ['class'],
        });
        return () => observer.disconnect();
    }, []);

    return (
        <Toaster
            theme={isDark ? 'dark' : 'light'}
            position="top-right"
            richColors
            closeButton
        />
    );
}

const queryClient = new QueryClient({
    defaultOptions: {
        queries: { staleTime: 30_000, retry: 1, refetchOnWindowFocus: false },
    },
});

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

if (import.meta.env.VITE_SENTRY_DSN_PUBLIC) {
    Sentry.init({
        dsn: import.meta.env.VITE_SENTRY_DSN_PUBLIC,
        environment: import.meta.env.VITE_APP_ENV || 'production',
        integrations: [
            Sentry.browserTracingIntegration(),
            Sentry.replayIntegration(),
        ],
        tracesSampleRate: import.meta.env.PROD ? 0.2 : 1.0,
        replaysSessionSampleRate: 0.1,
        replaysOnErrorSampleRate: 1.0,
    });
}

createInertiaApp({
    title: (title) => `${title} - ${appName}`,
    resolve: (name) =>
        resolvePageComponent(
            `./Pages/${name}.tsx`,
            import.meta.glob('./Pages/**/*.tsx'),
        ),
    setup({ el, App, props }) {
        // Flash toasts on every successful Inertia navigation
        router.on('success', (event) =>
            fireFlash((event.detail.page.props as PageProps).flash),
        );

        // Flash on the very first page load
        fireFlash((props.initialPage.props as PageProps).flash);

        if (import.meta.env.SSR) {
            hydrateRoot(
                el,
                <QueryClientProvider client={queryClient}>
                    <App {...props} />
                    <AppToaster />
                </QueryClientProvider>,
            );
            return;
        }

        const rootEl = el as typeof el & { _root?: Root };
        if (!rootEl._root) {
            rootEl._root = createRoot(el);
        }

        rootEl._root.render(
            <QueryClientProvider client={queryClient}>
                <Sentry.ErrorBoundary
                    fallback={<p>An unexpected error occurred.</p>}
                >
                    <App {...props} />
                </Sentry.ErrorBoundary>
                <AppToaster />
            </QueryClientProvider>,
        );
    },
    progress: {
        color: '#4B5563',
    },
});
