package com.jeequan.jeepay.thirdparty.device.speaker.bsjSpeaker;

import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.device.BsjParams;
import com.jeequan.jeepay.core.model.device.PayOrderInfo4Device;
import com.jeequan.jeepay.core.utils.AmountUtil;
import com.jeequan.jeepay.core.utils.DateKit;
import com.jeequan.jeepay.core.utils.JeepayKit;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.TreeMap;

/**
 * @Author: ZhuXiao
 * @Description:
 * @Date: 18:20 2021/7/6
*/
@Slf4j
public class BsjUtil {

    /**
     * 发起get请求
     */
    public static JSONObject get(String reqUrl, BsjParams bsjParams, JSONObject reqParams) throws BizException {

        packageCommonParams(bsjParams, reqParams);

        // 发起请求
        log.info("博实结设备号：{}，请求参数：{}", bsjParams.getDeviceParams().getDeviceNo(), reqParams.toJSONString());
        String responseStr = HttpUtil.get(reqUrl, reqParams, 60000);
        log.info("博实结设备号：{}，返回结果：{}", bsjParams.getDeviceParams().getDeviceNo(), responseStr);

        if (StringUtils.isBlank(responseStr)) {
            throw new BizException("请求失败");
        }

        return JSONObject.parseObject(responseStr);
    }

    /**
     * 发起post请求
     */
    public static JSONObject post(String reqUrl, BsjParams bsjParams, JSONObject reqParams) throws BizException {

        // 添加公共参数
        packageCommonParams(bsjParams, reqParams);

        // 发起请求
        log.info("博实结设备号：{}，请求参数：{}", bsjParams.getDeviceParams().getDeviceNo(), reqParams.toJSONString());
        String responseStr = HttpUtil.post(reqUrl, reqParams, 60000);
        log.info("博实结设备号：{}，返回结果：{}", bsjParams.getDeviceParams().getDeviceNo(), responseStr);

        if (StringUtils.isBlank(responseStr)) {
            throw new BizException("请求失败");
        }

        return JSONObject.parseObject(responseStr);
    }

    /** 获取播报内容   bizType：1-交易语音  2-自定义语音   */
    public static JSONObject getSpeakData(String customContent, PayOrderInfo4Device payOrderInfo) {
        JSONObject voiceJson = new JSONObject();

        // 防逃单播报走自定义模式
        if (PayOrderInfo4Device.BOARD_TYPE_CANCEL.equals(payOrderInfo.getWayCodeType())) {
            voiceJson.put("bizType", "2");
            voiceJson.put("content", "客户取消付款" + AmountUtil.convertCent2Dollar(payOrderInfo.getAmount()) + "元");
            return voiceJson;
        }

        // 会员余额支付
        if (PayOrderInfo4Device.BOARD_TYPE_MEMBER.equals(payOrderInfo.getWayCodeType())) {
            voiceJson.put("bizType", "2");
            voiceJson.put("content", "会员余额支付" + AmountUtil.convertCent2Dollar(payOrderInfo.getAmount()) + "元");
            return voiceJson;
        }

        // 配置了自定义播报内容
        if (StringUtils.isNotBlank(customContent)) {
            voiceJson.put("bizType", "2");
            voiceJson.put("content", customContent + AmountUtil.convertCent2Dollar(payOrderInfo.getAmount())+ "元");
        }else {
            // 未配置 自定义播报内容，走默认播报语音
            voiceJson.put("bizType", "1");
            voiceJson.put("money", covertMoney(payOrderInfo.getAmount()));  // 金额
            voiceJson.put("broadCastType", getPayTypeCode(payOrderInfo.getWayCodeType()));  //1-收款成功   2-支付宝收款成功  3-微信收款成功
        }

        return voiceJson;
    }

    private static JSONObject packageCommonParams(BsjParams bsjParams, JSONObject reqParams) {
        reqParams.put("appId", bsjParams.getProviderParams().getAppId());
        reqParams.put("timestamp", DateKit.currentTimeMillis());
        reqParams.put("userCode", bsjParams.getProviderParams().getUserCode());
        reqParams.put("requestId", IdUtil.fastSimpleUUID());  //请求ID 唯一
        reqParams.put("token", getToken(reqParams, bsjParams.getProviderParams().getAppSecret()));
        reqParams.put("devName", bsjParams.getDeviceParams().getDeviceNo());  //设备名称  唯一

        return reqParams;
    }

    /**
     * 生成签名字符串
     */
    public static String getToken(JSONObject params, String appSecret) throws BizException {

        TreeMap<String, Object> tree = new TreeMap<>();

        // 1. 所有参数进行排序
        params.keySet().forEach(key -> {
            switch (key) {
                case "appId":
                case "requestId":
                case "timestamp":
                case "userCode":
                    tree.put(key, params.get(key));
                    break;
            }
        });

        //2. 拼接为 key=value&形式
        StringBuffer stringBuffer = new StringBuffer();
        tree.keySet().forEach(key -> {

            if (tree.get(key) == null) {
                return ;
            }
            if(StringUtils.isAnyEmpty(key, tree.get(key).toString())){ //空值， 不参与签名
                return ;
            }
            if("token".equals(key)){ //签名串， 不参与签名
                return ;
            }

            stringBuffer.append(key).append(tree.get(key).toString());
        });

        //3. 拼接appSecret
        String signStr = stringBuffer.append(appSecret).toString();
        log.info("博实结【待加签字符串】：{}", signStr);

        String md5 = JeepayKit.md5(signStr, "UTF-8");
        if (StringUtils.isBlank(md5)) {
            throw new BizException("博实结请求数据加密失败");
        }

        return md5.toUpperCase();
    }

    /**
     * 支付方式
     */
    public static String getPayTypeCode(String wayCodeType) {
        if (CS.PAY_WAY_CODE_TYPE.WECHAT.equals(wayCodeType)) { // 微信
            return "2";
        }else if (CS.PAY_WAY_CODE_TYPE.ALIPAY.equals(wayCodeType)) { // 支付宝
            return "3";
        }else if (CS.PAY_WAY_CODE_TYPE.YSFPAY.equals(wayCodeType)) { // 云闪付
            return "8";
        }else if (PayOrderInfo4Device.BOARD_TYPE_CANCEL.equals(wayCodeType)) {
            return "24";
        }else {
            return "1";
        }
    }

    /** 金额转元，并去掉多余0 */
    public static String covertMoney(Long amount) {
        return new BigDecimal(String.valueOf(amount)).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
    }

}
