import "./init-interceptor"; // MUST BE FIRST
import "@github/relative-time-element";
import { QueryClientProvider } from "@tanstack/react-query";
import { ClerkProvider } from "@clerk/clerk-react";
import React, { useEffect, useRef } from "react";
import { createRoot } from "react-dom/client";
import { Toaster } from "react-hot-toast";
import { RouterProvider } from "react-router-dom";
import "./i18n";
import "./index.css";
import { ErrorBoundary } from "@/components/ErrorBoundary";
import Spinner from "@/components/Spinner";
import { AuthProvider, useAuth } from "@/contexts/AuthContext";
import { InstanceProvider, useInstance } from "@/contexts/InstanceContext";
import { ViewProvider } from "@/contexts/ViewContext";
import { queryClient } from "@/lib/query-client";
import router from "./router";
import { applyLocaleEarly } from "./utils/i18n";
import { applyThemeEarly } from "./utils/theme";
import "leaflet/dist/leaflet.css";
import "katex/dist/katex.min.css";

// Apply theme and locale early to prevent flash
applyThemeEarly();
applyLocaleEarly();

// Inner component that initializes contexts
function AppInitializer({ children }: { children: React.ReactNode }) {
  const { isInitialized: authInitialized, initialize: initAuth } = useAuth();
  const { isInitialized: instanceInitialized, initialize: initInstance } = useInstance();
  const initStartedRef = useRef(false);

  // Initialize on mount - run in parallel for better performance
  useEffect(() => {
    if (initStartedRef.current) return;
    initStartedRef.current = true;

    /* 
       Khi dùng Clerk, ta có thể bỏ initAuth() của hệ thống cũ đi 
       nếu AuthProvider đã được viết lại để dùng Clerk.
       Tuy nhiên, để an toàn, ta cứ để cả 2 chạy song song nếu AuthProvider chưa sửa.
    */
    const init = async () => {
      await Promise.all([initInstance(), initAuth()]);
    };
    init();
  }, [initAuth, initInstance]);

  if (!authInitialized || !instanceInitialized) {
    return (
      <div className="w-full h-screen flex items-center justify-center">
        <Spinner size="lg" />
      </div>
    );
  }

  return <>{children}</>;
}

function Main() {
  const publishableKey = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY as string | undefined;

  if (!publishableKey) {
    return (
      <div className="w-full min-h-svh flex items-center justify-center p-6">
        <div className="max-w-xl w-full rounded-xl border border-border bg-background p-6 space-y-3">
          <h1 className="text-xl font-semibold">Missing Clerk publishable key</h1>
          <p className="text-sm text-muted-foreground">
            App requires <code className="px-1 py-0.5 rounded bg-muted">VITE_CLERK_PUBLISHABLE_KEY</code>.
          </p>
        </div>
      </div>
    );
  }

  return (
    <ErrorBoundary>
      <ClerkProvider
        publishableKey={publishableKey}
        signInFallbackRedirectUrl="/app"
        signUpFallbackRedirectUrl="/app"
        afterSignOutUrl="/auth"
      >
        <QueryClientProvider client={queryClient}>
          <InstanceProvider>
            <AuthProvider>
              <ViewProvider>
                <AppInitializer>
                  <RouterProvider router={router} />
                  <Toaster position="top-right" />
                </AppInitializer>
              </ViewProvider>
            </AuthProvider>
          </InstanceProvider>
        </QueryClientProvider>
      </ClerkProvider>
    </ErrorBoundary>
  );
}

const container = document.getElementById("root");
const root = createRoot(container as HTMLElement);
root.render(<Main />);