package xn.xxp.app;

import android.app.AlertDialog;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;

import com.blankj.utilcode.util.ActivityUtils;
import com.blankj.utilcode.util.AppUtils;
import com.blankj.utilcode.util.GsonUtils;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.ShellUtils;
import com.blankj.utilcode.util.ThreadUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.hikvision.dmb.EthernetConfig;
import com.hikvision.dmb.network.InfoNetworkApi;
import com.hikvision.dmb.system.InfoSystemApi;
import com.hjq.permissions.OnPermissionCallback;
import com.hjq.permissions.Permission;
import com.hjq.permissions.XXPermissions;
import com.kongzue.dialogx.dialogs.InputDialog;
import com.njlz.face.FaceUtils;

import org.json.JSONObject;

import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import core.ui.activity.BaseActivity;
import http.client.ApiRepository;
import http.client.HttpTool;
import http.vo.response.LaboratoryVo;
import io.reactivex.rxjava3.functions.Consumer;
import xn.xxp.HomeActivity;
import xn.xxp.home.auth.PickSignCheckDialog;
import xn.xxp.home.setting.SettingActivity;
import xn.xxp.room.bean.DeviceConfig;
import xn.xxp.room.bean.LabConfig;
import http.vo.response.TerminalAuthResp;
import okhttp3.HttpUrl;
import okhttp3.Response;
import xn.xxp.databinding.ActivityInitBinding;
import xn.xxp.room.RoomTool;
import xn.xxp.utils.Tool;

public class InitActivity extends BaseActivity<ActivityInitBinding> {
    private CountDownTimer storageCD;
    private DeviceConfig deviceConfig;
    private int reTryCount = 0;

    /**
     * 实验室信息是否查询完成
     */
    private volatile boolean isGetLabInfo = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected ActivityInitBinding createViewBinding() {
        return ActivityInitBinding.inflate(getLayoutInflater());
    }

    @Override
    protected void initViews(Bundle savedInstanceState) {
        super.initViews(savedInstanceState);
        deviceConfig = RoomTool.getInstance().deviceConfigDao().getDeviceConfig();
        if (null == deviceConfig) {
            deviceConfig = new DeviceConfig();
        }
        EthernetConfig ethernetConfig = InfoNetworkApi.getEthernetConfig();
        String ip = ethernetConfig.getIpAddress();
        deviceConfig.setIp(ip);
        String devId = "EBOARD_" + InfoSystemApi.getSerialNumber();
        deviceConfig.setDevId(devId);

        binding.versionNameTV.setText(AppUtils.getAppVersionName());
        Tool.INSTANCE.getPermission();
        storageCD = new CountDownTimer(1000, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {

            }

            @Override
            public void onFinish() {
                requestPermission();
            }
        };
        storageCD.start();
    }

    private void requestPermission() {
        if (!XXPermissions.isGranted(this, Permission.MANAGE_EXTERNAL_STORAGE)
                || !XXPermissions.isGranted(this, Permission.READ_PHONE_STATE)
                || !XXPermissions.isGranted(this, Permission.CAMERA)
                || !XXPermissions.isGranted(this, Permission.RECORD_AUDIO)
                || !XXPermissions.isGranted(this, Permission.NOTIFICATION_SERVICE)
        ) {
            Tool.INSTANCE.getPermission();
            storageCD.start();
        } else {
            storageCD.cancel();
            runTask();
        }
    }

    @Override
    protected void initListener() {
        super.initListener();
        binding.logoTV.setOnLongClickListener(v -> {
            if (AppUtils.isAppDebug()) {
                ActivityUtils.startActivity(SettingActivity.class);
                finish();
            } else {
                InputDialog.show("Tips", "请输入密码", "确认").setOkButtonClickListener((dialog, v1) -> {
                    String inputText = dialog.getInputText();
                    if ("admin@098&".equals(inputText)) {
                        ActivityUtils.startActivity(SettingActivity.class);
                    }
                    finish();
                    return false;
                }).show();
            }
            return true;
        });
    }

    @Override
    protected void initData() {
        super.initData();
    }

    private ThreadUtils.SimpleTask<Object> simpleTask;

