package com.gh.gamecenter.common.base;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.util.Log;

import com.therouter.TheRouter;
import com.gh.gamecenter.common.constant.Config;
import com.gh.gamecenter.common.constant.RouteConsts;
import com.gh.gamecenter.core.HaloApp;
import com.gh.gamecenter.core.provider.ISentryProvider;
import com.lightgame.utils.AppManager;
import com.lightgame.utils.Utils;

import java.lang.Thread.UncaughtExceptionHandler;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeoutException;

public class AppUncaughtHandler implements UncaughtExceptionHandler {

    private final Context mContext;
    private ArrayList<UncaughtExceptionListener> listeners;

    public AppUncaughtHandler(Context context) {
        // 获取系统默认的UncaughtException处理器
        mContext = context;
    }

    public void setUncaughtExceptionListener(UncaughtExceptionListener listener) {
        if (listener == null) {
            listeners = new ArrayList<>();
        }
        listeners.add(listener);
    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        if (("FinalizerWatchdogDaemon").equals(t.getName())
                && e instanceof TimeoutException) {
            // ignore timeoutException
            // detail can be found in this didi tech blog post https://mp.weixin.qq.com/s?__biz=MzU1ODEzNjI2NA==&mid=2247487185&idx=2&sn=cf2d9e10053f625bde0f61d246f14870&source=41#wechat_redirect
        } else {
            if (listeners != null) {
                for (UncaughtExceptionListener listener : listeners) {
                    listener.uncaughtException(t, e);
                }
            }
            new Thread(() -> {
                Looper.prepare();
                Utils.toast(mContext.getApplicationContext(), "\"光环助手\"发生错误");
                Looper.loop();
            });
            saveCrashLogToSp(e);
            restart(mContext);

            ISentryProvider sentryProvider = TheRouter.get(ISentryProvider.class);
            if (sentryProvider != null) {
                sentryProvider.captureException(e);
            }
        }
    }

    public static void restart(final Context context) {
        // S450 这机器会无限重启循环 : (
        if ("S450".equals(Build.MODEL)) return;

        // 防止重复奔溃，导致助手一直重启，20秒内不做处理
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
        long curTime = System.currentTimeMillis();
        long time = sp.getLong("last_restart_time", 0);
        if (curTime - time > 20 * 1000) {
            sp.edit().putLong("last_restart_time", curTime).apply();
            Intent intent = getLaunchIntentForPackage(context);
            if (intent != null) {
                intent.setAction(Intent.ACTION_MAIN);
                intent.addCategory(Intent.CATEGORY_LAUNCHER);
                PendingIntent restartIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
                // 退出程序并重启
                AlarmManager mgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
                mgr.set(AlarmManager.RTC, curTime + 3000, restartIntent); // 1秒钟后重启应用
            }
        }

        AppManager.getInstance().finishAllActivity();
    }

    private static Intent getLaunchIntentForPackage(Context context) {
        String packageName = HaloApp.getInstance().getPackageName();
        Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
        intentToResolve.addCategory(Intent.CATEGORY_INFO);
        intentToResolve.setPackage(packageName);
        List<ResolveInfo> ris = context.getPackageManager().queryIntentActivities(intentToResolve, 0);

        if (ris == null || ris.size() <= 0) {
            intentToResolve.removeCategory(Intent.CATEGORY_INFO);
            intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
            intentToResolve.setPackage(packageName);
            ris = context.getPackageManager().queryIntentActivities(intentToResolve, 0);
        }
        if (ris == null || ris.size() <= 0) {
            return null;
        }
        Intent intent = new Intent(intentToResolve);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setClassName(ris.get(0).activityInfo.packageName, ris.get(0).activityInfo.name);
        return intent;
    }


    // 保存 crash log 到Sp
    public static void saveCrashLogToSp(Throwable ex) {
        String errorMsg = Log.getStackTraceString(ex);
        Config.setExceptionMsg(errorMsg);
        Config.updateContainsErrorMsg(true);
    }

    interface UncaughtExceptionListener {
        void uncaughtException(Thread t, Throwable e);
    }
}