package com.suno.android.ui.screens.onboarding.login import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import androidx.navigation.toRoute import com.suno.android.common_core_utils.global_errors.DialogSpec import com.suno.android.common_core_utils.global_errors.TopLevelErrorManager import com.suno.android.common_core_utils.model.UiString import com.suno.android.common_mvi.MviProcessorFactory import com.suno.android.common_mvi.MviViewModel import com.suno.android.common_res.R import com.suno.android.framework.auth.api.AuthManager import com.suno.android.framework.auth.api.AuthStrategies import com.suno.android.gating.Feature import com.suno.android.gating.FeatureManager import com.suno.android.ui.screens.navigation.NavDestination import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.launch import javax.inject.Inject import com.suno.android.common_res.R as CommonResR import com.suno.android.common_ui.R as CommonUiR @HiltViewModel class LoginScreenVM @Inject constructor( processorFactory: MviProcessorFactory, savedStateHandle: SavedStateHandle, private val authManager: AuthManager, private val featureManager: FeatureManager, private val errorManager: TopLevelErrorManager, ) : MviViewModel( processorFactory = processorFactory, initialState = LoginScreenState( isSignUp = savedStateHandle.toRoute().isSignUp, authenticationOptions = buildList { add( AuthenticationItem( textRes = CommonResR.string.google, imageRes = CommonUiR.drawable.google, loginMethodEvent = LoginScreenEvent.OnOauthClicked(AuthStrategies.OAUTH_GOOGLE), ), ) add( AuthenticationItem( textRes = CommonResR.string.microsoft, imageRes = CommonUiR.drawable.microsoft, loginMethodEvent = LoginScreenEvent.OnOauthClicked(AuthStrategies.OAUTH_MICROSOFT), ), ) add( AuthenticationItem( textRes = CommonResR.string.discord, imageRes = CommonUiR.drawable.discord, loginMethodEvent = LoginScreenEvent.OnOauthClicked(AuthStrategies.OAUTH_DISCORD), ), ) if (featureManager.hasFeature(Feature.AuthFacebook)) { add( AuthenticationItem( textRes = CommonResR.string.facebook, imageRes = CommonUiR.drawable.facebook, loginMethodEvent = LoginScreenEvent.OnOauthClicked(AuthStrategies.OAUTH_FACEBOOK), ), ) } add( AuthenticationItem( textRes = CommonResR.string.sign_up_phone, imageRes = CommonUiR.drawable.phone_login, loginMethodEvent = LoginScreenEvent.OnPhoneAuthClicked, ), ) }, ), ) { override suspend fun reduceEvent( currentState: LoginScreenState, event: LoginScreenEvent, emitEffect: suspend (LoginScreenEffect) -> Unit, ): LoginScreenState = when (event) { is LoginScreenEvent.OnOauthClicked -> { viewModelScope.launch { authManager.onOauthClicked(event.clerkMethod).onLeft { e -> logger.e(e.toThrowable()) errorManager.broadcastTopLevelDialogError( DialogSpec( title = UiString.Resource(R.string.sign_up_error_title), body = UiString.Resource(R.string.sign_up_error_body), buttons = persistentListOf( DialogSpec.Button( label = UiString.Resource(R.string.ok), ), ), ), ) emitAnalyticEffect(LoginScreenAnalyticEffect.AuthError) }.onRight { externalRedirectUrl -> emitEffect( LoginScreenEffect.OnOauthClicked( isSignUp = currentState.isSignUp, redirectUrl = externalRedirectUrl, ), ) } updateState { it.copy(authLoading = false) } } currentState.copy(authLoading = true) } LoginScreenEvent.OnPhoneAuthClicked -> { emitEffect( LoginScreenEffect.OnPhoneNumberClicked(currentState.isSignUp), ) currentState } } data class AuthenticationItem( @StringRes val textRes: Int, @DrawableRes val imageRes: Int, val loginMethodEvent: LoginScreenEvent, ) }