import { ComponentType, FC, useCallback, useEffect, useMemo, useRef, useState } from "react" // eslint-disable-next-line no-restricted-imports import { Image, ImageStyle, TextInput, TextStyle, View, ViewStyle } from "react-native" import { useFocusEffect } from "@react-navigation/native" import { Button } from "@/components/Button" import { Icon, PressableIcon } from "@/components/Icon" import { Screen } from "@/components/Screen" import { Text } from "@/components/Text" import { TextField, type TextFieldAccessoryProps } from "@/components/TextField" import { useAuth } from "@/context/AuthContext" import type { AppStackScreenProps } from "@/navigators/navigationTypes" import { useAppTheme } from "@/theme/context" import type { ThemedStyle } from "@/theme/types" import { s } from "@/utils/responsive" interface LoginScreenProps extends AppStackScreenProps<"Login"> {} export const LoginScreen: FC = ({ navigation }) => { const authPasswordInput = useRef(null) const verificationCodeInput = useRef(null) const [email, setEmail] = useState("") const [password, setPassword] = useState("") const [verificationCode, setVerificationCode] = useState("") const [isPasswordHidden, setIsPasswordHidden] = useState(true) const [resendCountdown, setResendCountdown] = useState(0) const { loginStep, pendingEmail, isLoading, error, preLogin, resendCode, verifyLogin, googleLogin, resetLoginStep, clearError, } = useAuth() const { themed, theme: { colors }, } = useAppTheme() // Email validation const emailError = useMemo(() => { if (!email || email.length === 0) return "" if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) return "Please enter a valid email" return "" }, [email]) // Password validation - requires uppercase, lowercase, number, and special character const passwordError = useMemo(() => { if (!password || password.length === 0) return "" if (password.length < 8) return "Password must be at least 8 characters" if (!/[A-Z]/.test(password)) return "Password must contain an uppercase letter" if (!/[a-z]/.test(password)) return "Password must contain a lowercase letter" if (!/[0-9]/.test(password)) return "Password must contain a number" if (!/[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(password)) return "Password must contain a special character" return "" }, [password]) // Countdown timer for resend button useEffect(() => { if (resendCountdown > 0) { const timer = setTimeout(() => setResendCountdown(resendCountdown - 1), 1000) return () => clearTimeout(timer) } return undefined }, [resendCountdown]) // Auto-focus verification code input when entering verification step useEffect(() => { if (loginStep === "verification") { // Small delay to ensure the input is rendered const timer = setTimeout(() => { verificationCodeInput.current?.focus() }, 100) return () => clearTimeout(timer) } return undefined }, [loginStep]) // Reset state when screen comes into focus (e.g., navigating back from another screen) useFocusEffect( useCallback(() => { // Clear any lingering errors from previous screens clearError() // Reset countdown and verification code when screen is focused // but only if we're on credentials step (not in the middle of verification) if (loginStep === "credentials") { setResendCountdown(0) setVerificationCode("") } }, [loginStep, clearError]), ) // Clear error when inputs change (not when error changes) const prevInputsRef = useRef({ email, password, verificationCode }) useEffect(() => { const prev = prevInputsRef.current // Only clear error if one of the input fields actually changed if ( prev.email !== email || prev.password !== password || prev.verificationCode !== verificationCode ) { if (error) clearError() prevInputsRef.current = { email, password, verificationCode } } }, [email, password, verificationCode, error, clearError]) // Handle pre-login (step 1) const handlePreLogin = useCallback(async () => { if (!email || emailError || !password) return const success = await preLogin(email, password) if (success) { setResendCountdown(60) } }, [email, emailError, password, preLogin]) // Handle verify login (step 2) const handleVerifyLogin = useCallback(async () => { if (!verificationCode || verificationCode.length !== 6) return await verifyLogin(verificationCode) }, [verificationCode, verifyLogin]) // Handle resend code const handleResendCode = useCallback(async () => { if (resendCountdown > 0) return const success = await resendCode() if (success) { setResendCountdown(60) } }, [resendCountdown, resendCode]) // Handle Google login const handleGoogleLogin = useCallback(async () => { await googleLogin() }, [googleLogin]) // Handle back to credentials step const handleBackToCredentials = useCallback(() => { resetLoginStep() setVerificationCode("") }, [resetLoginStep]) // Navigate to register const handleGoToRegister = useCallback(() => { navigation.navigate("Register") }, [navigation]) // Navigate to forgot password const handleGoToForgotPassword = useCallback(() => { navigation.navigate("ForgotPassword") }, [navigation]) // Password visibility toggle const PasswordRightAccessory: ComponentType = useMemo( () => function PasswordRightAccessory(props: TextFieldAccessoryProps) { return ( setIsPasswordHidden(!isPasswordHidden)} /> ) }, [isPasswordHidden, colors.palette.neutral800], ) // Render credentials step (step 1) const renderCredentialsStep = () => ( <> {error ? : null} authPasswordInput.current?.focus()} />