package com.suno.android.ui.screens.onboarding.phone.input import androidx.lifecycle.viewModelScope import com.google.i18n.phonenumbers.PhoneNumberUtil import com.suno.android.common_core_utils.extensions.xGetFlagEmojiFromRegionCode import com.suno.android.common_mvi.MviProcessorFactory import com.suno.android.common_mvi.MviViewModel import com.suno.android.framework.auth.api.AuthRepository import com.suno.android.framework.auth.api.AuthSignInError import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import java.util.Locale import javax.inject.Inject @HiltViewModel class LoginPhoneNumberScreenVM @Inject constructor( processorFactory: MviProcessorFactory, private val authRepository: AuthRepository, ) : MviViewModel( processorFactory = processorFactory, initialState = LoginPhoneNumberScreenState(), ) { override suspend fun reduceEvent( currentState: LoginPhoneNumberScreenState, event: LoginPhoneNumberScreenEvent, emitEffect: suspend (LoginPhoneNumberScreenEffect) -> Unit, ): LoginPhoneNumberScreenState = when (event) { is LoginPhoneNumberScreenEvent.AttemptToSignInWithPhoneNumberEvent -> { viewModelScope.launch { val countryDialCode = state.value.selectedCountry.dialCode val countryCode = state.value.selectedCountry.code val phoneNumberWithCountryCode = (countryDialCode + event.phoneNumber) authRepository.signInPhone( phoneNumber = phoneNumberWithCountryCode, countryCode = countryCode, ).fold( { response -> emitEffect( LoginPhoneNumberScreenEffect.OnPhoneNumberSubmittedSuccessfully( phoneNumber = phoneNumberWithCountryCode, signUpId = null, signInId = response.id, ), ) }, { error -> emitEffect( LoginPhoneNumberScreenEffect.OTPCodeRequestError( phoneNumber = phoneNumberWithCountryCode, ), ) }, ) updateState { it.copy(loading = false) } } currentState.copy( loading = true, ) } is LoginPhoneNumberScreenEvent.AttemptToSignUpWithPhoneNumberEvent -> { viewModelScope.launch { val countryDialCode = state.value.selectedCountry.dialCode val countryCode = state.value.selectedCountry.code val phoneNumberWithCountryCode = countryDialCode + event.phoneNumber authRepository.signUpPhone( phoneNumber = phoneNumberWithCountryCode, countryCode = countryCode, ).fold( { response -> if (response.errors.contains(AuthSignInError.AccountAlreadyExists)) { emitEffect( LoginPhoneNumberScreenEffect.PhoneNumberAlreadyExists, ) } else { emitEffect( LoginPhoneNumberScreenEffect.OnPhoneNumberSubmittedSuccessfully( phoneNumber = phoneNumberWithCountryCode, signUpId = response.id, signInId = null, ), ) } }, { error -> if (error is AuthSignInError.AccountAlreadyExists) { emitEffect( LoginPhoneNumberScreenEffect.PhoneNumberAlreadyExists, ) } else { emitEffect( LoginPhoneNumberScreenEffect.OTPCodeRequestError( phoneNumber = phoneNumberWithCountryCode, ), ) } }, ) updateState { it.copy( loading = false, ) } } currentState.copy(loading = true) } is LoginPhoneNumberScreenEvent.OnPhoneNumberEnteredEvent -> { currentState.copy( phoneNumber = event.phoneNumber, ) } is LoginPhoneNumberScreenEvent.SetCountryEvent -> { currentState.copy( selectedCountry = event.country, ) } } init { val phoneUtil = PhoneNumberUtil.getInstance() val regions = phoneUtil.supportedRegions val userCountryCode = Locale.getDefault().country val countryCode = phoneUtil.getCountryCodeForRegion(userCountryCode) val flagEmoji = userCountryCode.xGetFlagEmojiFromRegionCode() val exampleNumber = phoneUtil.getExampleNumberForType( userCountryCode, PhoneNumberUtil.PhoneNumberType.MOBILE, ) val exampleNumberString = exampleNumber?.let { phoneUtil.format( exampleNumber.clearCountryCode(), PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL, ) } val userCountry = Country( name = Locale("", userCountryCode).displayCountry, code = userCountryCode, dialCode = "+$countryCode", flagEmoji = flagEmoji, examplePhoneNumber = exampleNumberString, ) sendEvent( LoginPhoneNumberScreenEvent.SetCountryEvent( country = userCountry, ), ) } } data class Country( val name: String, val code: String, val dialCode: String, val flagEmoji: String? = null, val examplePhoneNumber: String? = null, )