import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import type { BottomSheetModalRef } from "@umituz/react-native-design-system/molecules"; import { useAuthModalStore } from "../stores/authModalStore"; import { useAuth } from "../hooks/useAuth"; import { useGoogleAuth, type GoogleAuthConfig } from "./useGoogleAuth"; import { useAppleAuth } from "./useAppleAuth"; import type { SocialAuthProvider } from "../../domain/value-objects/AuthConfig"; import { useAuthTransitions, executeAfterAuth, } from "../utils/authTransition.util"; import { determineEnabledProviders } from "../utils/socialAuthHandler.util"; export interface SocialAuthConfiguration { google?: GoogleAuthConfig; apple?: { enabled: boolean }; } interface UseAuthBottomSheetParams { socialConfig?: SocialAuthConfiguration; onGoogleSignIn?: () => Promise; onAppleSignIn?: () => Promise; /** Called when auth completes successfully (login or register) */ onAuthSuccess?: () => void; } export function useAuthBottomSheet(params: UseAuthBottomSheetParams = {}) { const { socialConfig, onGoogleSignIn, onAppleSignIn, onAuthSuccess } = params; const modalRef = useRef(null); const { isVisible, mode, hideAuthModal, setMode, executePendingCallback, clearPendingCallback } = useAuthModalStore(); const { isAuthenticated, isAnonymous } = useAuth(); // Social Auth Hooks const { signInWithGoogle, googleConfigured } = useGoogleAuth(socialConfig?.google); const { signInWithApple, appleAvailable } = useAppleAuth(); // Determine enabled providers // PERFORMANCE: Memoize to prevent recalculation when config hasn't changed const providers = useMemo(() => { return determineEnabledProviders(socialConfig, appleAvailable, googleConfigured); }, [ // Use deep comparison for socialConfig to avoid unnecessary recalculation // when parent passes a new object reference with same values socialConfig?.google?.iosClientId, socialConfig?.google?.webClientId, socialConfig?.google?.androidClientId, socialConfig?.apple?.enabled, appleAvailable, googleConfigured, ]); // Social auth loading states const [googleLoading, setGoogleLoading] = useState(false); const [appleLoading, setAppleLoading] = useState(false); // Handle visibility sync with modalRef useEffect(() => { if (isVisible) { modalRef.current?.present(); } else { modalRef.current?.dismiss(); } }, [isVisible]); const handleDismiss = useCallback(() => { hideAuthModal(); clearPendingCallback(); }, [hideAuthModal, clearPendingCallback]); const handleClose = useCallback(() => { modalRef.current?.dismiss(); handleDismiss(); }, [handleDismiss]); // Handle auth transitions useAuthTransitions( { isAuthenticated, isAnonymous, isVisible }, (result) => { if (result.shouldClose) { modalRef.current?.dismiss(); hideAuthModal(); onAuthSuccess?.(); executeAfterAuth(() => { executePendingCallback(); }); return undefined; } return undefined; } ); const handleNavigateToRegister = useCallback(() => { setMode("register"); }, [setMode]); const handleNavigateToLogin = useCallback(() => { setMode("login"); }, [setMode]); const handleGoogleSignIn = useCallback(async () => { setGoogleLoading(true); try { if (onGoogleSignIn) { await onGoogleSignIn(); } else if (signInWithGoogle) { await signInWithGoogle(); } } finally { setGoogleLoading(false); } }, [onGoogleSignIn, signInWithGoogle]); const handleAppleSignIn = useCallback(async () => { setAppleLoading(true); try { if (onAppleSignIn) { await onAppleSignIn(); } else if (signInWithApple) { await signInWithApple(); } } finally { setAppleLoading(false); } }, [onAppleSignIn, signInWithApple]); return useMemo(() => ({ modalRef, googleLoading, appleLoading, mode, providers, handleDismiss, handleClose, handleNavigateToRegister, handleNavigateToLogin, handleGoogleSignIn, handleAppleSignIn, }), [ modalRef, googleLoading, appleLoading, mode, providers, handleDismiss, handleClose, handleNavigateToRegister, handleNavigateToLogin, handleGoogleSignIn, handleAppleSignIn, ]); }