package com.pj.usersync;

import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.util.SaFoxUtil;
import com.dtflys.forest.Forest;
import com.pj.utils.JsonUtil;
import com.pj.utils.Sm4Util;
import com.pj.utils.SoMap;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

/**
 * 用户同步工具类，向 Ssp-Server 推送数据
 *
 * @author kong
 * @since 2022-11-22
 */
@Slf4j
public class SspClientBrdUtil {

    /** 是否打开: 向 ssp-server 推送数据  */
    public static final boolean isPush = true;

    /** Ssp-Server 接口地址 */
    public static final String SSP_SERVER_ADDRESS = "http://127.0.0.1:9000";

    /** 添加用户接口 */
    public static final String PUSH_USER_ADD = "/ssp/listen/user/add";

    /** 删除用户接口 */
    public static final String PUSH_USER_DELETE = "/ssp/listen/user/delete";

    /** 修改用户资料 */
    public static final String PUSH_USER_UPDATE = "/ssp/listen/user/update";

    /** 修改用户密码 */
    public static final String PUSH_USER_UPDATE_PASSWORD = "/ssp/listen/user/updatePassword";

    /** 查询用户信息 */
    public static final String PUSH_USER_GET = "/ssp/listen/user/get";

    /** 接口签名秘钥 */
    public static final String signKey = "YQfyZtAmDbYHTBaHPSx3GZeX7x2ip7ik";

    /** SM4数据加密秘钥 */
    public static final String sm4Key = "uYdc58GHjd4TjsHe";

    /** 是否采用 SM4 算法加密推送的数据 */
    public static final boolean isBrdEncrypt = true;



    // 推送：添加一个用户
    public static void userAdd(SoMap dataMap) {

        // 如果尚未打开推送开关，则直接退出
        if(isPush == false) {
            return;
        }

        // 推送
        pushData(PUSH_USER_ADD, dataMap);
    }

    // 推送：删除一个用户
    public static void userDelete(long id) {

        // 如果尚未打开推送开关，则直接退出
        if(isPush == false) {
            return;
        }

        // 构建 Data 对象
        SoMap dataMap = SoMap.getSoMap()
                .set("id", id);

        // 推送
        pushData(PUSH_USER_DELETE, dataMap);
    }

    // 推送：修改一个用户
    public static void userUpdate(SoMap dataMap) {

        // 如果尚未打开推送开关，则直接退出
        if(isPush == false) {
            return;
        }

        // 推送
        pushData(PUSH_USER_UPDATE, dataMap);
    }

    // 推送：指定用户修改了密码
    public static void userUpdatePassword(long id, String password) {

        // 如果尚未打开推送开关，则直接退出
        if(isPush == false) {
            return;
        }

        // 构建 Data 对象
        SoMap dataMap = SoMap.getSoMap()
                .set("id", id)
                .set("password", password);

        // 推送
        pushData(PUSH_USER_UPDATE_PASSWORD, dataMap);
    }

    // 推送：查询用户信息
    public static SoMap userGet(long id) {

        // 如果尚未打开推送开关，则直接退出
        if(isPush == false) {
            return null;
        }

        // 构建 Data 对象
        SoMap dataMap = SoMap.getSoMap()
                .set("id", id);

        // 推送
        return pushData(PUSH_USER_GET, dataMap);
    }


    // -----------------

    /**
     * 向 Ssp-Server 推送数据
     *
     * @param apiPath 推送接口地址
     * @param dataMap 推送的数据 Map
     */
    public static SoMap pushData(String apiPath, Map<String, Object> dataMap) {

        /*
         * 构建请求参数Map，形如：
         * {
         * 		data: "230ef68683b7fa2c5c1eabb9249412d",   // 数据字符串, SM4加密
         * 		timestamp: "1668965686992",   // 时间戳，13位，String格式
         * 		nonce: "WaetF4SEtSCaRXAIHmMGFvH0qAAyS7KW",   // 随机字符串,32位
         * 		sign: "5acdde80919b9cba08bcc2cc2d997192"   // 签名字符串，防篡改、防重放
         * }
         */
        SoMap paramMap = SoMap.getSoMap();

        // s1、数据 Map 转 JSON 串
        String dataJson = JsonUtil.toJsonString(dataMap);

        // s2、SM4 加密
        String dataStr = dataJson;
        if(isBrdEncrypt) {
            dataStr = Sm4Util.encrypt(dataJson, sm4Key);
        }

        // s3、写入参数Map
        paramMap.set("data", dataStr);

        // s4、给 参数Map 增加 sign 等参数，防篡改、防重放
        SaManager.getSaSignTemplate().addSignParams(paramMap, signKey);

        // s5、参数Map 转 参数字符串，形如：data=xxx&nonce=xxx&timestamp=xxx&sign=xxx
        String paramStr = SaManager.getSaSignTemplate().joinParams(paramMap);

        // ------------------------ 开始向 Ssp-Server 推送

        // 发送请求
        String fullUrl = SaFoxUtil.spliceTwoUrl(SSP_SERVER_ADDRESS, apiPath);
        try {
            String resBody = Forest.post(fullUrl).addBody(paramStr).executeAsString();

            // 判断结果
            SoMap resMap = SoMap.getSoMap().setJsonString(resBody);
            if(200 == resMap.getInt("code") && "ok".equals(resMap.getString("msg"))){
                log.info("数据推送成功({}) data={}", fullUrl, dataJson);
                return resMap;
            } else {
                throw new RuntimeException(resMap.getString("msg"));
            }
        } catch (Exception e) {
            log.info("数据推送失败({}) data={}", fullUrl, dataJson);
            throw new RuntimeException("数据推送失败：" + e.getMessage(), e);
        }



    }


}
