I have the following ViewModel that manages the UI states for the following screens in Android(Compose): TipSelectionScreen, CustomTipScreen, TipPaymentScreen.
Can we split this logic by different delegates(classes) for each screen to simplify the ViewModel and also follow the single responsibility principle.

@HiltViewModel
internal class TippingViewModel @Inject constructor(
    savedStateHandle: SavedStateHandle,
    private val tipRepository: TipRepositoryApi,
    private val paymentInteractor: PaymentInteractor,
) : ViewModel() {

    private val tippingArgs = TippingArgs(savedStateHandle)
    private var tipConfiguration = TipConfiguration.EMPTY
    private var selectedTip: Tip? by Delegates.observable(null) { _, _, newValue ->
        _tipSelectionUiState.update { state ->
            state.copy(
                customTip = if (newValue is Tip.CustomTip) newValue else Tip.CustomTip(null),
                selectedTip = newValue
            )
        }
    }

    private val _sheetUiState: MutableStateFlow<TipSheetUiState> =
        MutableStateFlow(TipSheetUiState.EMPTY)
    val sheetUiState: StateFlow<TipSheetUiState> get() = _sheetUiState

    private val _tipSelectionUiState: MutableStateFlow<TipSelectionUiState> =
        MutableStateFlow(TipSelectionUiState.EMPTY)
    val tipSelectionUiState: StateFlow<TipSelectionUiState>
        get() = _tipSelectionUiState

    private val _customTipUiState: MutableStateFlow<CustomTipUiState> =
        MutableStateFlow(CustomTipUiState.EMPTY)
    val customTipUiState: StateFlow<CustomTipUiState> get() = _customTipUiState

    private val _tipPaymentUiState: MutableStateFlow<TipPaymentUiState> =
        MutableStateFlow(TipPaymentUiState.EMPTY_DETAILS)
    val tipPaymentUiState: StateFlow<TipPaymentUiState> get() = _tipPaymentUiState

    private val _tipPaymentMethod: StateFlow<PaymentInteractor.PaymentMethodModel?> =
        paymentInteractor.providePaymentMethod()
            .asFlow()
            .onEach { paymentMethod ->
                _tipPaymentUiState.update { state ->
                    if (state is TipPaymentUiState.Details) {
                        state.copy(paymentMethod = paymentMethod)
                    } else {
                        state
                    }
                }
            }
            .stateIn(
                scope = viewModelScope,
                started = SharingStarted.Eagerly,
                initialValue = null
            )

    fun onInit() {
        viewModelScope.launch {
            tipConfiguration = tipRepository.getTipConfiguration(tippingArgs.orderId)
            _tipSelectionUiState.update { state ->
                state.copy(
                    predefinedTips = tipConfiguration.predefinedAmounts
                        .map { Tip.PredefinedTip(it) },
                    currency = tipConfiguration.currency
                )
            }
            _sheetUiState.update { state ->
                state.copy(page = TipSheetPage.TIP_OPTIONS, showHeader = false)
            }
        }
    }

    fun onTipSelected(tip: Tip) {
        if (tip is Tip.CustomTip) {
            _customTipUiState.update {
                CustomTipUiState(
                    customTip = tip.amount?.toString() ?: "",
                    currency = tipConfiguration.currency,
                    customTipCaption = if (tip.amount == null || tip.amount < tipConfiguration.excessiveTipAmount) {
                        CustomTipCaption.MinTip(tipConfiguration.minTipAmount)
                    } else {
                        CustomTipCaption.ExcessiveTip(tipConfiguration.excessiveTipPercentage)
                    },
                    isEditMode = tip.amount != null,
                    isButtonEnabled = tip.amount != null && tip.amount >= tipConfiguration.minTipAmount
                )
            }
            _sheetUiState.update { state ->
                state.copy(page = TipSheetPage.CUSTOM_TIP, showHeader = true)
            }
        } else {
            selectedTip = tip
        }
    }

    fun onFinishTipSelection() {
        if (selectedTip == null || selectedTip?.amount == 0.0) {
            _sheetUiState.update { state ->
                state.copy(closeSheet = true)
            }
        } else {
            _tipPaymentUiState.update {
                TipPaymentUiState.Details(
                    value = "${selectedTip?.amount} ${tipConfiguration.currency}",
                    paymentMethod = _tipPaymentMethod.value,
                    isPaymentProcessing = false
                )
            }
            _sheetUiState.update { state ->
                state.copy(page = TipSheetPage.TIP_PAYMENT, showHeader = true)
            }
        }
    }

    fun onChangeCustomTipAmount(amount: String) {
        val sanitizedAmount = if (amount.isNotBlank()) amount.sanitizeNumberString() else ""
        val value = sanitizedAmount.toDoubleOrDefault(0.0)
        _customTipUiState.update { state ->
            state.copy(
                customTip = sanitizedAmount,
                customTipCaption = if (value < tipConfiguration.excessiveTipAmount) {
                    CustomTipCaption.MinTip(tipConfiguration.minTipAmount)
                } else {
                    CustomTipCaption.ExcessiveTip(tipConfiguration.excessiveTipPercentage)
                },
                isButtonEnabled = value >= tipConfiguration.minTipAmount &&
                        !sanitizedAmount.endsWith('.')
            )
        }
    }

    fun onApplyCustomTip() {
        val customTip = _customTipUiState.value.customTip.toDoubleOrNull() ?: 0.0
        selectedTip = when {
            tipConfiguration.predefinedAmounts.contains(customTip) -> Tip.PredefinedTip(
                customTip
            )
            else -> Tip.CustomTip(customTip)
        }
        _sheetUiState.update { state ->
            state.copy(page = TipSheetPage.TIP_OPTIONS, showHeader = false)
        }
    }

    fun onPaymentOptions(fm: FragmentManager?) {
        fm?.let { paymentInteractor.selectPaymentMethod(fm, tippingArgs.orderId) }
    }

    fun onSubmitTip() {
        viewModelScope.launch {
            try {
                _tipPaymentUiState.update {
                    TipPaymentUiState.Details(
                        value = "${selectedTip?.amount} ${tipConfiguration.currency}",
                        paymentMethod = _tipPaymentMethod.value,
                        isPaymentProcessing = true
                    )
                }
                // TODO : Submit tip. The implementation is just a stub to have different conditions
                delay(2000)
                if (Random.nextDouble() > 0.5) throw Exception("Server request failed")
                _sheetUiState.update { state ->
                    state.copy(showHeader = false)
                }
                _tipPaymentUiState.update { TipPaymentUiState.Success }
            } catch (e: Exception) {
                _sheetUiState.update { state ->
                    state.copy(showHeader = false)
                }
                _tipPaymentUiState.update { TipPaymentUiState.Error }
            }
        }
    }

    fun onRetryPayment() {
        _sheetUiState.update { state ->
            state.copy(showHeader = true)
        }
        _tipPaymentUiState.update {
            TipPaymentUiState.Details(
                value = "${selectedTip?.amount} ${tipConfiguration.currency}",
                paymentMethod = _tipPaymentMethod.value,
                isPaymentProcessing = false
            )
        }
    }

    fun back() {
        _sheetUiState.update { state ->
            when (state.page) {
                TipSheetPage.NONE, TipSheetPage.TIP_OPTIONS -> state
                TipSheetPage.CUSTOM_TIP, TipSheetPage.TIP_PAYMENT -> state.copy(
                    page = TipSheetPage.TIP_OPTIONS,
                    showHeader = false
                )
            }
        }
    }
}