package com.tangem.features.yield.supply.impl.entry.model

import arrow.core.getOrElse
import com.tangem.common.routing.AppRoute
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.domain.account.status.supplier.SingleAccountStatusListSupplier
import com.tangem.domain.account.status.utils.CryptoCurrencyStatusOperations.getCryptoCurrencyStatus
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.details.NavigationAction
import com.tangem.domain.yield.supply.promo.usecase.IsYieldBoostPromoEnabledForTokenUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyEnterStatusUseCase
import com.tangem.features.yield.supply.api.YieldSupplyEntryComponent
import com.tangem.features.yield.supply.api.entry.YieldSupplyEntryRoute
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import com.tangem.utils.logging.TangemLogger
import javax.inject.Inject

@ModelScoped
@Suppress("LongParameterList")
internal class YieldSupplyEntryModel @Inject constructor(
    paramsContainer: ParamsContainer,
    override val dispatchers: CoroutineDispatcherProvider,
    private val router: Router,
    private val yieldSupplyEnterStatusUseCase: YieldSupplyEnterStatusUseCase,
    private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier,
    private val isYieldBoostPromoEnabledForTokenUseCase: IsYieldBoostPromoEnabledForTokenUseCase,
) : Model() {

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

    val initialRoute: YieldSupplyEntryRoute = YieldSupplyEntryRoute.Empty

    init {
        navigateToInitialRoute()
    }

    private fun navigateToInitialRoute() {
        val userWalletId = params.userWalletId
        val cryptoCurrency = params.cryptoCurrency
        modelScope.launch(dispatchers.default) {
            singleAccountStatusListSupplier.getSyncOrNull(userWalletId)
                .getCryptoCurrencyStatus(currency = cryptoCurrency)
                .onNone {
                    TangemLogger.e("Failed to get CryptoCurrencyStatus: ${cryptoCurrency.id}")
                    withContext(dispatchers.mainImmediate) {
                        router.pop()
                    }
                }
                .onSome { cryptoCurrencyStatus ->
                    withContext(dispatchers.mainImmediate) {
                        val route = getInitialRoute(cryptoCurrencyStatus)
                        if (route != null) {
                            router.replaceCurrent(route)
                        }
                    }
                }
        }
    }

    private suspend fun getInitialRoute(cryptoCurrencyStatus: CryptoCurrencyStatus): YieldSupplyEntryRoute? {
        val userWalletId = params.userWalletId
        val cryptoCurrency = params.cryptoCurrency
        val token = cryptoCurrency as? CryptoCurrency.Token
        if (token == null) {
            router.pop()
            return null
        }

        val tokenEnterStatus = yieldSupplyEnterStatusUseCase(
            userWalletId = userWalletId,
            cryptoCurrencyStatus = cryptoCurrencyStatus,
        ).getOrNull()
        val isActiveYield = cryptoCurrencyStatus.value.yieldSupplyStatus?.isActive == true

        if (tokenEnterStatus != null) {
            router.replaceCurrent(
                AppRoute.CurrencyDetails(
                    userWalletId = userWalletId,
                    currency = token,
                    navigationAction = NavigationAction.YieldSupply(
                        isActive = isActiveYield,
                    ),
                ),
            )
            return null
        }

        return if (isActiveYield) {
            YieldSupplyEntryRoute.Active(cryptoCurrency = token)
        } else {
            val isPromoEnabled = isYieldBoostPromoEnabledForTokenUseCase(userWalletId, token).getOrElse { false }
            YieldSupplyEntryRoute.Promo(
                cryptoCurrency = token,
                apy = params.apy,
                isPromoEnabled = isPromoEnabled,
            )
        }
    }
}