package com.iformall.utils;

import com.alibaba.fastjson.JSONObject;
import com.iformall.common.ErrorCode;
import com.iformall.domain.po.WxWiWideInfo;
import com.iformall.exception.MallinkException;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.codec.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class WiwideUtil {
    private static final Logger logger = LoggerFactory.getLogger(WiwideUtil.class);

    private static final String addTemplateUrl = "https://webapp.wiwide.com/apisms/addtemplate";
    private static final String smsSendUrl = "https://webapp.wiwide.com/apisms/send";

    public static String addTemplate(String secret, String bid, String publickey, String signature, String content, String notifyUrl, String verifysms) {
        //请求api数据排序
        TreeMap<String, String> message = new TreeMap<>();
        message.put("bid", bid);
        message.put("signature", signature);
        message.put("content", content);
        message.put("notify_url", notifyUrl);
        message.put("verifysms", verifysms);

        StringBuilder sb = new StringBuilder();
        Set<Map.Entry<String, String>> entries = message.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            sb.append(entry.getKey()).append("=").append(entry.getValue());
        }
        sb.append("&secret=").append(secret);
        String sign = HMACSHA256.sha256_HMAC(sb.toString(), secret);
        message.put("sign", sign.toUpperCase());
        logger.debug(message.toString());

        String str32 = HMACSHA256.STR2;
        String iv = HMACSHA256.IV;

        Map<String, String> params = new HashMap<>();
        params.put("iv", iv);
        params.put("bid", bid);
        try {
            String data = AesUtil.AESEncode(str32, JSONObject.toJSONString(message), iv);
            String sc = RsaUtil.RSAEncode(str32.getBytes(), publickey);
            params.put("data", data);
            params.put("sc", sc);
        } catch (Exception e) {
            logger.info("短信AES/RSA解密失败");
            throw new MallinkException(ErrorCode.TEMPLATE_SEND_FAILED);
        }

        String requestUrl = addTemplateUrl;
        return HttpUtil.doPost(requestUrl, params);
    }

    public static String sendMsg(String secret, String bid, String publickey,
                                 String phone, String signature, String msg, String notifyUrl, String verifysms, Integer modelId) {
        TreeMap<String, Object> message = new TreeMap<>();
        message.put("bid", bid);
        message.put("phone", phone);
        message.put("signature", signature);
        message.put("msg", msg);
        message.put("notify_url", notifyUrl);
        message.put("verifysms", verifysms);
        if (modelId != null) {
            message.put("model_id", modelId);
        }
        StringBuilder sb = new StringBuilder();
        Set<Map.Entry<String, Object>> entries = message.entrySet();
        for (Map.Entry<String, Object> entry : entries) {
            sb.append(entry.getKey()).append("=").append(entry.getValue());
        }
        sb.append("&secret=").append(secret);
        String sign = HMACSHA256.sha256_HMAC(sb.toString(), secret);
        message.put("sign", sign.toUpperCase());
        logger.debug(message.toString());

        String str32 = HMACSHA256.STR2;
        String iv = HMACSHA256.IV;

        Map<String, String> params = new HashMap<>();
        params.put("iv", iv);
        params.put("bid", bid);

        try {
            String data = AesUtil.AESEncode(str32, JSONObject.toJSONString(message), iv);
            String sc = RsaUtil.RSAEncode(str32.getBytes(), publickey);
            params.put("data", data);
            params.put("sc", sc);
        } catch (Exception e) {
            logger.info("短信AES/RSA解密失败");
            throw new MallinkException(ErrorCode.MSG_SEND_ERROR);
        }

        String requestUrl = smsSendUrl;
        return HttpUtil.doPost(requestUrl, params);
    }

    public static String encrypt(String key) {
        String data = System.currentTimeMillis() / 1000 + 30 + "";
        String md5 = HashUtil.md5(key);
        int x = 0;
        int len = data.length();
        int l = md5.length();
        char[] datachar = new char[len];
        for (int i = 0; i < len; i++) {
            if (x == l) {
                x = 0;
            }
            datachar[i] = md5.charAt(x);
            x++;
        }

        StringBuilder chars = new StringBuilder();
        for (int i = 0; i < len; i++) {
            int a = data.charAt(i);
            int b = (datachar[i] % 256);
            char v = (char) (a + b);
            chars.append(v);
        }

        byte[] bytes = null;
        try {
            bytes = chars.toString().getBytes("ISO-8859-1");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Base64.encodeToString(bytes);

    }

    public static String queryToken(WxWiWideInfo wiWideInfo) {
        logger.info("获取TOKEN");
        String username = wiWideInfo.getWiwideId();
        String authVal = WiwideUtil.encrypt(wiWideInfo.getWiwideKey());
        if(StringUtils.isEmpty(username)){
            logger.error("商场:" + wiWideInfo.getTenantId() + ",wiwideId为空" );
            return null;
        }

        if(StringUtils.isEmpty(authVal)){
            logger.error("商场:" + wiWideInfo.getTenantId() + ",wiwideKey为空" );
            return null;
        }

        Map<String, String> params = new HashMap<>(2);
        params.put("username", username);
        params.put("authVal", authVal);
        String wiwideUrl = wiWideInfo.getWiwideUrl();
        String token = HttpUtil.doPost(wiwideUrl + "/login/auth", params);
        logger.info("商场:" + wiWideInfo.getTenantId() + ",返回TOKEN" + token);
        return token;
    }

    public static String queryData(WxWiWideInfo wiWideInfo, String token, Map<String, String> params) {

        String data = HttpUtil.doPostWiwide(wiWideInfo.getWiwideUrl() + "/reports/data", token, params);
        return data;
    }
}
