package com.ruoyi.web.core.config;

import cn.hutool.core.codec.Base64;
import lombok.Builder;
import lombok.Data;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;

import java.math.BigInteger;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;

/**
 * lombok 1.16.16.
 */
public class GlobalLogHelper {

    @Data
    @Builder
    public static class UploadInfo {
        //info设备信息
        private String imei;
        private String oaid;
        private long convTime;
        private String clientIp;
        private String ua;
        private long adId;
        //conversion转化信息
        private long appId;
        private int customerId;
        private String convType;
        private String signKey;
        private String encryptKey;
        //生成的信息
        //最终url
        private String finalUrl;
        //最终生成的info
        private String finalInfo;
        //queryString 设备信息
        private String queryString;
        private String property;
        private String baseData;
        //md5后的sign值
        private String signature;

        private final static String HOST = "http://trail.e.mi.com";
        private final static String PATH = "/global/log";

        @SneakyThrows
        public UploadInfo genInfo() {
            List<String> kvParam = new ArrayList<>();
            if (StringUtils.isNotBlank(this.imei)) {
                kvParam.add("imei=" + URLEncoder.encode(this.imei, "UTF-8"));
            }
            if (StringUtils.isNotBlank(this.oaid)) {
                kvParam.add("oaid=" + URLEncoder.encode(this.oaid, "UTF-8"));
            }
            if (this.convTime > 0) {
                kvParam.add("conv_time=" + URLEncoder.encode(String.valueOf(this.convTime), "UTF-8"));
            }
            if (StringUtils.isNotBlank(this.clientIp)) {
                kvParam.add("client_ip=" + URLEncoder.encode(this.clientIp, "UTF-8"));
            }
            if (StringUtils.isNotBlank(this.ua)) {
                kvParam.add("ua=" + URLEncoder.encode(this.ua, "UTF-8"));
            }
            if (this.adId > 0) {
                kvParam.add("ad_id=" + URLEncoder.encode(String.valueOf(this.adId), "UTF-8"));
            }

            try {
                //1.按照顺序使用 & 拼接key=urlEncode(value),queryString
                this.queryString = String.join("&", kvParam);
                //2.按照顺序使用 & 拼接签名密钥signKey 和 urlEncode(queryString),得到property
                this.property = this.signKey + "&" + URLEncoder.encode(this.queryString, "UTF-8");
                //3. 将字符串(property) 进行md5(property)加密,得到32位小写字符串signature
                this.signature = getMd5Digest(this.property);
            } catch (Exception ignored) {

            }
            //4.按照顺序使用 & 拼接 queryString(注意是第一个步骤生成的) 和 sign=signature
            this.baseData = this.queryString + "&sign=" + this.signature;
            //5.baseData进行加密 Base64(simple_xor{base_data, encrypt_key}),得到info信息
            this.finalInfo = encrypt(this.baseData, this.encryptKey);
            this.finalUrl = HOST + PATH
                    + "?appId=" + URLEncoder.encode(String.valueOf(this.appId), "UTF-8")
                    + "&info=" + URLEncoder.encode(this.finalInfo, "UTF-8")
                    + "&conv_type=" + URLEncoder.encode(this.convType, "UTF-8")
                    + "&customer_id=" + URLEncoder.encode(String.valueOf(this.customerId), "UTF-8");

            return this;
        }

        //对baseData进行加密 Base64(simple_xor{base_data, encrypt_key})
        public static String encrypt(String info, String key) {
            try {
                if (StringUtils.isEmpty(info) || StringUtils.isEmpty(key)) {
                    return null;
                }
                //6.1 base_data, encrypt_key 异或加密
                char[] infoChar = info.toCharArray();
                char[] keyChar = key.toCharArray();

                byte[] resultChar = new byte[infoChar.length];
                for (int i = 0; i < infoChar.length; i++) {
                    resultChar[i] = (byte) ((infoChar[i] ^ keyChar[i % keyChar.length]) & 0xFF);
                }
                //6.2 Base64 编码
                return Base64.encode(resultChar);
            } catch (Exception e) {
                return null;
            }
        }

        //md5 加密得到32位小写字符串.
        public static String getMd5Digest(String pInput) {
            try {
                MessageDigest lDigest = MessageDigest.getInstance("MD5");
                lDigest.update(pInput.getBytes("UTF-8"));
                BigInteger lHashInt = new BigInteger(1, lDigest.digest());
                return String.format("%1$032x", lHashInt);
            } catch (Exception e) {

            }
            return "";
        }
    }

}