import React, { useState, useRef, useEffect, useCallback } from 'react'; import { View, Text, StyleSheet, KeyboardAvoidingView, Platform, ScrollView, TouchableOpacity, TextInput, ActivityIndicator, } from 'react-native'; import { router, useLocalSearchParams } from 'expo-router'; import { Ionicons } from '@expo/vector-icons'; import { useAuth } from '@/contexts/AuthContext'; import { Button } from '@/components/ui/Button'; import { ErrorMessage } from '@/components/ui/ErrorMessage'; import { AppColors, BorderRadius, FontSizes, Spacing } from '@/constants/theme'; const CODE_LENGTH = 6; export default function VerifyOTPScreen() { // Params from previous screens const params = useLocalSearchParams<{ email: string; skipOtp: string; isNewUser: string; partnerCode: string; }>(); const email = params.email || ''; const skipOtp = params.skipOtp === '1'; const isNewUser = params.isNewUser === '1'; const partnerCode = params.partnerCode || ''; // Auth context const { verifyOtp, requestOtp, isLoading: authLoading, error: authError, clearError } = useAuth(); // Local state const [code, setCode] = useState(''); const [verifying, setVerifying] = useState(false); const [resending, setResending] = useState(false); const [localError, setLocalError] = useState(null); const [resendCooldown, setResendCooldown] = useState(0); // Refs const inputRef = useRef(null); const hasAutoLoggedIn = useRef(false); // Clear errors on mount useEffect(() => { clearError(); }, []); // Auto-login for skipOtp (dev mode) useEffect(() => { if (!skipOtp || !email || hasAutoLoggedIn.current) return; hasAutoLoggedIn.current = true; console.log('[VerifyOTP] Auto-login for dev email'); const autoLogin = async () => { setVerifying(true); const success = await verifyOtp(email, '000000'); setVerifying(false); if (success) { navigateAfterSuccess(); } else { setLocalError('Auto-login failed'); } }; autoLogin(); }, [skipOtp, email]); // Focus input on mount (if not skipping OTP) useEffect(() => { if (!skipOtp) { setTimeout(() => inputRef.current?.focus(), 100); } }, [skipOtp]); // Resend cooldown timer useEffect(() => { if (resendCooldown > 0) { const timer = setTimeout(() => setResendCooldown(resendCooldown - 1), 1000); return () => clearTimeout(timer); } }, [resendCooldown]); // Navigate after successful verification const navigateAfterSuccess = () => { if (isNewUser) { // New user - continue registration flow (ask name first) console.log('[VerifyOTP] -> enter-name (new user)'); router.replace({ pathname: '/(auth)/enter-name', params: { email, partnerCode }, }); } else { // Existing user - go to main app console.log('[VerifyOTP] -> tabs (existing user)'); router.replace('/(tabs)'); } }; // Handle code input const handleCodeChange = (text: string) => { const digits = text.replace(/\D/g, '').slice(0, CODE_LENGTH); setCode(digits); setLocalError(null); // Auto-submit when complete if (digits.length === CODE_LENGTH) { handleVerify(digits); } }; // Verify OTP const handleVerify = useCallback(async (verifyCode?: string) => { const codeToVerify = verifyCode || code; if (codeToVerify.length !== CODE_LENGTH) { setLocalError('Please enter the 6-digit code'); return; } setVerifying(true); setLocalError(null); console.log('[VerifyOTP] Verifying code for:', email); const success = await verifyOtp(email, codeToVerify); setVerifying(false); if (success) { navigateAfterSuccess(); } else { setLocalError('Invalid verification code. Please try again.'); setCode(''); setTimeout(() => inputRef.current?.focus(), 100); } }, [code, email, verifyOtp, isNewUser, partnerCode]); // Resend OTP const handleResend = useCallback(async () => { if (resendCooldown > 0) return; setResending(true); setLocalError(null); console.log('[VerifyOTP] Resending OTP to:', email); const result = await requestOtp(email); setResending(false); if (result.success) { setResendCooldown(60); setCode(''); } else { setLocalError('Failed to resend code'); } }, [email, resendCooldown, requestOtp]); // Go back const handleBack = () => { router.back(); }; // Render code boxes const renderCodeBoxes = () => { return Array.from({ length: CODE_LENGTH }).map((_, i) => { const isActive = i === code.length; const isFilled = i < code.length; return ( {code[i] || ''} ); }); }; // Auto-login loading screen if (skipOtp) { return ( Signing in... ); } const displayError = localError || authError?.message; return ( Check your email We sent a verification code to {email} {displayError && ( { setLocalError(null); clearError(); }} /> )} {/* Code Input Boxes */} inputRef.current?.focus()} > {renderCodeBoxes()} {/* Hidden Input */}