import {
	createContext,
	useCallback,
	useContext,
	useEffect,
	useMemo,
	useRef,
	useState,
	type ReactNode,
} from "react";
import { useLocation } from "react-router-dom";
import { SplashScreen } from "../components/pwa/SplashScreen";

const MIN_SPLASH_MS = 400;
const MAX_SPLASH_MS = 8000;
const SKIP_SPLASH_KEY = "sproutclaw-warm-boot";

type BootstrapRoute = "chat" | "settings";

interface BootstrapContextValue {
	markRouteReady: (route: BootstrapRoute) => void;
}

const BootstrapContext = createContext<BootstrapContextValue | null>(null);

export function BootstrapProvider({ children }: { children: ReactNode }) {
	const location = useLocation();
	const route: BootstrapRoute = location.pathname.startsWith("/settings") ? "settings" : "chat";
	const [readyRoutes, setReadyRoutes] = useState<Record<BootstrapRoute, boolean>>({
		chat: false,
		settings: false,
	});
	const [splashVisible, setSplashVisible] = useState(true);
	const [splashExiting, setSplashExiting] = useState(false);
	const mountTime = useRef(Date.now());

	const markRouteReady = useCallback((readyRoute: BootstrapRoute) => {
		setReadyRoutes((prev) => (prev[readyRoute] ? prev : { ...prev, [readyRoute]: true }));
	}, []);

	useEffect(() => {
		setReadyRoutes((prev) => ({ ...prev, [route]: false }));
		setSplashVisible(true);
		setSplashExiting(false);
		mountTime.current = Date.now();
	}, [route]);

	useEffect(() => {
		if (readyRoutes[route]) return;
		const timer = window.setTimeout(() => {
			setReadyRoutes((prev) => (prev[route] ? prev : { ...prev, [route]: true }));
		}, MAX_SPLASH_MS);
		return () => window.clearTimeout(timer);
	}, [route, readyRoutes]);

	useEffect(() => {
		if (!readyRoutes[route]) return;

		let warmBoot = false;
		try {
			warmBoot = sessionStorage.getItem(SKIP_SPLASH_KEY) === "1";
			sessionStorage.setItem(SKIP_SPLASH_KEY, "1");
		} catch {
			/* ignore */
		}

		if (warmBoot) {
			setSplashVisible(false);
			setSplashExiting(false);
			return;
		}

		const elapsed = Date.now() - mountTime.current;
		const remaining = Math.max(0, MIN_SPLASH_MS - elapsed);

		const timer = window.setTimeout(() => {
			setSplashExiting(true);
			window.setTimeout(() => setSplashVisible(false), 420);
		}, remaining);

		return () => window.clearTimeout(timer);
	}, [readyRoutes, route]);

	const value = useMemo(() => ({ markRouteReady }), [markRouteReady]);

	return (
		<BootstrapContext.Provider value={value}>
			{children}
			{splashVisible ? <SplashScreen exiting={splashExiting} /> : null}
		</BootstrapContext.Provider>
	);
}

export function useBootstrap(): BootstrapContextValue {
	const ctx = useContext(BootstrapContext);
	if (!ctx) throw new Error("useBootstrap must be used within BootstrapProvider");
	return ctx;
}
