package com.gh.gamecenter.login.user;

import static com.gh.gamecenter.common.constant.Constants.LOGIN_TAG;
import static com.gh.gamecenter.common.constant.Constants.LOGOUT_TAG;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MediatorLiveData;

import com.gh.gamecenter.common.callback.BiCallback;
import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.common.eventbus.EBReuse;
import com.gh.gamecenter.common.retrofit.ApiResponse;
import com.gh.gamecenter.common.retrofit.BiResponse;
import com.gh.gamecenter.common.retrofit.Response;
import com.gh.gamecenter.common.utils.DeviceUtils;
import com.gh.gamecenter.common.utils.EnvHelper;
import com.gh.gamecenter.common.utils.ExtensionsKt;
import com.gh.gamecenter.common.utils.PackageFlavorHelper;
import com.gh.gamecenter.common.utils.SensorsBridge;
import com.gh.gamecenter.core.provider.IAcceleratorDataHolderProvider;
import com.gh.gamecenter.core.provider.IAcceleratorProvider;
import com.gh.gamecenter.core.provider.IAppProvider;
import com.gh.gamecenter.core.provider.IDataUtilsProvider;
import com.gh.gamecenter.core.provider.IDownloadManagerProvider;
import com.gh.gamecenter.core.provider.IErrorHelperProvider;
import com.gh.gamecenter.core.provider.IMiniGameRecentlyPlayedProvider;
import com.gh.gamecenter.core.provider.IPushProvider;
import com.gh.gamecenter.core.provider.IReservationRepositoryProvider;
import com.gh.gamecenter.core.provider.IWechatBindHelperProvider;
import com.gh.gamecenter.core.utils.GsonUtils;
import com.gh.gamecenter.core.utils.SPUtils;
import com.gh.gamecenter.feature.entity.AvatarBorderEntity;
import com.gh.gamecenter.feature.entity.BackgroundImageEntity;
import com.gh.gamecenter.feature.entity.BaseEntity;
import com.gh.gamecenter.feature.entity.QyToken;
import com.gh.gamecenter.feature.entity.VipEntity;
import com.gh.gamecenter.feature.provider.IMessageUnreadRepositoryProvider;
import com.gh.gamecenter.login.HaloApp;
import com.gh.gamecenter.login.R;
import com.gh.gamecenter.login.entity.IdCardEntity;
import com.gh.gamecenter.login.entity.LoginTokenEntity;
import com.gh.gamecenter.login.entity.TokenEntity;
import com.gh.gamecenter.login.entity.UserInfoEntity;
import com.gh.gamecenter.login.retrofit.ApiService;
import com.gh.gamecenter.login.retrofit.RetrofitManager;
import com.gh.gamecenter.login.utils.LoginHelper;
import com.gh.gamecenter.login.utils.LoginUtils;
import com.gh.gamecenter.login.utils.NewLogUtils;
import com.gh.gamecenter.login.utils.QuickLoginHelper;
import com.lightgame.utils.Utils;
import com.therouter.TheRouter;

import org.greenrobot.eventbus.EventBus;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import kotlin.Pair;
import kotlin.Triple;
import kotlin.Unit;
import kotlin.jvm.functions.Function0;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.HttpException;

/**
 * Created by khy on 28/11/17.
 */
public class UserRepository {

    private final SharedPreferences mPreferences;

    private Context mContext;

    private ApiService mApiService;

    private final MediatorLiveData<ApiResponse<UserInfoEntity>> mLoginObsResponseUserInfo = new MediatorLiveData<>();
    private final MediatorLiveData<ApiResponse<UserInfoEntity>> mEditObsResponseUserInfo = new MediatorLiveData<>();
    private final MediatorLiveData<Boolean> mUploadBackgroundLiveData = new MediatorLiveData<>();
    private final MediatorLiveData<Boolean> mUploadAvatarBorderLiveData = new MediatorLiveData<>();

    private final MediatorLiveData<LoginTokenEntity> mObservableLoginToken = new MediatorLiveData<>();

