package cn.yyxx.eyuangame.core.impl.login

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Looper
import android.text.TextUtils
import cn.yyxx.eyuangame.base.utils.Logger
import cn.yyxx.eyuangame.base.utils.ParamsUtils
import cn.yyxx.eyuangame.core.entity.LoginType
import cn.yyxx.eyuangame.core.entity.ResultInfo
import cn.yyxx.eyuangame.core.entity.SdkBackLoginInfo
import cn.yyxx.eyuangame.core.entity.Session
import cn.yyxx.eyuangame.core.internal.IRequestCallback
import cn.yyxx.eyuangame.core.network.SdkRequest
import cn.yyxx.eyuangame.core.ui.dialog.ScaleLoadingDialog
import cn.yyxx.eyuangame.core.utils.SessionUtils
import cn.yyxx.support.hawkeye.ToastUtils
import com.facebook.*
import com.facebook.login.LoginManager
import com.facebook.login.LoginResult
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.android.gms.auth.api.signin.GoogleSignInClient
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import com.google.android.gms.common.api.ApiException
import com.google.android.gms.tasks.Task
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.json.JSONException
import org.json.JSONObject
import java.util.*

/**
 * @author #Suyghur.
 * Created on 2021/06/18
 */
class UserSignInImpl constructor(val activity: LoginActivity, private val callback: ISignInCallback) {

    private var fbCallback: CallbackManager? = null
    private var googleSignInClient: GoogleSignInClient? = null
    private var loginLoadingDialog: ScaleLoadingDialog? = null

    init {
        this.fbCallback = CallbackManager.Factory.create()
        val googleServerClientId = ParamsUtils.getGoogleClientId(activity)
        val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .requestIdToken(googleServerClientId)
            .requestId()
            .requestProfile()
            .build()
        this.googleSignInClient = GoogleSignIn.getClient(activity, gso)
    }

    fun facebookLogin(activity: Activity) {
        if (!FacebookSdk.isInitialized()) {
            callback.onFailed("Facebook SDK 初始化失败")
        }
        //先注销账号，防止同一台设备有多个应用登录后直接回调onCancel
        LoginManager.getInstance().logOut()
        LoginManager.getInstance().registerCallback(fbCallback, object : FacebookCallback<LoginResult> {
            override fun onSuccess(result: LoginResult?) {
                result?.apply {
                    try {
                        val jsonObject = JSONObject()
                        jsonObject.put("login_type", LoginType.TYPE_FACEBOOK_LOGIN)
                        jsonObject.put("third_plat_id", AccessToken.getCurrentAccessToken().userId)
                        jsonObject.put("third_plat_token", AccessToken.getCurrentAccessToken().token)
                        userLoginVerify(activity, jsonObject)
                    } catch (e: JSONException) {
                        e.printStackTrace()
                        callback.onFailed("Facebook登录异常")
                    }
                }
            }

            override fun onCancel() {
                callback.onFailed("Facebook登录取消")
            }

            override fun onError(error: FacebookException?) {
                error?.apply {
                    Logger.e("FBLogin onError error : " + this.message)
                }
                callback.onFailed("Facebook登录失败")
            }
        })
        LoginManager.getInstance().logInWithReadPermissions(activity, Collections.singletonList("public_profile"))
    }

    fun googleLogin(activity: Activity) {
        if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(activity) != ConnectionResult.SUCCESS) {
            ToastUtils.toastInfo(activity, "Google Services is not available for this device")
            callback.onFailed("谷歌登录服务不可用，登录失败")
            return
        }

