package com.adealink.weparty.im.manager.login

import android.app.Application
import com.adealink.frame.base.CommonDataNullError
import com.adealink.frame.base.Rlt
import com.adealink.frame.base.fastLazy
import com.adealink.frame.frame.BaseFrame
import com.adealink.frame.log.Log
import com.adealink.frame.util.AppUtil
import com.adealink.weparty.App
import com.adealink.weparty.commonui.ext.isFailure
import com.adealink.weparty.im.constant.TAG_IM_LOGIN
import com.adealink.weparty.im.datasource.remote.IMHttpService
import com.adealink.weparty.im.manager.LoginWrapper
import com.adealink.weparty.im.service.TIMAppService
import com.adealink.weparty.im.util.TUIUtils
import com.adealink.weparty.module.account.AccountModule
import com.adealink.weparty.module.account.ILoginListener
import com.adealink.weparty.module.im.IMConfig
import com.tencent.qcloud.tuicore.TUILogin
import com.tencent.qcloud.tuicore.interfaces.TUICallback
import com.tencent.qcloud.tuicore.interfaces.TUILoginConfig
import com.tencent.qcloud.tuicore.interfaces.TUILoginListener
import kotlinx.coroutines.launch

val imLoginManager: ILoginManager by lazy { LoginManager() }

class LoginManager : BaseFrame<com.adealink.weparty.im.manager.login.ILoginListener>(),
    ILoginManager,
    ILoginListener {

    private val imHttpService by fastLazy {
        App.instance.networkService.getHttpService(IMHttpService::class.java)
    }

    override fun init(application: Application) {
        AccountModule.registerListener(this)
        login()
    }

    override fun onLogin() {
        login()
    }

    override fun onLogout() {
        handleLogout()
    }

    private fun handleLogout() {
        Log.d(TAG_IM_LOGIN, "handleLogout")
        if (isLogin()) {
            logout()
        }
    }

    private fun reLogin() {
        login(true)
    }

    override fun login(reLogin: Boolean) {
        launch {
            if (!AccountModule.isLogin()) {
                Log.d(TAG_IM_LOGIN, "login return, Account is not Login")
                return@launch
            }
            if (TUILogin.isUserLogined()) {
                Log.d(TAG_IM_LOGIN, "login return, TUILogin.isUserLogined")
                return@launch
            }
            val uid = AccountModule.uid
            if (uid.isEmpty()) {
                Log.e(TAG_IM_LOGIN, "handleLogin fail, for $uid is invalid.")
                return@launch
            }

            val userSignRlt = getUserIMSign()
            if (userSignRlt.isFailure) {
                Log.d(TAG_IM_LOGIN, "handleLogin, getUserIMSign fail, $userSignRlt")
                return@launch
            }
            val userSign = (userSignRlt as Rlt.Success).data
            val tuiLoginConfig: TUILoginConfig = TUIUtils.getLoginConfig()
            LoginWrapper.loginIMSDK(
                AppUtil.appContext,
                IMConfig.APP_ID,
                uid,
                userSign, tuiLoginConfig,
                object : TUICallback() {
                    override fun onSuccess() {
                        Log.i(TAG_IM_LOGIN, "login onSuccess, uid: $uid")
                        TUILogin.addLoginListener(mLoginListener)
                        TIMAppService.getInstance().registerPushManually()
                    }

                    override fun onError(errorCode: Int, errorMessage: String?) {
                        Log.e(
                            TAG_IM_LOGIN,
                            "login fail errorCode: $errorCode errorMessage:$errorMessage"
                        )
                    }
                })
        }
    }

    private suspend fun getUserIMSign(): Rlt<String> {
        val rlt = imHttpService.imUserSign()
        when (rlt) {
            is Rlt.Failed -> {
                return rlt
            }

            is Rlt.Success -> {
                val sign = rlt.data.data
                if (sign.isNullOrEmpty()) {
                    return Rlt.Failed(CommonDataNullError())
                }
                return Rlt.Success(sign)
            }
        }
    }

    override fun isLogin(): Boolean {
        return TUILogin.isUserLogined()
    }

    private fun logout() {
        try {
            TUILogin.logout(object : TUICallback() {
                override fun onSuccess() {
                    Log.i(TAG_IM_LOGIN, "logout success")
                    TUILogin.removeLoginListener(mLoginListener)
                }

                override fun onError(errorCode: Int, errorMessage: String) {
                    Log.e(
                        TAG_IM_LOGIN,
                        "logout failed, errorCode: $errorCode , errorMessage: $errorMessage"
                    )
                }
            })
        } catch (e: Exception) {
            Log.e(TAG_IM_LOGIN, "logout failed with exception: ${e.message}", e)
        }

    }

    private val mLoginListener: TUILoginListener = object : TUILoginListener() {
        override fun onKickedOffline() {
            super.onKickedOffline()
            Log.i(TAG_IM_LOGIN, "You have been kicked off the line. Please login again!")
            logout()
        }

        override fun onUserSigExpired() {
            super.onUserSigExpired()
            Log.i(TAG_IM_LOGIN, "Your user signature information has expired")
            reLogin()
        }
    }
}