package com.suno.android.ui.screens.onboarding.username_handle import androidx.lifecycle.viewModelScope import arrow.core.getOrElse import arrow.retrofit.adapter.either.networkhandling.HttpError 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_data.user.UserSessionRepository import com.suno.android.common_mvi.MviProcessorFactory import com.suno.android.common_mvi.MviViewModel import com.suno.android.common_networking.extensions.toThrowable import com.suno.android.common_networking.remote.entities.UpdateArtistProfileSpec import com.suno.android.common_networking.remote.profiles.ProfilesService import com.suno.android.common_res.R import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class OnboardingUsernameHandleScreenVM @Inject constructor( processorFactory: MviProcessorFactory, private val userSessionRepository: UserSessionRepository, private val profilesService: ProfilesService, private val topLevelErrorManager: TopLevelErrorManager, ) : MviViewModel< OnboardingUsernameHandleScreenEvent, OnboardingUsernameHandleScreenState, OnboardingUsernameHandleScreenEffect, >( processorFactory = processorFactory, initialState = OnboardingUsernameHandleScreenState(), ) { init { userSessionRepository.sessionConfigurationStateFlow() .onEach { sessionConfiguration -> val user = sessionConfiguration.user updateState { it.copy( user = user, userHandle = user?.handle.orEmpty(), ) } }.catch { exception -> logger.e(exception) }.launchIn(viewModelScope) } override suspend fun reduceEvent( currentState: OnboardingUsernameHandleScreenState, event: OnboardingUsernameHandleScreenEvent, emitEffect: suspend (OnboardingUsernameHandleScreenEffect) -> Unit, ): OnboardingUsernameHandleScreenState = when (event) { is OnboardingUsernameHandleScreenEvent.OnHandleInput -> { currentState.copy(userHandle = event.handle) } is OnboardingUsernameHandleScreenEvent.OnSaveClicked -> { val user = currentState.user viewModelScope.launch { val spec = UpdateArtistProfileSpec( displayName = user?.displayName.orEmpty(), handle = event.handle, profileDescription = user?.profileDescription.orEmpty(), avatarImageUrl = user?.avatarImageUrl.orEmpty(), ) profilesService.updateArtistProfile(spec).getOrElse { error -> logger.e(error.toThrowable()) val statusCode = (error as? HttpError)?.code if (statusCode == 400) { topLevelErrorManager.broadcastTopLevelDialogError( DialogSpec( title = UiString.Resource(R.string.sorry), body = UiString.Resource(R.string.userhandle_taken), ), ) } updateState { it.copy(loading = false) } return@launch } userSessionRepository.refreshUserSessionConfiguration() emitEffect( OnboardingUsernameHandleScreenEffect.OnUsernameHandleSuccessfullySaved, ) updateState { it.copy(loading = false) } } currentState.copy(loading = true) } OnboardingUsernameHandleScreenEvent.OnSkipClicked -> { emitEffect( OnboardingUsernameHandleScreenEffect.OnSkipClicked, ) currentState } is OnboardingUsernameHandleScreenEvent.OnUserUpdated -> { currentState.copy( user = event.user, userHandle = event.user?.handle.orEmpty(), ) } } }