package com.tangem.features.hotwallet.addexistingwallet.im.port.model

import com.tangem.utils.logging.TangemLogger
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.event.OnboardingAnalyticsEvent
import com.tangem.core.decompose.di.GlobalUiMessageSender
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.ui.UiMessageSender
import com.tangem.core.ui.R
import com.tangem.core.ui.components.bottomsheets.message.*
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.message.SnackbarMessage
import com.tangem.core.ui.message.bottomSheetMessage
import com.tangem.crypto.bip39.Mnemonic
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
import com.tangem.domain.common.wallets.error.SaveWalletError
import com.tangem.domain.assetsdiscovery.usecase.StartAssetsDiscoveryUseCase
import com.tangem.domain.wallets.builder.HotUserWalletBuilder
import com.tangem.domain.wallets.models.WalletSyncResult
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
import com.tangem.domain.wallets.usecase.SyncWalletWithRemoteUseCase
import com.tangem.features.hotwallet.HotWalletFeatureToggles
import com.tangem.features.hotwallet.MnemonicRepository
import com.tangem.features.hotwallet.addexistingwallet.im.port.AddExistingWalletImportComponent
import com.tangem.features.hotwallet.addexistingwallet.im.port.entity.AddExistingWalletImportUM
import com.tangem.hot.sdk.TangemHotSdk
import com.tangem.hot.sdk.model.HotAuth
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import javax.inject.Inject

@Suppress("LongParameterList")
@ModelScoped
internal class AddExistingWalletImportModel @Inject constructor(
    paramsContainer: ParamsContainer,
    override val dispatchers: CoroutineDispatcherProvider,
    private val mnemonicRepository: MnemonicRepository,
    private val tangemHotSdk: TangemHotSdk,
    private val hotUserWalletBuilderFactory: HotUserWalletBuilder.Factory,
    private val saveUserWalletUseCase: SaveWalletUseCase,
    private val syncWalletWithRemoteUseCase: SyncWalletWithRemoteUseCase,
    private val startAssetsDiscoveryUseCase: StartAssetsDiscoveryUseCase,
    private val hotWalletFeatureToggles: HotWalletFeatureToggles,
    @GlobalUiMessageSender private val uiMessageSender: UiMessageSender,
    private val analyticsEventHandler: AnalyticsEventHandler,
    private val appsFlyerStore: AppsFlyerStore,
) : Model() {

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

    private val importSeedPhraseUiStateBuilder: ImportSeedPhraseUiStateBuilder

    private val passphraseInfoAlertBS
        get() = bottomSheetMessage {
            infoBlock {
                icon(R.drawable.ic_passcode_lock_56) {
                    type = MessageBottomSheetUM.Icon.Type.Accent
                    backgroundType = MessageBottomSheetUM.Icon.BackgroundType.SameAsTint
                }
                title = resourceReference(R.string.common_passphrase)
                body = resourceReference(R.string.onboarding_bottom_sheet_passphrase_description)
            }
            secondaryButton {
                text = resourceReference(R.string.common_got_it)
                onClick { closeBs() }
            }
        }

    init {
        analyticsEventHandler.send(OnboardingAnalyticsEvent.SeedPhrase.ImportSeedPhraseScreenOpened())
        importSeedPhraseUiStateBuilder = ImportSeedPhraseUiStateBuilder(
            modelScope = modelScope,
            mnemonicRepository = mnemonicRepository,
            updateUiState = { block -> uiState.update { block(it) } },
            readyToImport = { ready -> uiState.update { it.copy(readyToImport = ready) } },
            importWallet = { mnemonic: Mnemonic, passphrase: String? ->
                importWallet(
                    mnemonic = mnemonic,
                    passphrase = passphrase,
                )
            },
            onPassphraseInfoClick = ::onPassphraseInfoClick,
            onImportClick = { analyticsEventHandler.send(OnboardingAnalyticsEvent.SeedPhrase.ButtonImport()) },
        )
    }

    internal val uiState: StateFlow<AddExistingWalletImportUM>
        field = MutableStateFlow(importSeedPhraseUiStateBuilder.getState())

    @Suppress("UnusedPrivateMember")
    private fun importWallet(mnemonic: Mnemonic, passphrase: String?) {
        modelScope.launch {
            setImportProgress(true)

            runCatching {
                val hotWalletId = tangemHotSdk.importWallet(mnemonic, passphrase?.toCharArray(), HotAuth.NoAuth)
                val hotUserWalletBuilder = hotUserWalletBuilderFactory.create(hotWalletId)
                val userWallet = hotUserWalletBuilder.build()
                saveUserWalletUseCase.invoke(userWallet.copy(backedUp = true))
                    .onLeft { error ->
                        setImportProgress(false)
                        when (error) {
                            is SaveWalletError.DataError -> TangemLogger.e("Unable to save user wallet: $error")
                            is SaveWalletError.WalletAlreadySaved -> {
                                uiMessageSender.send(
                                    SnackbarMessage(resourceReference(R.string.hw_import_seed_phrase_already_imported)),
                                )
                            }
                        }
                    }
                    .onRight {
                        setImportProgress(false)

                        launch(dispatchers.main + NonCancellable) {
                            val syncResult = syncWalletWithRemoteUseCase(userWallet.walletId)
                            if (hotWalletFeatureToggles.isAssetsDiscoveryEnabled &&
                                syncResult == WalletSyncResult.Created
                            ) {
                                startAssetsDiscoveryUseCase(userWallet.walletId)
                            }
                        }

                        analyticsEventHandler.send(
                            event = OnboardingAnalyticsEvent.Onboarding.Finished(
                                source = AnalyticsParam.ScreensSources.ImportWallet,
                            ),
                        )
                        analyticsEventHandler.send(
                            event = OnboardingAnalyticsEvent.CreateWallet.WalletCreatedSuccessfully(
                                source = AnalyticsParam.ScreensSources.ImportWallet,
                                creationType = AnalyticsParam.WalletCreationType.SeedImport,
                                seedPhraseLength = mnemonic.mnemonicComponents.size,
                                passPhraseState = if (passphrase.isNullOrBlank()) {
                                    AnalyticsParam.EmptyFull.Empty
                                } else {
                                    AnalyticsParam.EmptyFull.Full
                                },
                                referralId = appsFlyerStore.get()?.refcode,
                            ),
                        )
                        params.callbacks.onWalletImported(userWallet.walletId)
                    }
            }.onFailure { throwable ->
                TangemLogger.e("Error", throwable)
                setImportProgress(false)
            }
        }
    }

    private fun setImportProgress(progress: Boolean) {
        uiState.update {
            it.copy(importWalletProgress = progress)
        }
    }

    private fun onPassphraseInfoClick() {
        uiMessageSender.send(passphraseInfoAlertBS)
    }
}