import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { Stack, useRouter, useSegments } from "expo-router";
import * as SplashScreen from "expo-splash-screen";
import React, { useEffect, useState } from "react";
import { StatusBar } from "expo-status-bar";
import { Platform, View, StyleSheet, Text } from "react-native";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { trpc, trpcReactClient } from "@/lib/trpc";
import { AuthProvider, useAuth } from "@/lib/auth-context";
import { useDemoLedger } from "@/lib/demo-ledger";
import { ErrorBoundary } from "@/components/ErrorBoundary";
import { ThankYouBurst } from "@/components/ThankYouBurst";
import { runSensitiveRuntimeProtection } from "@/lib/security/runtime-protection";
import { ThemeProvider } from "@zendo/design-system";
import { WebScrollableRoot } from "@/lib/web/WebScrollableRoot";

const ONBOARDING_SEEN_KEY = "@zendo/onboarding_seen";

SplashScreen.preventAutoHideAsync();

const queryClient = new QueryClient();

function RootLayoutNav() {
  const { isAuthenticated, isLoading, isDemoMode, updateDemoUser } = useAuth();
  const segments = useSegments();
  const router = useRouter();
  const [hasSeenOnboarding, setHasSeenOnboarding] = useState(false);
  const [onboardingChecked, setOnboardingChecked] = useState(false);
  const ledgerBalance = useDemoLedger((s) => s.balance);
  const generateRandomIncoming = useDemoLedger((s) => s.generateRandomIncoming);
  const processDueScheduledSends = useDemoLedger((s) => s.processDueScheduledSends);

  // The ledger is the source of truth for demo balance - mirror it onto the
  // cached user object so every screen that already reads user.balance keeps
  // working without change.
  useEffect(() => {
    if (isDemoMode) {
      updateDemoUser({ balance: ledgerBalance });
    }
  }, [isDemoMode, ledgerBalance, updateDemoUser]);

  // Makes demo mode feel alive even if you just sit on the home screen - an occasional incoming payment, the same way production traffic would
  // produce them, just generated locally instead of over the network.
  useEffect(() => {
    if (!isDemoMode) return;
    const interval = setInterval(() => {
      if (Math.random() < 0.5) generateRandomIncoming();
    }, 60000 + Math.random() * 30000);
    return () => clearInterval(interval);
  }, [isDemoMode, generateRandomIncoming]);

  // Scheduled Sends fire on their own once they're due, the same way a real
  // payment scheduler would tick over things in the background. A 15s poll
  // is plenty for a demo clock - nobody's waiting on split-second timing.
  useEffect(() => {
    if (!isDemoMode) return;
    const interval = setInterval(() => {
      processDueScheduledSends();
    }, 15000);
    return () => clearInterval(interval);
  }, [isDemoMode, processDueScheduledSends]);

  useEffect(() => {
    AsyncStorage.getItem(ONBOARDING_SEEN_KEY)
      .then((value) => setHasSeenOnboarding(value === "true"))
      .finally(() => setOnboardingChecked(true));
  }, []);

  useEffect(() => {
    if (isLoading || !onboardingChecked) return;

    SplashScreen.hideAsync().catch(() => {
      // already hidden, ignore
    });

    const inAuthGroup = segments[0] === "auth";
    const inOnboarding = segments[0] === "onboarding";
    const inAdmin = segments[0] === "admin";

    if (isDemoMode && (inAuthGroup || inOnboarding)) {
      router.replace("/(tabs)");
    } else if (!isAuthenticated && !isDemoMode && !hasSeenOnboarding && !inOnboarding && !inAuthGroup && !inAdmin) {
      router.replace("/onboarding");
    } else if (!isAuthenticated && !isDemoMode && !inAuthGroup && !inOnboarding && !inAdmin) {
      router.replace("/auth");
    } else if (isAuthenticated && (inAuthGroup || inOnboarding)) {
      router.replace("/(tabs)");
    }
  }, [isAuthenticated, isLoading, isDemoMode, hasSeenOnboarding, onboardingChecked, segments, router]);

  return (
    <>
      <StatusBar style="light" backgroundColor={"#000000"} translucent={false} />
      <Stack screenOptions={{ headerBackTitle: "Back" }}>
        <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
        <Stack.Screen name="auth" options={{ headerShown: false }} />
        <Stack.Screen name="onboarding" options={{ headerShown: false }} />
      </Stack>
      {isDemoMode && <ThankYouBurst />}
    </>
  );
}

// Web container — full viewport; scrolling handled by WebScrollableRoot.
const WebContainer = ({ children }: { children: React.ReactNode }) => (
  <View style={styles.webContainer}>
    <WebScrollableRoot>{children}</WebScrollableRoot>
  </View>
);

export default function RootLayout() {
  const [runtimeBlocked, setRuntimeBlocked] = useState(false);

  useEffect(() => {
    const strictMode =
      (process.env.EXPO_PUBLIC_RUNTIME_GUARD_STRICT ?? "true").toLowerCase() === "true";
    if (!strictMode) return;

    runSensitiveRuntimeProtection("security")
      .then((result) => {
        if (!result.ok) {
          setRuntimeBlocked(true);
        }
      })
      .catch(() => {
        setRuntimeBlocked(true);
      });
  }, []);

  if (runtimeBlocked) {
    return (
      <View style={styles.blockedContainer}>
        <Text style={styles.blockedTitle}>Security protection triggered</Text>
        <Text style={styles.blockedBody}>
          This runtime environment failed integrity/debug checks for sensitive modules.
        </Text>
      </View>
    );
  }

  const content = (
    <ErrorBoundary>
      <ThemeProvider initialPreference="dark">
        <trpc.Provider client={trpcReactClient} queryClient={queryClient}>
          <QueryClientProvider client={queryClient}>
            <AuthProvider>
              <RootLayoutNav />
            </AuthProvider>
          </QueryClientProvider>
        </trpc.Provider>
      </ThemeProvider>
    </ErrorBoundary>
  );

  if (Platform.OS === "web") {
    return <WebContainer>{content}</WebContainer>;
  }

  return content;
}

const styles = StyleSheet.create({
  blockedContainer: {
    flex: 1,
    backgroundColor: "#000000",
    justifyContent: "center",
    alignItems: "center",
    paddingHorizontal: 24,
  },
  blockedTitle: {
    color: "#ffffff",
    fontSize: 20,
    fontWeight: "700",
    marginBottom: 12,
    textAlign: "center",
  },
  blockedBody: {
    color: "#d1d5db",
    fontSize: 14,
    textAlign: "center",
    lineHeight: 20,
  },
  webContainer: {
    flex: 1,
    width: "100%",
    backgroundColor: "#000000",
    ...(Platform.OS === "web" ? ({ minHeight: "100vh", height: "100vh" } as object) : {}),
  },
});
