package com.tangem.feature.wallet.child.wallet.model.intents

import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.ui.DesignFeatureToggles
import com.tangem.domain.exchange.RampStateManager
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.models.wallet.isLocked
import com.tangem.domain.onramp.FetchHotCryptoUseCase
import com.tangem.domain.settings.NeverToShowWalletsScrollPreview
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
import com.tangem.domain.wallets.usecase.SelectWalletUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyUpdateUseCase
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
import com.tangem.feature.wallet.presentation.wallet.domain.OnrampStatusFactory
import com.tangem.feature.wallet.presentation.wallet.domain.WalletContentFetcher
import com.tangem.feature.wallet.presentation.wallet.domain.unwrap
import com.tangem.feature.wallet.presentation.wallet.loaders.WalletScreenContentLoader
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
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.state.transformers.SetRefreshStateTransformer
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.launch
import javax.inject.Inject

@Suppress("LongParameterList")
@ModelScoped
internal class WalletClickIntents @Inject constructor(
    private val walletCardClickIntentsImplementor: WalletCardClickIntentsImplementor,
    private val warningsClickIntentsImplementer: WalletWarningsClickIntentsImplementor,
    private val currencyActionsClickIntentsImplementor: WalletCurrencyActionsClickIntentsImplementor,
    private val contentClickIntentsImplementor: WalletContentClickIntentsImplementor,
    private val pushPermissionClickIntentsImplementor: WalletPushPermissionClickIntentsImplementor,
    private val stateController: WalletStateController,
    private val walletScreenContentLoader: WalletScreenContentLoader,
    private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
    private val selectWalletUseCase: SelectWalletUseCase,
    private val walletContentFetcher: WalletContentFetcher,
    private val neverToShowWalletsScrollPreview: NeverToShowWalletsScrollPreview,
    private val rampStateManager: RampStateManager,
    private val fetchHotCryptoUseCase: FetchHotCryptoUseCase,
    private val onrampStatusFactory: OnrampStatusFactory,
    private val tangemPayIntents: TangemPayClickIntentsImplementor,
    private val yieldSupplyApyUpdateUseCase: YieldSupplyApyUpdateUseCase,
    private val designFeatureToggles: DesignFeatureToggles,
    private val analyticsEventHandler: AnalyticsEventHandler,
) : BaseWalletClickIntents(),
    WalletCardClickIntents by walletCardClickIntentsImplementor,
    WalletWarningsClickIntents by warningsClickIntentsImplementer,
    WalletCurrencyActionsClickIntents by currencyActionsClickIntentsImplementor,
    WalletContentClickIntents by contentClickIntentsImplementor,
    WalletPushPermissionClickIntents by pushPermissionClickIntentsImplementor,
    TangemPayIntents by tangemPayIntents {

    override fun initialize(router: InnerWalletRouter, coroutineScope: CoroutineScope) {
        super.initialize(router, coroutineScope)

        walletCardClickIntentsImplementor.initialize(router, coroutineScope)
        warningsClickIntentsImplementer.initialize(router, coroutineScope)
        currencyActionsClickIntentsImplementor.initialize(router, coroutineScope)
        contentClickIntentsImplementor.initialize(router, coroutineScope)
        pushPermissionClickIntentsImplementor.initialize(router, coroutineScope)
        tangemPayIntents.initialize(router, coroutineScope)
    }

    fun onWalletChange(index: Int, onlyState: Boolean) {
        if (onlyState) {
            stateController.update { it.copy(selectedWalletIndex = index) }
            return
        }

        modelScope.launch {
            launch { neverToShowWalletsScrollPreview() }

            val maybeUserWallet = selectWalletUseCase(
                userWalletId = stateController.value.wallets[index].walletCardState.id,
            )

            stateController.update { it.copy(selectedWalletIndex = index) }

            maybeUserWallet.onRight { userWallet ->
                if (!userWallet.isLocked) {
                    launch { walletContentFetcher(userWalletId = userWallet.walletId) }
                }

                walletScreenContentLoader.load(userWallet = userWallet, coroutineScope = modelScope)
            }
        }
    }

    fun onRefreshSwipe(showRefreshState: Boolean) {
        if (designFeatureToggles.isRedesignEnabled) {
            when (stateController.getSelectedWalletUM()) {
                is WalletUM.Content -> refreshMultiCurrencyContent(showRefreshState)
                is WalletUM.Locked -> Unit
            }
        } else {
            when (stateController.getSelectedWallet()) {
                is WalletState.MultiCurrency.Content -> {
                    refreshMultiCurrencyContent(showRefreshState)
                }
                is WalletState.SingleCurrency.Content,
                -> {
                    refreshSingleCurrencyContent(showRefreshState)
                }
                is WalletState.MultiCurrency.Locked,
                is WalletState.SingleCurrency.Locked,
                -> Unit
            }
        }
    }

    fun onReloadClick() {
        refreshSingleCurrencyContent(showRefreshState = true)
    }

    fun onAddFundsClick(userWalletId: UserWalletId) {
        analyticsEventHandler.send(MainScreenAnalyticsEvent.ButtonAddFunds())
        router.openAddFunds(userWalletId)
    }

    fun onTransferClick(userWalletId: UserWalletId) {
        analyticsEventHandler.send(MainScreenAnalyticsEvent.ButtonTransfer())
        router.openTransfer(userWalletId)
    }

    fun onAddFundsPromoClick(userWalletId: UserWalletId) {
        analyticsEventHandler.send(WalletScreenAnalyticsEvent.MainScreen.ButtonAddFundsPromo())
        router.openAddFunds(userWalletId)
    }

    private fun refreshMultiCurrencyContent(showRefreshState: Boolean) {
        val userWallet = getSelectedWalletSyncUseCase.unwrap() ?: return

        stateController.update(
            SetRefreshStateTransformer(userWalletId = userWallet.walletId, isRefreshing = showRefreshState),
        )

        modelScope.launch {
            walletContentFetcher(userWalletId = userWallet.walletId, forceUpdate = true)

            buildList {
                async { rampStateManager.fetchSellServiceData() }.let(::add)
                async { fetchHotCryptoUseCase() }.let(::add)
                async { tangemPayIntents.onPullToRefresh() }.let(::add)
                async { yieldSupplyApyUpdateUseCase() }.let(::add)
            }
                .awaitAll()

            stateController.update(
                SetRefreshStateTransformer(userWalletId = userWallet.walletId, isRefreshing = false),
            )
        }
    }

    // FIXME: refreshSingleCurrencyContent mustn't update the TxHistory and Buttons. It only must fetch primary
    //  currency. Now it not works because GetPrimaryCurrency's subscriber uses .distinctUntilChanged()
    private fun refreshSingleCurrencyContent(showRefreshState: Boolean) {
        val userWallet = getSelectedWalletSyncUseCase.unwrap() ?: return

        stateController.update(
            SetRefreshStateTransformer(userWalletId = userWallet.walletId, isRefreshing = showRefreshState),
        )

        modelScope.launch {
            walletContentFetcher(userWalletId = userWallet.walletId, forceUpdate = true)

            onrampStatusFactory.updateOnrmapTransactionStatuses(userWallet)
            walletScreenContentLoader.load(
                userWallet = userWallet,
                isRefresh = true,
                coroutineScope = modelScope,
            )

            stateController.update(
                SetRefreshStateTransformer(userWalletId = userWallet.walletId, isRefreshing = false),
            )
        }
    }
}