    private UserInfoEntity mCacheUserInfoEntity;
    private LoginTokenEntity mCacheLoginTokenEntity;

    public static UserRepository getInstance() {
        return SingletonHolder.INSTANCE;
    }

    private UserRepository() {
        mContext = HaloApp.getInstance().getApplicationContext();
        mApiService = RetrofitManager.getInstance().getApi();
        mPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
        isAutoLogging = true;
        checkLogin();
    }

    public void init() {
        getLoginUserInfo();
    }

    protected void checkLogin() {
        LoginTokenEntity tokenEntity = null;
        String userToken = mPreferences.getString(Constants.USER_TOKEN_KEY, null);
        if (!TextUtils.isEmpty(userToken)) {
            tokenEntity = GsonUtils.fromJson(userToken, LoginTokenEntity.class);
        }

        if (tokenEntity == null || tokenEntity.getRefreshToken() == null || tokenEntity.getAccessToken() == null) {
            logout();
            if (isAutoLogging && autoLoginListener != null) {
                autoLoginListener.finished();
            }
            isAutoLogging = false;
            return;
        }
        TokenEntity refreshToken = tokenEntity.getRefreshToken();
        if (refreshToken.getExpire() > Utils.getTime(mContext)) {
            cacheAndNotifyLoginToken(tokenEntity); // 设置登录数据
            refreshUserInfo(null); // 刷新UserInfo,如果refreshToken过期 自动刷新
            return;
        }

        logout();
        if (isAutoLogging && autoLoginListener != null) {
            autoLoginListener.finished();
        }
        isAutoLogging = false;
    }

    @SuppressLint("CheckResult")
    public void logout() {
        String userId = UserManager.getInstance().getUserId();
        SensorsBridge.logout(userId);

        if (UserManager.getInstance().getLoginTokenEntity() != null
                && "qq".equals(UserManager.getInstance().getLoginTokenEntity().getLoginType())) {
            LoginHelper.logoutWithQQ();
        }
        UserManager.getInstance().logout();

        if (!TextUtils.isEmpty(userId)) {
            // 退出登录后推送解绑别名
            IPushProvider pushProvider = TheRouter.get(IPushProvider.class);
            if (pushProvider != null) {
                pushProvider
                        .unbindAlias(userId)
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe((s) -> {
                        }, (e) -> {
                        });
            }
        }

        mLoginObsResponseUserInfo.postValue(null);
        mObservableLoginToken.postValue(null);

        if (mCacheLoginTokenEntity != null) {
            mCacheLoginTokenEntity = null;
        }

        if (mCacheUserInfoEntity != null) {
            mCacheUserInfoEntity = null;
        }

        SPUtils.setString(mPreferences, Constants.USER_TOKEN_KEY, null);
        SPUtils.setString(mPreferences, Constants.USER_INFO_KEY, null);
        SPUtils.setString(Constants.SP_REGULATION_TEST_PASS_STATUS, "");

        IReservationRepositoryProvider reservationRepository = TheRouter.get(IReservationRepositoryProvider.class);
        if (reservationRepository != null) {
            reservationRepository.clearReservations();
        }

        // 通知页面更新
        EventBus.getDefault().post(new EBReuse(LOGOUT_TAG));

        IDataUtilsProvider dataUtils = TheRouter.get(IDataUtilsProvider.class);
        if (dataUtils != null) {
            dataUtils.getDeviceCertification();
        }

        // 退出登录后进行预取号
        QuickLoginHelper.preLogin(mContext);

        // 退出加速器
        IAcceleratorProvider acceleratorProvider = TheRouter.get(IAcceleratorProvider.class);
        if (acceleratorProvider != null) {
            acceleratorProvider.deleteQyUserToken();
        }
        IAcceleratorDataHolderProvider iAcceleratorDataHolderProvider = TheRouter.get(IAcceleratorDataHolderProvider.class);
        if (iAcceleratorDataHolderProvider != null) {
            iAcceleratorDataHolderProvider.clear();
        }
    }

