package com.tangem.features.hotwallet.walletbackup.model

import com.tangem.common.routing.AppRoute
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.utils.TrackingContextProxy
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.decompose.navigation.Router
import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.core.ui.R
import com.tangem.core.ui.components.label.entity.LabelStyle
import com.tangem.core.ui.components.label.entity.LabelUM
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.message.DialogMessage
import com.tangem.core.ui.message.EventMessageAction
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.wallets.analytics.WalletSettingsAnalyticEvents
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.domain.wallets.usecase.UnlockHotWalletContextualUseCase
import com.tangem.features.hotwallet.WalletBackupComponent
import com.tangem.features.hotwallet.walletbackup.entity.BackupStatus
import com.tangem.features.hotwallet.walletbackup.entity.WalletBackupUM
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.logging.TangemLogger
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject

@Suppress("LongParameterList")
@ModelScoped
internal class WalletBackupModel @Inject constructor(
    paramsContainer: ParamsContainer,
    override val dispatchers: CoroutineDispatcherProvider,
    private val getUserWalletUseCase: GetUserWalletUseCase,
    private val unlockHotWalletContextualUseCase: UnlockHotWalletContextualUseCase,
    private val router: Router,
    private val trackingContextProxy: TrackingContextProxy,
    private val analyticsEventHandler: AnalyticsEventHandler,
    private val uiMessageSender: UiMessageSender,
) : Model() {

    private val params: WalletBackupComponent.Params = paramsContainer.require()

    private val isScreenOpenedEventSent: AtomicBoolean = AtomicBoolean(false)

    val uiState: StateFlow<WalletBackupUM>
        field = MutableStateFlow(
            WalletBackupUM(
                onBackClick = { router.pop() },
                hardwareWalletOption = LabelUM(
                    text = resourceReference(R.string.common_recommended),
                    style = LabelStyle.ACCENT,
                ).takeIf { params.isColdWalletOptionShown },
                recoveryPhraseOption = LabelUM(
                    text = resourceReference(R.string.hw_backup_no_backup),
                    style = LabelStyle.WARNING,
                ),
                googleDriveOption = LabelUM(
                    text = resourceReference(R.string.common_coming_soon),
                    style = LabelStyle.REGULAR,
                ),
                googleDriveStatus = BackupStatus.ComingSoon,
                onRecoveryPhraseClick = ::onRecoveryPhraseClick,
                onGoogleDriveClick = ::onGoogleDriveBackupClick,
                onHardwareWalletClick = ::onHardwareWalletClick,
                isBackedUp = false,
            ),
        )

    init {
        trackingContextProxy.addHotWalletContext()
        getUserWalletUseCase.invokeFlow(params.userWalletId)
            .onEach { either ->
                either.fold(
                    ifLeft = {
                        TangemLogger.e("Error on getting user wallet: $it")
                    },
                    ifRight = { userWallet ->
                        if (!isScreenOpenedEventSent.get() && userWallet is UserWallet.Hot) {
                            analyticsEventHandler.send(
                                event = WalletSettingsAnalyticEvents.BackupScreenOpened(
                                    isBackedUp = userWallet.backedUp,
                                ),
                            )
                            isScreenOpenedEventSent.set(true)
                        }
                        updateBackupStatuses(userWallet)
                    },
                )
            }.launchIn(modelScope)
    }

    override fun onDestroy() {
        trackingContextProxy.removeContext()
        super.onDestroy()
    }

    private fun updateBackupStatuses(userWallet: UserWallet) {
        uiState.update { currentState ->
            if (userWallet is UserWallet.Hot) {
                currentState.updateBackupStatusesHotWallet(userWallet)
            } else {
                currentState
            }
        }
    }

    private fun WalletBackupUM.updateBackupStatusesHotWallet(userWallet: UserWallet.Hot): WalletBackupUM = copy(
        recoveryPhraseOption = if (userWallet.backedUp) {
            LabelUM(
                text = resourceReference(R.string.common_done),
                style = LabelStyle.ACCENT,
            )
        } else {
            LabelUM(
                text = resourceReference(R.string.hw_backup_no_backup),
                style = LabelStyle.WARNING,
            )
        },
        googleDriveOption = LabelUM(
            text = resourceReference(R.string.hw_backup_no_backup),
            style = LabelStyle.WARNING,
        ),
        isBackedUp = userWallet.backedUp,
        googleDriveStatus = BackupStatus.NoBackup,
    )

    private fun onRecoveryPhraseClick() {
        analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonRecoveryPhrase())
        if (uiState.value.isBackedUp) {
            getUserWalletUseCase.invoke(params.userWalletId)
                .fold(
                    ifLeft = {
                        TangemLogger.e("Error on getting user wallet: $it")
                    },
                    ifRight = { userWallet ->
                        when (userWallet) {
                            is UserWallet.Cold -> {
                                val userWalletId = userWallet.walletId
                                TangemLogger.e("Unexpected cold wallet when request seed phrase: $userWalletId")
                            }
                            is UserWallet.Hot -> showSeedPhrase(userWallet)
                        }
                    },
                )
        } else {
            router.push(
                AppRoute.WalletActivation(
                    userWalletId = params.userWalletId,
                    isBackupExists = false,
                ),
            )
        }
    }

    private fun onGoogleDriveBackupClick() {
        analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonGoogleDriveBackup())
        uiMessageSender.send(
            DialogMessage(
                title = resourceReference(id = R.string.hw_backup_google_drive_dialog_title),
                message = resourceReference(id = R.string.hw_backup_google_drive_dialog_message),
                firstAction = EventMessageAction(
                    title = resourceReference(id = R.string.common_ok),
                    onClick = {},
                ),
            ),
        )
    }

    private fun showSeedPhrase(hotWallet: UserWallet.Hot) {
        modelScope.launch {
            unlockHotWalletContextualUseCase.invoke(hotWallet.hotWalletId)
                .fold(
                    ifLeft = {
                        TangemLogger.e("Error while export seed phrase: $it")
                    },
                    ifRight = { seedPhrasePrivateInfo ->
                        router.push(AppRoute.ViewPhrase(params.userWalletId))
                    },
                )
        }
    }

    private fun onHardwareWalletClick() {
        analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonHardwareUpdate())
        router.push(AppRoute.WalletHardwareBackup(params.userWalletId))
    }
}