package com.tangem.feature.wallet.presentation.wallet.analytics.utils

import com.tangem.common.routing.AppRoute.WalletBackup
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.navigation.Router
import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.core.ui.components.bottomsheets.message.*
import com.tangem.core.ui.ds.message.TangemMessageEffect
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.models.wallet.UserWalletId
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.feature.wallet.child.wallet.model.WalletActivationBannerType
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotificationUM
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider
import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject

@ModelScoped
internal class WalletWarningsSingleEventSender @Inject constructor(
    private val screenLifecycleProvider: ScreenLifecycleProvider,
    private val uiMessageSender: UiMessageSender,
    private val getUserWalletUseCase: GetUserWalletUseCase,
    private val router: Router,
) {
    private val isActivationBottomSheetShown: ConcurrentHashMap<UserWalletId, Boolean> = ConcurrentHashMap()

    fun send(userWalletId: UserWalletId, displayedUiState: WalletState?, newWarnings: List<WalletNotification>) {
        if (screenLifecycleProvider.isBackgroundState.value) return
        if (newWarnings.isEmpty()) return
        if (displayedUiState == null || displayedUiState.pullToRefreshConfig.isRefreshing) return

        val events = newWarnings.filter { it !in displayedUiState.warnings }

        // We must show activation bs only for the first seen wallet when open the app (if need, see conditions below),
        // so we keep this wallet id and use for future checks, ignore other wallets during the app session.
        if (isActivationBottomSheetShown.isEmpty()) {
            isActivationBottomSheetShown[userWalletId] = false
        }

        events.forEach { event ->
            when (event) {
                is WalletNotification.FinishWalletActivation -> {
                    // We check that map contains the first seen wallet (will return null instead false/true otherwise)
                    // and for this wallet we haven't shown the activation bs yet (check that returns false, not true)
                    if (isActivationBottomSheetShown[userWalletId] == false) {
                        if (event.type == WalletActivationBannerType.Warning && event.isBackupExists.not()) {
                            showFinishActivationBottomSheet(userWalletId)
                        }
                        isActivationBottomSheetShown[userWalletId] = true
                    }
                }
                else -> Unit
            }
        }
    }

    fun send(userWalletId: UserWalletId, displayedWalletUM: WalletUM?, newNotifications: List<WalletNotificationUM>) {
        if (screenLifecycleProvider.isBackgroundState.value) return
        if (newNotifications.isEmpty()) return
        if (displayedWalletUM == null || displayedWalletUM.pullToRefreshConfig.isRefreshing) return

        val totalNotifications = displayedWalletUM.notifications + displayedWalletUM.notificationsCarousel
        val events = newNotifications.filter { it !in totalNotifications }

        // We must show activation bs only for the first seen wallet when open the app (if need, see conditions below),
        // so we keep this wallet id and use for future checks, ignore other wallets during the app session.
        if (isActivationBottomSheetShown.isEmpty()) {
            isActivationBottomSheetShown[userWalletId] = false
        }

        events.forEach { event ->
            when (event) {
                is WalletNotificationUM.FinishWalletActivation -> {
                    // We check that map contains the first seen wallet (will return null instead false/true otherwise)
                    // and for this wallet we haven't shown the activation bs yet (check that returns false, not true)
                    if (isActivationBottomSheetShown[userWalletId] == false) {
                        if (event.messageEffect == TangemMessageEffect.Warning && event.isBackupExists.not()) {
                            showFinishActivationBottomSheet(userWalletId)
                        }
                        isActivationBottomSheetShown[userWalletId] = true
                    }
                }
                else -> Unit
            }
        }
    }

    private fun showFinishActivationBottomSheet(userWalletId: UserWalletId) {
        val userWallet = getUserWalletUseCase(userWalletId).getOrNull() ?: return
        if (userWallet !is UserWallet.Hot) return

        val message = bottomSheetMessage {
            infoBlock {
                icon(R.drawable.img_knight_shield_32) {
                    type = MessageBottomSheetUM.Icon.Type.Warning
                    backgroundType = MessageBottomSheetUM.Icon.BackgroundType.SameAsTint
                }
                title = resourceReference(R.string.hw_activation_need_title)
                body = resourceReference(R.string.hw_activation_need_description)
            }
            secondaryButton {
                text = resourceReference(R.string.common_later)
                onClick {
                    closeBs()
                }
            }
            primaryButton {
                text = resourceReference(R.string.hw_activation_need_backup)
                onClick {
                    router.push(
                        WalletBackup(
                            userWalletId = userWalletId,
                            isColdWalletOptionShown = true,
                        ),
                    )
                    closeBs()
                }
            }
        }

        uiMessageSender.send(message)
    }
}