        googleSignInClient?.apply {
            val intent = signInIntent
            activity.startActivityForResult(intent, 10000)
        }
    }

    private fun handleGoogleSignInResult(data: Intent) {
        val task: Task<GoogleSignInAccount> = GoogleSignIn.getSignedInAccountFromIntent(data)
        try {
            val account = task.getResult(ApiException::class.java)
            Logger.d("${account?.email}")
            try {
                val jsonObject = JSONObject()
                jsonObject.put("login_type", LoginType.TYPE_GOOGLE_LOGIN)
                jsonObject.put("third_plat_id", account?.id)
                jsonObject.put("third_plat_token", account?.idToken)
                userLoginVerify(activity, jsonObject)
            } catch (e: JSONException) {
                e.printStackTrace()
                callback.onFailed("Google登录异常")
            }
        } catch (e: ApiException) {
            e.printStackTrace()
            callback.onFailed("Google登录异常")
        }
    }


    fun guestLogin(activity: Activity) {
        try {
            val jsonObject = JSONObject()
            jsonObject.put("login_type", LoginType.TYPE_GUEST_LOGIN)
            jsonObject.put("third_plat_id", "")
            jsonObject.put("third_plat_token", "")
            userLoginVerify(activity, jsonObject)
        } catch (e: JSONException) {
            e.printStackTrace()
            callback.onFailed("游客登录异常")
        }
    }

    fun accountLogin(context: Context, userName: String, pwd: String) {
        try {
            val jsonObject = JSONObject()
            jsonObject.put("login_type", LoginType.TYPE_ACCOUNT_LOGIN)
            jsonObject.put("uname", userName)
            jsonObject.put("pwd", pwd)
            userLoginVerify(context, jsonObject)
        } catch (e: JSONException) {
            e.printStackTrace()
            callback.onFailed("用户登录异常")
        }
    }

    fun userRegister(context: Context, userName: String, pwd: String) {
        try {
            showLoadingDialog(context)
            val registerParams = JSONObject()
            registerParams.put("login_type", LoginType.TYPE_ACCOUNT_LOGIN)
            registerParams.put("uname", userName)
            registerParams.put("pwd", pwd)
            SdkRequest.instance.registerUser(context, registerParams, object : IRequestCallback {
                override fun onResponse(resultInfo: ResultInfo) {
                    hideLoadingDialog()
                    if (resultInfo.code == 1 && !TextUtils.isEmpty(resultInfo.data)) {
                        try {
                            val jsonObject = JSONObject(resultInfo.data)
                            SdkBackLoginInfo.instance.userId = jsonObject.getString("uid")
                            SdkBackLoginInfo.instance.token = jsonObject.getString("token")
                            SdkBackLoginInfo.instance.isRegUser = jsonObject.getInt("is_reg_user") == 1
                            SdkBackLoginInfo.instance.hasBindAccount = jsonObject.getInt("has_bind_account") == 1
                            SdkBackLoginInfo.instance.phoneNum = jsonObject.getString("phone_num")
                            SdkBackLoginInfo.instance.loginType = LoginType.TYPE_ACCOUNT_LOGIN

                            with(Session()) {
                                userId = SdkBackLoginInfo.instance.userId
                                loginType = SdkBackLoginInfo.instance.loginType
                                this.userName = userName
                                this.pwd = pwd
                                GlobalScope.launch(Dispatchers.IO) {
                                    Logger.d("with io coroutines do save session")
                                    SessionUtils.instance.saveSession(context, this@with)
                                }
                            }
                            callback.onSuccess(SdkBackLoginInfo.instance.toJsonString())
                        } catch (e: JSONException) {
                            e.printStackTrace()
                            callback.onFailed("用户注册异常")
                        }
                    } else {
                        callback.onFailed("用户注册异常")
                    }
                }
            })
        } catch (e: Exception) {
            e.printStackTrace()
            hideLoadingDialog()
            callback.onFailed("用户注册异常")
        }
    }

    private fun userLoginVerify(context: Context, loginParams: JSONObject) {
        showLoadingDialog(context)
        SdkRequest.instance.userLoginVerify(context, loginParams, object : IRequestCallback {
            override fun onResponse(resultInfo: ResultInfo) {
                hideLoadingDialog()
                if (resultInfo.code == 1 && !TextUtils.isEmpty(resultInfo.data)) {
                    try {
                        val jsonObject = JSONObject(resultInfo.data)
                        SdkBackLoginInfo.instance.userId = jsonObject.getString("uid")
                        SdkBackLoginInfo.instance.token = jsonObject.getString("token")
                        SdkBackLoginInfo.instance.isRegUser = jsonObject.getInt("is_reg_user") == 1
                        SdkBackLoginInfo.instance.hasBindAccount = jsonObject.getInt("has_bind_account") == 1
                        SdkBackLoginInfo.instance.phoneNum = jsonObject.getString("phone_num")
                        SdkBackLoginInfo.instance.loginType = loginParams.getInt("login_type")

                        with(Session()) {
                            userId = SdkBackLoginInfo.instance.userId
                            loginType = SdkBackLoginInfo.instance.loginType
                            if (loginType == LoginType.TYPE_ACCOUNT_LOGIN) {
                                userName = loginParams.getString("uname")
                                pwd = loginParams.getString("pwd")
                            }
                            GlobalScope.launch(Dispatchers.IO) {
                                Logger.d("with io coroutines do save session")
                                SessionUtils.instance.saveSession(context, this@with)
                            }
                        }
                        callback.onSuccess(SdkBackLoginInfo.instance.toJsonString())
                    } catch (e: JSONException) {
                        e.printStackTrace()
                        callback.onFailed("登录校验异常")
                    }
                } else {
                    callback.onFailed("登录校验异常")
                }
            }
        })
    }

    private fun showLoadingDialog(context: Context) {
        loginLoadingDialog?.apply {
            if (isShowing) {
                dismiss()
            }
            loginLoadingDialog = null
        }

        loginLoadingDialog = ScaleLoadingDialog(context, "")
        loginLoadingDialog?.show()
    }

    private fun hideLoadingDialog() {
        loginLoadingDialog?.apply {
            if (isShowing) {
                dismiss()
            }
            loginLoadingDialog = null
        }
    }

    fun onSignInResult(requestCode: Int, resultCode: Int, intent: Intent) {
        fbCallback?.apply {
            onActivityResult(requestCode, resultCode, intent)
        }
        if (requestCode == 10000) {
            handleGoogleSignInResult(intent)
        }
    }

    interface ISignInCallback {
        fun onSuccess(result: String)

        fun onFailed(result: String)
    }
}