package com.miraclegarden.smsmessage;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;

import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;

import com.miraclegarden.smsmessage.service.NotificationHealthCheckWorker;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class App extends Application {
    private static final String TAG = "App";
    public static String Hash_value;
    private static App instance;

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
        String packageName = getApplicationContext().getPackageName();
        MessageDigest messageDigest = getMessageDigest();
        String signature = getSignature(this, packageName);
        Hash_value = getHashCode(packageName, messageDigest, signature);
        scheduleHealthCheck();
    }

    public static Context getAppContext() {
        return instance;
    }

    private void scheduleHealthCheck() {
        PeriodicWorkRequest healthCheck = new PeriodicWorkRequest.Builder(
                NotificationHealthCheckWorker.class, 15, TimeUnit.MINUTES)
                .build();
        WorkManager.getInstance(this).enqueueUniquePeriodicWork(
                "notification_health_check",
                ExistingPeriodicWorkPolicy.KEEP,
                healthCheck);
    }

    public static MessageDigest getMessageDigest() {
        MessageDigest messageDigest = null;
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException e) {
            Log.e(TAG, "No Such Algorithm.", e);
        }
        return messageDigest;
    }

    public static String getSignature(Context context, String packageName) {
        PackageManager packageManager = context.getPackageManager();
        Signature[] signatureArrs;
        try {
            signatureArrs = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES).signatures;
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "Package name inexistent.");
            return "";
        }
        if (null == signatureArrs || 0 == signatureArrs.length) {
            Log.e(TAG, "signature is null.");
            return "";
        }
        return signatureArrs[0].toCharsString();
    }

    private String getHashCode(String packageName, MessageDigest messageDigest, String signature) {
        String appInfo = packageName + " " + signature;
        messageDigest.update(appInfo.getBytes(StandardCharsets.UTF_8));
        byte[] hashSignature = messageDigest.digest();
        hashSignature = Arrays.copyOfRange(hashSignature, 0, 9);
        String base64Hash = Base64.encodeToString(hashSignature, Base64.NO_PADDING | Base64.NO_WRAP);
        base64Hash = base64Hash.substring(0, 11);
        return base64Hash;
    }


    public static void saveNotiList(Context context, String value) {
        SharedPreferences sp = context.getSharedPreferences("server", Activity.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.putString("saveNotiList", value);
        editor.apply();
    }

    public static List<MessageInfo> getNotiList(Context context) {
        SharedPreferences sp = context.getSharedPreferences("server", Activity.MODE_PRIVATE);
        String messages = sp.getString("saveNotiList", "");
        if (TextUtils.isEmpty(messages)) {
            return new ArrayList<>();
        }
        List<MessageInfo> messageInfos = GsonUtils.getListFromJSON(messages, MessageInfo.class);
        if (messageInfos == null) {
            return new ArrayList<>();
        }
        return messageInfos;
    }


    public static void deleteNotiBean(Context context, MessageInfo appInfo) {
        List<MessageInfo> messageInfos = getNotiList(context);
        if (messageInfos.isEmpty()) {
            saveNotiList(context, "");
            return;
        }
        for (int i = 0; i < messageInfos.size(); i++) {
            if (messageInfos.get(i).getPackageName().equals(appInfo.getPackageName())) {
                messageInfos.remove(i);
                if (messageInfos.isEmpty()) {
                    saveNotiList(context, "");
                } else {
                    saveNotiList(context, GsonUtils.beanToJSONString(messageInfos));
                }
                break;
            }
        }
    }


    public static void saveNotiBean(Context context, AppInfo appInfo) {
        List<MessageInfo> messageInfos = getNotiList(context);
        boolean isAdd = true;
        for (int i = 0; i < messageInfos.size(); i++) {
            if (messageInfos.get(i).getPackageName().equals(appInfo.getPackageName())) {
                messageInfos.get(i).setName(appInfo.getName());
                messageInfos.get(i).setCode(appInfo.getCode());
                messageInfos.get(i).setRemark(appInfo.getRemark());
                isAdd = false;
                break;
            }
        }
        if (isAdd) {
            messageInfos.add(MessageInfo.AppInfoToMessageInfo(appInfo));
        } else {
            // 更新时也要同步 bankInfoId
            for (int i = 0; i < messageInfos.size(); i++) {
                if (messageInfos.get(i).getPackageName().equals(appInfo.getPackageName())) {
                    messageInfos.get(i).setBankInfoId(appInfo.getBankInfoId());
                    break;
                }
            }
        }
        saveNotiList(context, GsonUtils.beanToJSONString(messageInfos));
    }


    public static AppInfo getAppInfoByNotiList(Context context, AppInfo appInfo) {
        List<MessageInfo> messageInfos = getNotiList(context);
        for (int i = 0; i < messageInfos.size(); i++) {
            if (messageInfos.get(i).getPackageName().equals(appInfo.getPackageName())) {
                appInfo.setName(messageInfos.get(i).getName());
                appInfo.setCode(messageInfos.get(i).getCode());
                appInfo.setRemark(messageInfos.get(i).getRemark());
                appInfo.setBankInfoId(messageInfos.get(i).getBankInfoId());
                return appInfo;
            }
        }
        return appInfo;
    }


    public static MessageInfo getMessageByNotiList(Context context, String packageName) {
        List<MessageInfo> messageInfos = getNotiList(context);
        for (int i = 0; i < messageInfos.size(); i++) {
            if (messageInfos.get(i).getPackageName().equals(packageName)) {
                return messageInfos.get(i);
            }
        }
        return null;
    }

    // ========== 重试队列持久化辅助方法 ==========

    public static void saveRetryQueue(Context context, String value) {
        SharedPreferences sp = context.getSharedPreferences("server", Activity.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.putString("retry_queue", value);
        editor.apply();
    }

    public static String getRetryQueue(Context context) {
        SharedPreferences sp = context.getSharedPreferences("server", Activity.MODE_PRIVATE);
        return sp.getString("retry_queue", "");
    }

    public static void saveUploadedCount(Context context, int count) {
        SharedPreferences sp = context.getSharedPreferences("server", Activity.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.putInt("uploaded_count", count);
        editor.apply();
    }

    public static int getUploadedCount(Context context) {
        SharedPreferences sp = context.getSharedPreferences("server", Activity.MODE_PRIVATE);
        return sp.getInt("uploaded_count", 0);
    }

}
