import { RouterProvider, createRouter } from "@tanstack/react-router";
import { routeTree } from "./routeTree.gen";
import { QueryClientProvider } from "@tanstack/react-query";
import { queryClient } from "./lib/query";
import { useAuthStore } from "@/stores/auth/authStore";
import { RouterContext } from "@/types/routerContext";
import { useState, useEffect, useRef } from "react";
import NotFound from "@/app/pages/404/page";
import { Toaster } from "@/components/ui/sonner";
import { Helmet } from "react-helmet-async";
import TrialDialog from "./app/pages/billing/components/TrialDialog";
import { useBillingStore } from "@/stores/billing/BillingStore";
import useUserStore from "@/stores/Data/useUserStore";
import { useOnboarding } from "@/hooks/useOnboarding";
import { useQuery } from "@tanstack/react-query";
import { getCalls } from "@/api/authApi";
import { getTheme } from "./api/theme";
import { useTheme } from "@/hooks/useTheme";
import { GoogleOAuthProvider } from "@react-oauth/google";


const createAppRouter = (authStore: RouterContext["authStore"]) =>
  createRouter({
    routeTree,
    context: {
      authStore,
      queryClient,
    } as RouterContext,
    defaultPreloadDelay: 100,
    defaultNotFoundComponent: () => <NotFound />,
  });

declare module "@tanstack/react-router" {
  interface Register {
    router: typeof createAppRouter;
  }
}

function InnerApp() {
  const authStore = useAuthStore();
  const [router] = useState(() => createAppRouter(authStore));
  const { user, isAuthenticated, isHydrated } = useAuthStore();
  const { isTrial } = useBillingStore();
  const recruiter = useUserStore((state: unknown) => (state as { user: { subscriptionSettings?: string } | null }).user);
  const { themeData } = useTheme(); 
  const hasHydrated = useRef(false);

  // Simplified initialization
  const [isInitializing, setIsInitializing] = useState(true);

  useEffect(() => {
    if (!hasHydrated.current) {
      hasHydrated.current = true;
      
      // Hydrate auth state
      useAuthStore.getState().hydrate().finally(() => {
        // Remove HTML loader after hydration
        const htmlLoader = document.getElementById('initial-loader');
        if (htmlLoader) {
          htmlLoader.style.opacity = '0';
          setTimeout(() => htmlLoader.remove(), 100);
        }
        
        // Mark initialization as complete
        setIsInitializing(false);
      });
    }
  }, []); 

  // Defer non-critical API calls until after initial render
  const shouldFetchCalls = !!(user && isAuthenticated && isHydrated && !isInitializing);
  const { data: callsData, error: callsError } = useQuery({
    queryKey: ["calls"],
    queryFn: () => new Promise(resolve => {
      // Defer this call by 1 second to not block initial render
      setTimeout(() => resolve(getCalls()), 1000);
    }),
    enabled: shouldFetchCalls,
    staleTime: 1000 * 60 * 15, // 15 minutes cache
    refetchInterval: false, // Disable automatic refetching
    refetchOnWindowFocus: false,
    retry: 1,
    refetchOnMount: false,
  });
  const minutesLimits = (callsData as { minutesLimits?: unknown })?.minutesLimits;
  const { shouldShowOnboarding, isStrictOnboarding } = useOnboarding(minutesLimits as { totalAllowed: number; minutesUsed: number; freeMinutes: number; secondsRemainder: number; } | undefined);

  // Defer theme loading significantly - not critical for initial render
  const { data: themeQueryData, error: themeError } = useQuery({
    queryKey: ["theme"],
    queryFn: () => new Promise(resolve => {
      // Defer theme loading by 2 seconds
      setTimeout(() => resolve(getTheme()), 2000);
    }),
    enabled: shouldFetchCalls && !isInitializing, // Only after user data is loaded
    staleTime: 1000 * 60 * 60 * 4, // 4 hours cache
    retry: 1,
    refetchOnWindowFocus: false,
  });

  // Check if user should see onboarding but can skip (non-subscribed users)
  const shouldShowSkippableOnboarding = !!(
    user && 
    isAuthenticated && 
    isHydrated &&
    user.isOnboarded && 
    !user.role?.includes('superAdmin') && 
    user.userType !== 'enterprise' &&
    minutesLimits && 
    (minutesLimits as { minutesUsed: number }).minutesUsed > 0 &&
    !isStrictOnboarding
  );

  // Remove debug logs and optimize theme effect
  useEffect(() => {
    // Only log in development
    if (process.env.NODE_ENV === 'development') {
      if (themeQueryData) {
          console.log("Theme loaded:", (themeQueryData as { data?: { data?: { theme?: unknown } } })?.data?.data?.theme);
      }
      if (themeError) {
        console.error("Failed to fetch theme:", themeError);
      }
    }
  }, [themeQueryData, themeError]);

  // Optimize onboarding logic with memoization and reduced dependencies
  useEffect(() => {
    // Only run onboarding logic if user is authenticated and hydrated and not initializing
    if (!user || !isAuthenticated || !isHydrated || isInitializing) return;
    
    // Prevent redirect loops - if we're already on onboarding, don't redirect again
    if (window.location.pathname === '/onboarding') return;
    
    // Only log in development
    if (process.env.NODE_ENV === 'development') {
      console.log("Onboarding check:", {
        user: user?.email,
        pathname: window.location.pathname,
        shouldShowOnboarding: shouldShowOnboarding(),
        isStrictOnboarding
      });
    }
    
    // Force onboarding for required cases (can't skip)
    if (shouldShowOnboarding()) {
      router.navigate({ to: '/onboarding' });
      return;
    }
    
    // If strict onboarding, block navigation away from onboarding
    if (isStrictOnboarding) {
      router.navigate({ to: '/onboarding' });
      return;
    }
    
    // Show skippable onboarding only on login/dashboard visit, but don't force it on every navigation
    if (shouldShowSkippableOnboarding && 
        (window.location.pathname === '/' || window.location.pathname === '/dashboard') &&
        !sessionStorage.getItem('onboardingSkipped')) {
      router.navigate({ to: '/onboarding' });
    }
  }, [user, isAuthenticated, isHydrated, isInitializing, shouldShowOnboarding, isStrictOnboarding, shouldShowSkippableOnboarding, router]);

  // If getCalls fails, do not log out or break session, just ignore onboarding logic
  if (callsError) {
    // Optionally log error, but do not break session
    // console.error('Failed to fetch call limits:', callsError);
  }

  // Use theme title if available, otherwise fall back to user company name or default
  const pageTitle = themeData?.title || user?.companyName || "AI Dashboard";

  // Show loading spinner while initializing
  if (isInitializing) {
    return (
      <div className="min-h-screen bg-background flex items-center justify-center">
        <div className="text-center space-y-4">
          <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary mx-auto"></div>
          <p className="text-sm text-muted-foreground">Loading...</p>
        </div>
      </div>
    );
  }

  return (
    <>
      <RouterProvider router={router} context={{ authStore, queryClient }} />
      <div className="font-interRegular">
        <Helmet>
          <title>{pageTitle}</title>
        </Helmet>
        {isTrial && recruiter?.subscriptionSettings === "trial" && <TrialDialog />}
        <Toaster position="top-right" />
      </div>
    </>
  );
}

const App = () => {
  return (
    <div className="font-interRegular">
      <GoogleOAuthProvider clientId={import.meta.env.VITE_GOOGLE_CLIENT_ID}>
        <QueryClientProvider client={queryClient}>
          <InnerApp />
        </QueryClientProvider>
      </GoogleOAuthProvider>
    </div>
  );
};

export default App;