package com.adealink.weparty.account.login.auth

import android.app.Activity
import android.content.Intent
import com.adealink.frame.log.Log
import com.adealink.weparty.account.BuildConfig
import com.adealink.weparty.account.constant.GOOGLE_CLIENT_ID
import com.adealink.weparty.account.constant.GOOGLE_CLIENT_ID_DEBUG
import com.adealink.weparty.account.constant.TAG_GOOGLE_AUTH
import com.adealink.weparty.account.login.auth.AuthManager.Companion.REQ_GOOGLE_SIGN_IN
import com.adealink.weparty.account.login.data.ThirdType
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.auth.api.signin.GoogleSignInStatusCodes
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 java.lang.ref.WeakReference

class GoogleAuth(
    override val activityRef: WeakReference<Activity>?,
    override val authCallback: IAuthCallback?,
) : IAuth {

    companion object {
        private const val ERROR_CODE_SEND_INTENT_EXCEPTION = 10000
        private const val ERROR_CODE_NO_ID_TOKEN = 10002
    }

    override var secret: String? = null

    private var googleSignInClient: GoogleSignInClient? = null
    val thirdType = ThirdType.GOOGLE

    private fun getServerClientId(): String {
        return when (BuildConfig.DEBUG) {
            true -> GOOGLE_CLIENT_ID_DEBUG
            else -> GOOGLE_CLIENT_ID
        }
    }

    override fun auth() {
        val activity = activityRef?.get() ?: return
        val available = GoogleApiAvailability.getInstance()
            .isGooglePlayServicesAvailable(activity.applicationContext)
        if (available != ConnectionResult.SUCCESS) {
            authCallback?.onFailed(thirdType, "google service no support", null)
            return
        }

        unOneTapSignIn(activity)
    }

    private fun getGoogleSignInClient(activity: Activity): GoogleSignInClient {
        if (googleSignInClient != null) {
            return googleSignInClient!!
        }

        val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(getServerClientId())
            .requestEmail()
            .requestProfile()
            .build()
        googleSignInClient = GoogleSignIn.getClient(activity, gso)
        return googleSignInClient!!
    }

    private fun unOneTapSignIn(activity: Activity) {
        val signInIntent = getGoogleSignInClient(activity).signInIntent
        activity.startActivityForResult(signInIntent, REQ_GOOGLE_SIGN_IN)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
        when (requestCode) {
            REQ_GOOGLE_SIGN_IN -> {
                val task: Task<GoogleSignInAccount> =
                    GoogleSignIn.getSignedInAccountFromIntent(intent)

                handleSignInResult(task)
            }
        }
    }

    private fun handleSignInResult(completedTask: Task<GoogleSignInAccount>) {
        try {
            val account = completedTask.getResult(
                ApiException::class.java
            )
            Log.d(TAG_GOOGLE_AUTH, "handleSignInResult, account.id:${account.id}")
            val token = account.idToken
            if (!account.isExpired && !token.isNullOrEmpty()) {
                authCallback?.onSuccess(thirdType, token)
            }
        } catch (e: ApiException) {
            Log.e(
                TAG_GOOGLE_AUTH,
                "signInResult:failed code=${e.statusCode}, errorMsg:${e.message}"
            )
            if (GoogleSignInStatusCodes.SIGN_IN_CANCELLED == e.statusCode) {
                authCallback?.onCancel(thirdType)
            } else {
                authCallback?.onFailed(thirdType, e.message ?: "", e.statusCode)
            }
        }
    }

    override fun logout() {
        val activity = activityRef?.get() ?: return
        getGoogleSignInClient(activity).signOut()
    }

}