    public LiveData<ApiResponse<UserInfoEntity>> getLoginUserInfo() {
        if (mCacheUserInfoEntity != null) {
            mLoginObsResponseUserInfo.postValue(new ApiResponse<>(mCacheUserInfoEntity));
        } else {
            String userInfo = mPreferences.getString(Constants.USER_INFO_KEY, null);
            if (!TextUtils.isEmpty(userInfo)) {
                UserInfoEntity infoEntity = GsonUtils.fromJson(userInfo, UserInfoEntity.class);
                cacheAndNotifyUserInfo(infoEntity, false);
            }
        }

        return mLoginObsResponseUserInfo;
    }

    public void login(final JSONObject content, final LoginTag loginTag) {
        login(content, loginTag, null);
    }

    // 登录前，做好body判断
    public void login(final JSONObject content, final LoginTag loginTag, BiCallback<LoginTokenEntity, ApiResponse<LoginTokenEntity>> callback) {

        Observable<LoginTokenEntity> observable = null;
        String userToken = null;

        try {
            JSONObject device = DeviceUtils.getLoginDevice(mContext.getApplicationContext());
            content.put("device", device);
            RequestBody body = RequestBody.create(MediaType.parse("application/json"), content.toString());

            if (loginTag == LoginTag.weibo) {
                userToken = content.getString("uid");
                observable = mApiService.loginByWeibo(body);
            } else if (loginTag == LoginTag.qq) {
                userToken = content.getString("openid");
                observable = mApiService.loginByQQ(body);
            } else if (loginTag == LoginTag.wechat) {
                userToken = content.getString("openid");
                observable = mApiService.loginByWechat(body);
            } else if (loginTag == LoginTag.douyin) {
                userToken = content.getString("openid");
                observable = mApiService.loginByDouYin(body);
            } else if (loginTag == LoginTag.phone) {
                userToken = content.getString("mobile");
                observable = mApiService.loginByMobile(body);
            } else if (loginTag == LoginTag.oauth) {
                userToken = content.getString("token");
                observable = RetrofitManager.getInstance().getNewApi().loginByOauth(body);
            } else {
                return;
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

        if (observable == null) return;

        final String finalUserToken = userToken;
        observable
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Response<LoginTokenEntity>() {
                    @Override
                    public void onResponse(LoginTokenEntity response) {
                        super.onResponse(response);
                        // 设置登录方式
                        if (LoginTag.phone.equals(loginTag)) {
                            try {
                                response.setLoginType(content.getString("mobile"));
                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                        } else {
                            response.setLoginType(loginTag.name());
                        }

                        response.setId(finalUserToken);

                        userTokenHandle(response, loginTag);
                        IWechatBindHelperProvider wechatBindHelper = TheRouter.get(IWechatBindHelperProvider.class);
                        if (wechatBindHelper != null) {
                            wechatBindHelper.getWechatConfig(null);
                        }

                        if (callback != null) {
                            callback.onFirst(response);
                        }
                    }

                    @Override
                    public void onApiFailure(ApiResponse<LoginTokenEntity> e) {
                        super.onApiFailure(e);
                        try {
                            HttpException httpException = e.getHttpException();
                            ApiResponse<UserInfoEntity> value = new ApiResponse<>();
                            value.setThrowable(value.getThrowable());
                            value.setHttpException(httpException);
                            mLoginObsResponseUserInfo.postValue(value);

                            if (LoginTag.qq.equals(loginTag)) {
                                LoginHelper.logoutWithQQ();
                            }
                            // 如果是一键登录失败，不需要弹这些提示
                            if (!LoginTag.oauth.equals(loginTag)) {
                                if (httpException != null) {
                                    if ((httpException.code() == 400 || httpException.code() == 403)) {
                                        ResponseBody responseBody = httpException.response().errorBody();
                                        String string = responseBody.string();
                                        JSONObject content = new JSONObject(string);
                                        int code = content.getInt("code");
                                        if (httpException.code() == 400) {
                                            LoginUtils.outputErrorHint(mContext, code);
                                        } else if (code == 403092) {
                                            Utils.toast(mContext, "填写邀请码错误");
                                        } else {
                                            Utils.toast(mContext, mContext.getString(R.string.login_failure_hint_code, code));
                                        }
                                        Utils.log("login->onFailure:: code:" + code + " content:" + content.toString());
                                    } else {
                                        Utils.toast(mContext, mContext.getString(R.string.login_failure_hint_code, httpException.code()));
                                    }
                                } else {
                                    Utils.toast(mContext, mContext.getString(R.string.login_failure_hint));
                                }
                            } else {
                                Utils.toast(mContext, mContext.getString(R.string.auth_login_failure_hint));
                            }
                        } catch (Exception e1) {
                            e1.printStackTrace();
                        }

                        if (callback != null) {
                            callback.onSecond(e);
                        }
                    }
                });
    }

    //更改用户信息
    @SuppressLint("CheckResult")
    public void changeUserInfo(final String content, final String editType, final Boolean isForcedToCertificate) {
        // 未登录也可以更新实名认证 https://git.ghzs.com/pm/halo-app-issues/-/issues/1526 (这里拦截掉实名更新类型的东西)
        if (UserViewModel.TYPE_ID_CARD.equals(editType)) {
            updateCertificate(content, isForcedToCertificate);
            return;
        }

        JSONObject object = new JSONObject();
        try {
            if (editType.equals(UserViewModel.TYPE_BACKGROUND)
                    || editType.equals(UserViewModel.TYPE_ICON_BORDER)) {
                object = new JSONObject();
                object.put(editType, new JSONObject(content));
            } else {
                object.put(editType, content);
            }
            JSONObject device = DeviceUtils.getLoginDevice(mContext.getApplicationContext());
            object.put("device", device);
        } catch (JSONException e) {
            e.printStackTrace();
        }

        RequestBody body = RequestBody.create(MediaType.parse("application/json"),
                object.toString());
        mApiService
                .changeUserInfo(body, UserManager.getInstance().getUserId())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Response<ResponseBody>() {
                    @Override
                    public void onResponse(ResponseBody response) {
                        super.onResponse(response);
                        switch (editType) {
                            case UserViewModel.TYPE_NAME:
                                mCacheUserInfoEntity.setName(content);
                                break;
                            case UserViewModel.TYPE_QQ:
                                mCacheUserInfoEntity.setQq(content);
                                break;
                            case UserViewModel.TYPE_MOBILE:
                                mCacheUserInfoEntity.setMobile(content);
                                break;
                            case UserViewModel.TYPE_GENDER:
                                mCacheUserInfoEntity.setGender(content);
                                break;
                            case UserViewModel.TYPE_REGION:
                                mCacheUserInfoEntity.setRegion(content);
                                break;
                            case UserViewModel.TYPE_PORTRAIT:
                                mCacheUserInfoEntity.setIcon(content);
                                break;
                            case UserViewModel.TYPE_ID_CARD:
                                mCacheUserInfoEntity.setIdCard(GsonUtils.fromJson(content, IdCardEntity.class));
                                break;
                            case UserViewModel.TYPE_INTRODUCE:
                                mCacheUserInfoEntity.setIntroduce(content);
                                break;
                            case UserViewModel.TYPE_BACKGROUND:
                                mCacheUserInfoEntity.setBackground(GsonUtils.fromJson(content, BackgroundImageEntity.class));
                                mUploadBackgroundLiveData.postValue(true);
                                break;
                            case UserViewModel.TYPE_ICON_BORDER:
                                mCacheUserInfoEntity.setIconBorder(GsonUtils.fromJson(content, AvatarBorderEntity.class));
                                mUploadAvatarBorderLiveData.postValue(true);
                                break;
                        }

                        userInfoHandle(mCacheUserInfoEntity, true);
                    }

                    @Override
                    public void onApiFailure(ApiResponse<ResponseBody> e) {
                        super.onApiFailure(e);
                        HttpException httpException = e.getHttpException();

                        ApiResponse<UserInfoEntity> value = new ApiResponse<>();
                        value.setThrowable(e.getThrowable());
                        value.setHttpException(httpException);
                        mEditObsResponseUserInfo.postValue(value);
                        if (editType.equals(UserViewModel.TYPE_BACKGROUND)) {
                            mUploadBackgroundLiveData.postValue(false);
                        }
                        if (editType.equals(UserViewModel.TYPE_ICON_BORDER)) {
                            mUploadAvatarBorderLiveData.postValue(false);
                        }

                        if (httpException == null || httpException.code() == Constants.NOT_NETWORK_CODE) {
                            Utils.toast(mContext, "请检查网络是否可用");
                            return;
                        }
                        try {
                            ResponseBody responseBody = e.getHttpException().response().errorBody();
                            String string = responseBody.string();
                            JSONObject content = new JSONObject(string);
                            int code = content.getInt("code");
                            LoginUtils.outputErrorHint(mContext, code);
                        } catch (Exception e1) {
                            e1.printStackTrace();
                        }
                    }
                });
    }

    public void refreshUserInfo(LoginTag loginTag) {
        mApiService
                .getUserInfo(EnvHelper.getHost() + "tokens:validate")
                .flatMap((Function<UserInfoEntity, ObservableSource<Pair<QyToken, UserInfoEntity>>>) this::getQyToken)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(userInfoResponse(loginTag));
    }

    /**
     * 更新实名信息
     */
    @SuppressLint("CheckResult")
    private void updateCertificate(final String content, final Boolean isForcedToCertificate) {
        UserInfoEntity userInfoEntity = new UserInfoEntity();
        IdCardEntity idCardEntity = GsonUtils.fromJson(content, IdCardEntity.class);
        userInfoEntity.setIdCard(idCardEntity);
        RequestBody body = RequestBody.create(
                MediaType.parse("application/json"), GsonUtils.toJson(userInfoEntity));
        RetrofitManager.getInstance().getApi().postCertification(body)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new BiResponse<ResponseBody>() {
                    @Override
                    public void onSuccess(ResponseBody data) {
                        ApiResponse<UserInfoEntity> response = new ApiResponse<>();
                        response.setData(new UserInfoEntity());
                        mEditObsResponseUserInfo.postValue(response);
                        // 登录状态下更新实名认证信息
                        if (mCacheUserInfoEntity != null) {
                            mCacheUserInfoEntity.setIdCard(GsonUtils.fromJson(content, IdCardEntity.class));
                            userInfoHandle(mCacheUserInfoEntity, true);
                        }
                        try {
                            JSONObject object = new JSONObject(data.string());
                            boolean isUnQualified = object.getBoolean("minor");
                            int qualifyInt = 1;
                            if (!isUnQualified) {
                                qualifyInt = 2;
                            }
                            NewLogUtils.INSTANCE.logCertificationResult(isForcedToCertificate, qualifyInt);
                        } catch (Throwable e) {
                            e.printStackTrace();
                        }

                        // 重启因为实名认证而处于等待中的任务
                        IDownloadManagerProvider downloadManager = TheRouter.get(IDownloadManagerProvider.class);
                        if (downloadManager != null) {
                            downloadManager.resumeAllInvisiblePendingTask();
                        }
                    }

                    @Override
                    public void onFailure(@NonNull Exception exception) {
                        mEditObsResponseUserInfo.postValue(null);
                        IErrorHelperProvider errorHelper = TheRouter.get(IErrorHelperProvider.class);
                        if (errorHelper != null) {
                            errorHelper.handleLoginError(HaloApp.getInstance(), (HttpException) exception, "", true);
                        }
                        NewLogUtils.INSTANCE.logCertificationResult(isForcedToCertificate, 0);
                    }
                });
    }