    private void runTask() {
        simpleTask = new ThreadUtils.SimpleTask<>() {
            @Override
            public Object doInBackground() throws Throwable {
                // 递归检查网络
                available();
                // 递归鉴权
                terminalAuth();
                // 递归查询实验室配置
                queryLabConfig();
                // 递归查询实验室信息
                queryLabInfo();
                // 死循环等待实验室信息查询成功
                while (!isGetLabInfo) {
                    Thread.sleep(10);
                }
                return null;
            }

            @Override
            public void onSuccess(Object result) {
                startSyncFaceWorker();
            }
        };
        ThreadUtils.executeByCached(simpleTask);
    }

    private void startSyncFaceWorker() {
        binding.tips.setText("正在同步人脸...");
        ThreadUtils.executeByCached(new ThreadUtils.SimpleTask<Object>() {
            @Override
            public Object doInBackground() throws Throwable {
                SyncFaceTool.INSTANCE.doWork(true);
                LogUtils.d("人脸同步结束");
                return null;
            }

            @Override
            public void onSuccess(Object result) {
                LogUtils.json("人脸数据库", RoomTool.getInstance().faceDao().getAll());
                ActivityUtils.startActivity(HomeActivity.class);
                finish();
            }
        });
    }

    /**
     * 查询实验室信息
     */
    private void queryLabInfo() {
        if (reTryCount > 0) {
            runOnUiThread(() -> binding.tips.setText("查询实验室信息,正在重试," + reTryCount));
        } else {
            runOnUiThread(() -> binding.tips.setText("正在查询实验室信息..."));
        }
        LabConfig labConfig = RoomTool.getInstance().labConfigDao().getLabConfig();
        addDisposable(InitTool.INSTANCE.queryLabInfo(String.valueOf(labConfig.getLabId()), new androidx.core.util.Consumer<Boolean>() {
            @Override
            public void accept(Boolean aBoolean) {
                if (aBoolean) {
                    isGetLabInfo = true;
                    reTryCount = 0;
                } else {
                    reTryCount++;
                    ThreadUtils.runOnUiThreadDelayed(new Runnable() {
                        @Override
                        public void run() {
                            queryLabInfo();
                        }
                    }, 1000L * ThreadLocalRandom.current().nextInt(10, 20));
                }
            }
        }));
    }

    /**
     * 查询实验室配置
     */
    private void queryLabConfig() throws InterruptedException {
        try {
            if (reTryCount > 0) {
                runOnUiThread(() -> binding.tips.setText("查询实验室配置,正在重试," + reTryCount));
            } else {
                runOnUiThread(() -> binding.tips.setText("正在查询实验室配置..."));
            }
            if (InitTool.INSTANCE.queryLabConfig(deviceConfig.getDevId())) {
                reTryCount = 0;
                return;
            }
        } catch (Exception e) {
            LogUtils.e(Log.getStackTraceString(e));
        }
        reTryCount++;
        Thread.sleep(1000L * ThreadLocalRandom.current().nextInt(10, 20));
        queryLabConfig();
    }

    /**
     * 设备鉴权
     */
    private void terminalAuth() throws InterruptedException {
        try {
            if (reTryCount > 0) {
                runOnUiThread(() -> binding.tips.setText("鉴权异常,正在重试," + reTryCount));
            } else {
                runOnUiThread(() -> binding.tips.setText("正在鉴权..."));
            }
            deviceConfig.setTerminalAuth("");
            RoomTool.getInstance().deviceConfigDao().insert(deviceConfig);
            Response response = HttpTool.terminalAuth(deviceConfig.getDevId());
            if (response.isSuccessful()) {
                String json = response.body().string();
                TerminalAuthResp terminalAuthResp = GsonUtils.fromJson(json, TerminalAuthResp.class);
                if (null != terminalAuthResp) {
                    if (terminalAuthResp.getCode() == 200) {
                        if (!TextUtils.isEmpty(terminalAuthResp.getData())) {
                            LogUtils.d("鉴权", terminalAuthResp.getData());
                            deviceConfig.setTerminalAuth("Bearer " + terminalAuthResp.getData());
                            reTryCount = 0;
                            RoomTool.getInstance().deviceConfigDao().insert(deviceConfig);
                            return;
                        } else {
                            ToastUtils.showLong(terminalAuthResp.getMessage());
                        }
                    }
                }
            }
        } catch (Exception e) {
            LogUtils.e(Log.getStackTraceString(e));
        }
        reTryCount++;
        Thread.sleep(1000L * ThreadLocalRandom.current().nextInt(10, 20));
        terminalAuth();
    }

