package com.tangem.feature.walletsettings.utils

import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.domain.account.usecase.ApplyAccountListSortingUseCase
import com.tangem.utils.coroutines.AppCoroutineScope
import com.tangem.domain.models.account.AccountId
import com.tangem.domain.wallets.analytics.WalletSettingsAnalyticEvents
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.*
import com.tangem.utils.logging.TangemLogger
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.time.Duration.Companion.seconds

/**
 * Saves the sorting order of accounts with a debounce to prevent frequent updates.
 *
 * @property applyAccountListSortingUseCase Use case to apply the account list sorting.
 * @param dispatchers Coroutine dispatcher provider for managing threading.
 *
[REDACTED_AUTHOR]
 */
@Singleton
@OptIn(FlowPreview::class)
internal class AccountListSortingSaver @Inject constructor(
    private val applyAccountListSortingUseCase: ApplyAccountListSortingUseCase,
    private val analyticsEventHandler: AnalyticsEventHandler,
    private val coroutineScope: AppCoroutineScope,
) {

    /** Flow to hold the account IDs for sorting, with an initial null value. */
    val accountsOrderFlow: StateFlow<List<AccountId>?>
        private field = MutableStateFlow<List<AccountId>?>(value = null)

    init {
        accountsOrderFlow
            .filterNotNull()
            .debounce { 3.seconds }
            .onEach { accountIds ->
                applyAccountListSortingUseCase.invoke(accountIds).onLeft {
                    TangemLogger.e("Error while saving account list sorting: $it")
                }
                    .onRight {
                        analyticsEventHandler.send(WalletSettingsAnalyticEvents.LongtapAccountsOrder())
                    }
            }
            .launchIn(coroutineScope)
    }

    /**
     * Saves the provided list of account IDs to apply the sorting order.
     *
     * @param accountIds List of AccountId representing the desired order.
     */
    fun save(accountIds: List<AccountId>) {
        accountsOrderFlow.value = accountIds
    }
}