    /**
     * 同步实名信息
     */
    @SuppressLint("CheckResult")
    public void syncCertificate(final String realName, final String idCard) {
        Map<String, Map<String, String>> map = new HashMap<>();
        Map<String, String> info = new HashMap<>();
        info.put("id", idCard);
        info.put("name", realName);
        map.put("id_card", info);
        RequestBody body = RequestBody.create(
                MediaType.parse("application/json"), new JSONObject(map).toString());
        RetrofitManager.getInstance().getApi().postSyncCertification(body)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Response<ResponseBody>() {
                    @Override
                    public void onResponse(@Nullable ResponseBody response) {
                        super.onResponse(response);
                        IDataUtilsProvider dataUtils = TheRouter.get(IDataUtilsProvider.class);
                        if (dataUtils != null) {
                            dataUtils.getDeviceCertification();
                        }
                    }

                    @Override
                    public void onApiFailure(ApiResponse<ResponseBody> e) {
                        super.onApiFailure(e);

                    }
                });
    }

    private Response<Pair<QyToken, UserInfoEntity>> userInfoResponse(final LoginTag loginTag) {
        return new Response<Pair<QyToken, UserInfoEntity>>() {
            @Override
            public void onResponse(Pair<QyToken, UserInfoEntity> response) {
                super.onResponse(response);
                QyToken qyToken = response.getFirst();
                UserInfoEntity userInfo = response.getSecond();

                IAcceleratorProvider acceleratorProvider = TheRouter.get(IAcceleratorProvider.class);
                if (acceleratorProvider != null && qyToken != null) {
                    String userId = userInfo != null ? userInfo.getUserId() : "";
                    acceleratorProvider.setQyUserToken(qyToken.getToken(), userId != null ? userId : "", () -> {
                        updateUserInfo(userInfo, loginTag);
                        return null;
                    });
                } else {
                    updateUserInfo(userInfo, loginTag);
                }
            }

            @Override
            public void onApiFailure(ApiResponse<Pair<QyToken, UserInfoEntity>> e) {
                super.onApiFailure(e);
                loginFailed(loginTag, e);
            }
        };
    }

    @SuppressLint("CheckResult")
    private void updateUserInfo(UserInfoEntity userInfo, LoginTag loginTag) {
        if (userInfo == null) {
            // 理论上这里不会调用，做这个判断只是为了消除空指针提示
            loginFailed(loginTag, new ApiResponse<>());
            return;
        }
        userInfoHandle(userInfo, false);
        IReservationRepositoryProvider reservationRepository = TheRouter.get(IReservationRepositoryProvider.class);
        if (reservationRepository != null) {
            reservationRepository.refreshReservations();
        }

        UserManager.getInstance().refreshUserRegulationTestStatus();

        if (loginTag != null) {
            Utils.toast(mContext, R.string.login_success);
            EventBus.getDefault().post(new EBReuse(LOGIN_TAG));

            IMessageUnreadRepositoryProvider messageUnreadRepository = TheRouter.get(IMessageUnreadRepositoryProvider.class);
            if (messageUnreadRepository != null) {
                messageUnreadRepository.loadMessageUnreadData();
            }

            // 登录成功后推送绑定别名
            IPushProvider pushProvider = TheRouter.get(IPushProvider.class);
            if (pushProvider != null) {
                pushProvider
                        .bindAlias(userInfo.getUserId())
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe((s) -> {
                        }, (e) -> {
                        });
            }

            // 登录成功后，刷新qq小游戏最近在玩
            IMiniGameRecentlyPlayedProvider miniGameRecentlyPlayedProvider = TheRouter.get(IMiniGameRecentlyPlayedProvider.class);
            if (miniGameRecentlyPlayedProvider != null) {
                miniGameRecentlyPlayedProvider.refreshQQMiniRecentPlayed();
            }
        }

        if (UserManager.getInstance().getLoginTokenEntity() != null) {
            IAppProvider appProvider = TheRouter.get(IAppProvider.class);
            if (UserManager.getInstance().getLoginTokenEntity().isFirstLogin()) {
                appProvider.getFlavorProvider().logEvent("active_register");
            }

            SensorsBridge.login(UserManager.getInstance().getUserId());
            if (loginTag != null) {
                SensorsBridge.trackEvent("LoginResult", "login_type", loginTag.toChinese(), "login_result", "成功");
            }
        }
        if (isAutoLogging && autoLoginListener != null) {
            autoLoginListener.finished();
        }
        isAutoLogging = false;
    }


    private void loginFailed(LoginTag loginTag, ApiResponse<Pair<QyToken, UserInfoEntity>> e) {
        if (loginTag != null) {
            ApiResponse<UserInfoEntity> apiResponse = new ApiResponse<>();
            apiResponse.setThrowable(e.getThrowable());
            apiResponse.setHttpException(e.getHttpException());
            mLoginObsResponseUserInfo.postValue(apiResponse);

            IErrorHelperProvider errorHelper = TheRouter.get(IErrorHelperProvider.class);
            if (errorHelper != null) {
                errorHelper.handleLoginError(mContext, e.getHttpException(), loginTag.toChinese(), false);
            }
            logout();
        } else {
            // loginTag == null 时，UserInfo 刷新失败，这里没有退出登录，此时用户仍然是登录状态，就会使用本地缓存的用户信息,等到调用下一个需要用户token的接口时，刷新token之后才会刷新用户信息
            // 在此之后，如果用户不进入搜索页或者详情页，则再也没有机会刷新 加速器vip状态，用户点击加速时，可能会出现状态错误
            // 所以，这里需要刷新 用户vip状态 和 qyToken
            // 请注意，这里qiToken也需要刷新，因为用户可能在自定义页面点击加速，自定义页面不需要登录状态，可能不会自动刷新token
            String userInfo = mPreferences.getString(Constants.USER_INFO_KEY, null);
            if (!TextUtils.isEmpty(userInfo)) {
                UserInfoEntity infoEntity = GsonUtils.fromJson(userInfo, UserInfoEntity.class);
                setAcceleratorToken(infoEntity.getUserId(), () -> null);
            }

        }

        if (PackageFlavorHelper.IS_TEST_FLAVOR) {
            try {
                HttpException httpException = e.getHttpException();
                ResponseBody responseBody = httpException.response().errorBody();
                Utils.log("UserInfo ->onApiFailure Code:" + httpException.code() + " ErrorBody:" + responseBody.string());
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
        if (isAutoLogging && autoLoginListener != null) {
            autoLoginListener.finished();
        }
        isAutoLogging = false;
    }

    @SuppressLint("CheckResult")
    public void setAcceleratorToken(String userId, Function0<Unit> function) {
        RetrofitManager.getInstance().getNewApi()
                .getQyToken(userId, "gjonline_vip")
                .compose(ExtensionsKt.singleToMain())
                .subscribe(new BiResponse<BaseEntity<QyToken>>() {

                    @Override
                    public void onSuccess(BaseEntity<QyToken> data) {
                        QyToken qyToken = data.getData();
                        if (qyToken != null) {
                            String token = qyToken.getToken();
                            if (!token.isEmpty()) {
                                IAcceleratorProvider acceleratorProvider = TheRouter.get(IAcceleratorProvider.class);
                                if (acceleratorProvider != null) {
                                    acceleratorProvider.setQyUserToken(token, userId, function);
                                }
                            } else {
                                if (function != null) {
                                    function.invoke();
                                }

                            }
                        }
                    }

                    @Override
                    public void onFailure(@NonNull Exception exception) {
                        super.onFailure(exception);
                        if (function != null) {
                            function.invoke();
                        }
                    }
                });
    }

    /**
     * 用户登录之后调用(包括自动登录和主动登录)
     * 1.刷新 奇游token
     * 2.获取vip状态
     */
    public Observable<Pair<QyToken, UserInfoEntity>> getQyToken(UserInfoEntity userInfoEntity) {
        String userId = userInfoEntity.getUserId();
        String vipType = "gjonline_vip";
        return RetrofitManager.getInstance().getNewApi()
                .getQyToken(userId, vipType)
                .map(BaseEntity::getData)
                .onErrorReturnItem(new QyToken())
                .map(qyToken -> new Pair<>(qyToken, userInfoEntity)).toObservable();
    }

    /**
     * 光环刷新token之后调用：刷新奇游token
     */
    public Observable<Pair<QyToken, LoginTokenEntity>> loadQyToken(String userId, LoginTokenEntity loginTokenEntity) {
        return RetrofitManager.getInstance().getNewApi()
                .getQyToken(userId, "gjonline_vip")
                .map(qyTokenBaseEntity -> new Pair<>(qyTokenBaseEntity.getData(), loginTokenEntity))
                .onErrorReturnItem(new Pair<>(null, loginTokenEntity))
                .toObservable();
    }

    private void userInfoHandle(final UserInfoEntity userInfo, boolean isEditUserInfo) {
        SPUtils.setString(mPreferences, Constants.USER_INFO_KEY, GsonUtils.toJson(userInfo));

        cacheAndNotifyUserInfo(userInfo, isEditUserInfo);
    }

    private void userTokenHandle(final LoginTokenEntity tokenEntity, LoginTag loginTag) {
        SPUtils.setString(mPreferences, Constants.USER_TOKEN_KEY, GsonUtils.toJson(tokenEntity));
        cacheAndNotifyLoginToken(tokenEntity);

        refreshUserInfo(loginTag);
    }

    public void cacheAndNotifyUserInfo(UserInfoEntity userInfoEntity, boolean isEditUserInfo) {
        setUserManagerData(null, userInfoEntity);

        mCacheUserInfoEntity = userInfoEntity;
        mLoginObsResponseUserInfo.postValue(new ApiResponse<>(userInfoEntity));

        if (isEditUserInfo) {
            mEditObsResponseUserInfo.postValue(new ApiResponse<>(userInfoEntity));
        } else {
            IDataUtilsProvider dataUtils = TheRouter.get(IDataUtilsProvider.class);
            if (dataUtils != null) {
                dataUtils.getDeviceCertification();
            }
        }
    }

    @Nullable
    public UserInfoEntity getCacheUserInfoEntity() {
        return mCacheUserInfoEntity;
    }

    private void cacheAndNotifyLoginToken(LoginTokenEntity loginTokenEntity) {
        setUserManagerData(loginTokenEntity, null);

        mCacheLoginTokenEntity = loginTokenEntity;
        mObservableLoginToken.postValue(loginTokenEntity);
    }


    public void setUserManagerData(LoginTokenEntity loginTokenEntity, UserInfoEntity userInfoEntity) {
        if (loginTokenEntity != null) {
            UserManager.getInstance().setLoginTokenEntity(loginTokenEntity);
        }
        if (userInfoEntity != null) {
            UserManager.getInstance().setUserInfoEntity(userInfoEntity);
        }
    }

    public MediatorLiveData<ApiResponse<UserInfoEntity>> getEditObsUserInfo() {
        return mEditObsResponseUserInfo;
    }

    public MediatorLiveData<Boolean> getUploadBackgroundLiveData() {
        return mUploadBackgroundLiveData;
    }

    public MediatorLiveData<Boolean> getUploadAvatarBorderLiveData() {
        return mUploadAvatarBorderLiveData;
    }

    private static class SingletonHolder {
        private static final UserRepository INSTANCE = new UserRepository();
    }

    private boolean isAutoLogging;
    private AutoLoginListener autoLoginListener;

    public void setAutoLoginListener(AutoLoginListener listener) {
        this.autoLoginListener = listener;
        if (!isAutoLogging) {
            autoLoginListener.finished();
        }
    }

    /**
     * 监听启动app后，自动登录是否成功
     * 首页弹窗需要用到登录后的县官数据
     */
    public interface AutoLoginListener {

        void finished();
    }
}
