package com.tangem.features.hotwallet.wallethardwarebackup.model

import arrow.core.getOrElse
import com.tangem.common.routing.AppRoute
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic
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.navigation.url.UrlOpener
import com.tangem.core.ui.components.bottomsheets.message.MessageBottomSheetUM
import com.tangem.core.ui.components.bottomsheets.message.icon
import com.tangem.core.ui.components.bottomsheets.message.infoBlock
import com.tangem.core.ui.components.bottomsheets.message.onClick
import com.tangem.core.ui.components.bottomsheets.message.primaryButton
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.bottomSheetMessage
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.wallets.analytics.WalletSettingsAnalyticEvents
import com.tangem.domain.wallets.usecase.GenerateBuyTangemCardLinkUseCase
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.domain.wallets.usecase.UnlockHotWalletContextualUseCase
import com.tangem.features.hotwallet.WalletHardwareBackupComponent
import com.tangem.features.hotwallet.impl.R
import com.tangem.features.hotwallet.wallethardwarebackup.entity.WalletHardwareBackupUM
import com.tangem.hot.sdk.model.HotWalletId
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import com.tangem.utils.logging.TangemLogger
import javax.inject.Inject

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

    private val params = paramsContainer.require<WalletHardwareBackupComponent.Params>()

    private val makeBackupAtFirstAlertBS
        get() = run {
            analyticsEventHandler.send(
                WalletSettingsAnalyticEvents.NoticeBackupFirst(
                    source = AnalyticsParam.ScreensSources.HardwareWallet.value,
                    action = WalletSettingsAnalyticEvents.NoticeBackupFirst.Action.Upgrade,
                ),
            )
            bottomSheetMessage {
                infoBlock {
                    icon(R.drawable.ic_passcode_lock_32) {
                        type = MessageBottomSheetUM.Icon.Type.Accent
                        backgroundType = MessageBottomSheetUM.Icon.BackgroundType.SameAsTint
                    }
                    title = resourceReference(R.string.hw_backup_need_finish_first)
                    body = resourceReference(R.string.hw_backup_to_upgrade_description)
                }
                primaryButton {
                    text = resourceReference(R.string.hw_backup_need_action)
                    onClick {
                        router.push(
                            AppRoute.CreateWalletBackup(
                                userWalletId = params.userWalletId,
                                isUpgradeFlow = true,
                                analyticsSource = AnalyticsParam.ScreensSources.HardwareWallet.value,
                                analyticsAction = WalletSettingsAnalyticEvents.RecoveryPhraseScreenAction.Upgrade.value,
                            ),
                        )
                        closeBs()
                    }
                }
            }
        }

    internal val uiState: StateFlow<WalletHardwareBackupUM>
        field = MutableStateFlow(
            WalletHardwareBackupUM(
                onBackClick = { router.pop() },
                blocks = persistentListOf(
                    WalletHardwareBackupUM.Block(
                        title = resourceReference(R.string.hw_backup_hardware_create_title),
                        titleLabel = LabelUM(
                            text = resourceReference(R.string.common_recommended),
                            style = LabelStyle.ACCENT,
                        ),
                        description = resourceReference(R.string.hw_backup_hardware_create_description),
                        onClick = ::onCreateNewWalletClick,
                    ),
                    WalletHardwareBackupUM.Block(
                        title = resourceReference(R.string.hw_backup_hardware_upgrade_title),
                        titleLabel = null,
                        description = resourceReference(R.string.hw_backup_hardware_upgrade_description),
                        onClick = ::onUpgradeCurrentWalletClick,
                    ),
                ),
                onBuyClick = ::onBuyClick,
            ),
        )

    init {
        trackingContextProxy.addHotWalletContext()
        analyticsEventHandler.send(WalletSettingsAnalyticEvents.HardwareBackupScreenOpened())
    }

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

    private fun onCreateNewWalletClick() {
        analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonCreateNewWallet())
        router.push(AppRoute.CreateHardwareWallet(source = AnalyticsParam.ScreensSources.CreateWallet))
    }

    private fun onUpgradeCurrentWalletClick() {
        val userWallet = getUserWalletUseCase.invoke(params.userWalletId)
            .getOrElse { error("Cannot find user wallet with id: ${params.userWalletId.stringValue}") }
        if (userWallet is UserWallet.Hot) {
            analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonUpgradeCurrent())
            if (!userWallet.backedUp) {
                messageSender.send(makeBackupAtFirstAlertBS)
            } else {
                val hotWalletId = userWallet.hotWalletId
                when (hotWalletId.authType) {
                    HotWalletId.AuthType.NoPassword -> {
                        router.push(AppRoute.UpgradeWallet(userWalletId = params.userWalletId))
                    }
                    HotWalletId.AuthType.Password,
                    HotWalletId.AuthType.Biometry,
                    -> modelScope.launch {
                        unlockHotWalletContextualUseCase.invoke(hotWalletId)
                            .onLeft {
                                TangemLogger.e("Unable to unlock wallet with id ${params.userWalletId}", it)
                            }
                            .onRight {
                                router.push(AppRoute.UpgradeWallet(userWalletId = params.userWalletId))
                            }
                    }
                }
            }
        }
    }

    private fun onBuyClick() {
        analyticsEventHandler.send(Basic.ButtonBuy(source = AnalyticsParam.ScreensSources.HardwareWallet))
        modelScope.launch {
            generateBuyTangemCardLinkUseCase
                .invoke(GenerateBuyTangemCardLinkUseCase.Source.Backup).let { urlOpener.openUrl(it) }
        }
    }
}