declare const __TURNSTILE_SITE_KEY__: string;

declare global {
    interface Window {
        onTurnstileCallback?: (token: string) => void;
    }
}

import '../css/app.css';
import './bootstrap';

import { createInertiaApp, router } from '@inertiajs/react';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { createRoot } from 'react-dom/client';
import { toast } from 'sonner';
import { getCsrfToken, refreshCsrfToken, updateCsrfToken } from './bootstrap';
import { initializeTheme } from './hooks/ui/use-appearance';
import { route as customRoute, setZiggyRoute } from './lib/route-helper';

// Store the original Ziggy route function before overwriting
// This prevents infinite recursion in route-helper
if (typeof window !== 'undefined') {
    if (typeof route === 'function') {
        setZiggyRoute(route);
    }
}

// Set custom route helper as global window.route
// This replaces Ziggy's route helper with our secure implementation
if (typeof window !== 'undefined') {
    (window as any).route = customRoute;
}

// Configure Inertia CSRF handling
if (typeof window !== 'undefined') {
    router.on('before', (_event) => {
        const token = getCsrfToken();
        if (token) {
            const metaTag = document.querySelector('meta[name="csrf-token"]');
            if (metaTag && metaTag.getAttribute('content') !== token) {
                metaTag.setAttribute('content', token);
            }
        }
    });
}

createInertiaApp({
    resolve: (name) => resolvePageComponent(`./pages/${name}.tsx`, import.meta.glob('./pages/**/*.tsx')),
    setup({ el, App, props }) {
        // Update CSRF token from initial page props
        const initialCsrfToken = (props.initialPage?.props as { csrfToken?: string })?.csrfToken;
        if (initialCsrfToken) {
            updateCsrfToken(initialCsrfToken);
        } else {
            const token = getCsrfToken();
            if (token && typeof window !== 'undefined' && (window as any).axios) {
                (window as any).axios.defaults.headers.common['X-CSRF-TOKEN'] = token;
            }
        }

        const root = createRoot(el);
        root.render(<App {...props} />);

        // Clear the data-page attribute after mounting to hide Inertia props from view source
        // This runs after React has mounted and read the initial props
        requestAnimationFrame(() => {
            if (el.hasAttribute('data-page')) {
                el.removeAttribute('data-page');
            }
        });
    },
    progress: {
        color: '#4B5563',
    },
});

// This will set light / dark mode on load...
initializeTheme();

// Handle 419 errors globally - CSRF token mismatch
let isHandling419 = false;

// Handle unhandled promise rejections
if (typeof window !== 'undefined') {
    window.addEventListener('unhandledrejection', (event) => {
        console.error('Unhandled Promise Rejection:', event.reason);
        // If the error is the obscure "W" error, we might want to reload or show a friendlier message
        if (event.reason === 'W' || (event.reason instanceof Error && event.reason.message === 'W')) {
            console.warn('Caught known obscure "W" error. This might be a transient build or network issue.');
        }
    });
}

router.on('error', async (event) => {
    const response = (event.detail as any)?.response;
    const data = (event.detail as any)?.response?.data;

    // Handle 429 Too Many Requests
    if (response?.status === 429) {
        const message = data?.message || data?.toast?.message || 'Terlalu banyak permintaan. Silakan tunggu beberapa saat.';
        const retryAfter = data?.retry_after || 60;

        toast.error(message, {
            duration: 5000,
            description: `Silakan coba lagi dalam ${retryAfter} detik`,
        });
        return;
    }

    if (response?.status === 419 && !isHandling419) {
        isHandling419 = true;

        // Try to refresh CSRF token first
        const newToken = await refreshCsrfToken();
        if (newToken) {
            isHandling419 = false;
            // Token refreshed, reload the page to retry with new token
            window.location.reload();
        } else {
            isHandling419 = false;
            // If token refresh failed, redirect to login
            window.location.href = '/login';
        }
    }
});

// Update CSRF token from successful Inertia responses
router.on('success', (event) => {
    const page = (event.detail as any)?.page;
    const newCsrfToken = page?.props?.csrfToken;

    if (newCsrfToken) {
        updateCsrfToken(newCsrfToken);
    }
});
