package com.adealink.weparty.account.login.phone.viewmodel

import androidx.lifecycle.LiveData
import com.adealink.frame.aab.util.getCompatString
import com.adealink.frame.base.IError
import com.adealink.frame.base.Rlt
import com.adealink.frame.log.Log
import com.adealink.frame.mvvm.livedata.ExtMutableLiveData
import com.adealink.frame.mvvm.livedata.OnceMutableLiveData
import com.adealink.frame.mvvm.viewmodel.BaseViewModel
import com.adealink.frame.network.data.Res
import com.adealink.weparty.App
import com.adealink.weparty.account.constant.TAG_PHONE_LOGIN
import com.adealink.weparty.account.login.datasource.remote.LoginHttpService
import com.adealink.weparty.account.login.phone.data.Page
import com.adealink.weparty.account.login.phone.data.SendPhoneVerifyReq
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import com.adealink.weparty.R as APP_R

data class SendVerifyCode(
    val rlt: Rlt<Any>,
    val lastSendVerifyCodeTs: Long,
)

class PhoneLoginViewModel : BaseViewModel() {

    companion object {
        const val SEND_DURATION = 60_000

        @JvmStatic
        var lastSendVerifyCodeTs = 0L
    }

    private val loginHttpService by lazy {
        App.instance.networkService.getHttpService(
            LoginHttpService::class.java
        )
    }

    val pageLD = ExtMutableLiveData<Page>()

    fun showPage(page: Page) {
        pageLD.send(page)
    }

    fun checkCanSendVerifyCode(): Rlt<Any> {
        val sendDuration = lastSendVerifyCodeTs + SEND_DURATION - System.currentTimeMillis()
        if (sendDuration > 0) {
            return Rlt.Failed(
                IError(
                    getCompatString(
                        APP_R.string.account_send_verify_code_duration_limit,
                        (sendDuration / 1000).toString()
                    )
                )
            )
        }
        return Rlt.Success(Unit)
    }

    var verifyPhoneRegion: String? = null
    var verifyPhoneNumber: String? = null

    val verifyPhoneNumberLD = ExtMutableLiveData<String>()
    val sendVerifyEnableLD = ExtMutableLiveData<Boolean>()

    fun sendVerifyCode(regionCode: String?, number: String?): LiveData<SendVerifyCode> {
        val liveData = OnceMutableLiveData<SendVerifyCode>()
        viewModelScope.launch {
            if (regionCode.isNullOrEmpty() || number.isNullOrEmpty()) {
                liveData.send(
                    SendVerifyCode(
                        Rlt.Failed(IError(getCompatString(APP_R.string.account_input_phone_number_invalid))),
                        lastSendVerifyCodeTs
                    )
                )
                return@launch
            }
            if (System.currentTimeMillis() - lastSendVerifyCodeTs < SEND_DURATION) {
                //小于60s,不重新发送
                liveData.send(
                    SendVerifyCode(
                        Rlt.Success(Unit),
                        lastSendVerifyCodeTs
                    )
                )
                return@launch
            }

            verifyPhoneRegion = regionCode
            verifyPhoneNumber = number
            verifyPhoneNumberLD.send("$regionCode $number")
            val rlt = retrySendVerifyCode(regionCode, number)
            liveData.send(
                SendVerifyCode(
                    rlt,
                    lastSendVerifyCodeTs
                )
            )
        }
        return liveData
    }

    fun resendVerifyCode(): LiveData<SendVerifyCode> {
        return sendVerifyCode(verifyPhoneRegion, verifyPhoneNumber)
    }

    private suspend fun retrySendVerifyCode(code: String, number: String): Rlt<Any> {
        var tryTimes = 3 //尝试发送3次
        var rlt: Rlt<Res<Any>>? = null
        while (tryTimes > 0) {
            rlt = loginHttpService.sendPhoneVerifyCode(SendPhoneVerifyReq(code, number))
            when (rlt) {
                is Rlt.Failed -> {
                    delay(100) //延时100毫秒后再发送
                    tryTimes--
                    continue
                }

                is Rlt.Success -> {
                    lastSendVerifyCodeTs = System.currentTimeMillis()
                    sendVerifyCodeCountDown()
                    break
                }
            }
        }
        return rlt ?: Rlt.Failed(IError("Unknow error"))
    }


    private fun sendVerifyCodeCountDown() {
        viewModelScope.launch {
            sendVerifyEnableLD.send(false)
            delay(60_000)
            val enable = System.currentTimeMillis() - lastSendVerifyCodeTs > SEND_DURATION
            Log.d(TAG_PHONE_LOGIN, "sendVerifyCodeCountDown, enable:${enable}")
            sendVerifyEnableLD.send(enable)
        }
    }
}