    private void available() {
        if (reTryCount > 0) {
            runOnUiThread(() -> binding.tips.setText("网络异常,正在重试," + reTryCount));
        } else {
            runOnUiThread(() -> binding.tips.setText("正在检查网络..."));
        }
        ShellUtils.CommandResult result = ShellUtils.execCmd(String.format("ping -c 5 %s", HttpUrl.get(deviceConfig.getBaseUrl()).host()), false);
        if (result.result == 0) {
            PingResult pingResult = parsePingOutput(result.successMsg);
            if (pingResult.avgRtt < 100) {
                reTryCount = 0;
            } else {
                reTryCount++;
                available();
            }
        } else {
            reTryCount++;
            available();
        }
    }


    public PingResult parsePingOutput(String pingOutput) {
        PingResult result = new PingResult();
        // 解析目标IP
        Pattern ipPattern = Pattern.compile("PING (\\d+\\.\\d+\\.\\d+\\.\\d+)");
        Matcher ipMatcher = ipPattern.matcher(pingOutput);
        if (ipMatcher.find()) {
            result.setTargetIP(ipMatcher.group(1));
        }
        // 解析统计信息
        Pattern statsPattern = Pattern.compile(
                "(\\d+) packets transmitted, (\\d+) received, (\\d+)% packet loss, time (\\d+)ms"
        );
        Matcher statsMatcher = statsPattern.matcher(pingOutput);
        if (statsMatcher.find()) {
            result.setPacketsTransmitted(Integer.parseInt(statsMatcher.group(1)));
            result.setPacketsReceived(Integer.parseInt(statsMatcher.group(2)));
            result.setPacketLossPercentage(Double.parseDouble(statsMatcher.group(3)));
        }
        // 解析RTT信息
        Pattern rttPattern = Pattern.compile(
                "rtt min/avg/max/mdev = (\\d+\\.\\d+)/(\\d+\\.\\d+)/(\\d+\\.\\d+)/(\\d+\\.\\d+) ms"
        );
        Matcher rttMatcher = rttPattern.matcher(pingOutput);
        if (rttMatcher.find()) {
            result.setMinRtt(Double.parseDouble(rttMatcher.group(1)));
            result.setAvgRtt(Double.parseDouble(rttMatcher.group(2)));
            result.setMaxRtt(Double.parseDouble(rttMatcher.group(3)));
            result.setMdevRtt(Double.parseDouble(rttMatcher.group(4)));
        }
        return result;
    }

    public class PingResult {
        private String targetIP;
        private int packetsTransmitted;
        private int packetsReceived;
        private double packetLossPercentage;
        private double minRtt;
        private double avgRtt;
        private double maxRtt;
        private double mdevRtt;

        public String getTargetIP() {
            return targetIP;
        }

        public void setTargetIP(String targetIP) {
            this.targetIP = targetIP;
        }

        public int getPacketsTransmitted() {
            return packetsTransmitted;
        }

        public void setPacketsTransmitted(int packetsTransmitted) {
            this.packetsTransmitted = packetsTransmitted;
        }

        public int getPacketsReceived() {
            return packetsReceived;
        }

        public void setPacketsReceived(int packetsReceived) {
            this.packetsReceived = packetsReceived;
        }

        public double getPacketLossPercentage() {
            return packetLossPercentage;
        }

        public void setPacketLossPercentage(double packetLossPercentage) {
            this.packetLossPercentage = packetLossPercentage;
        }

        public double getMinRtt() {
            return minRtt;
        }

        public void setMinRtt(double minRtt) {
            this.minRtt = minRtt;
        }

        public double getAvgRtt() {
            return avgRtt;
        }

        public void setAvgRtt(double avgRtt) {
            this.avgRtt = avgRtt;
        }

        public double getMaxRtt() {
            return maxRtt;
        }

        public void setMaxRtt(double maxRtt) {
            this.maxRtt = maxRtt;
        }

        public double getMdevRtt() {
            return mdevRtt;
        }

        public void setMdevRtt(double mdevRtt) {
            this.mdevRtt = mdevRtt;
        }
    }

    @Override
    public void onBackPressed() {
        Tool.INSTANCE.exitApp();
    }
}