package com.chinaweal.aiccs.outside.util;

import cn.hutool.core.util.XmlUtil;
import com.alibaba.fastjson.JSON;
import com.chinaweal.aiccs.outside.vo.DoorTask;
import com.dtflys.forest.http.ForestRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.util.encoders.Hex;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
import org.w3c.dom.Document;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 服务网关token生成
 */
@Slf4j
public class GzcssTokenUtils {

    // 统一门户账号秘钥
    private final static String APPID = "xyjgSystem";
    private final static String SECRET = "2Moreed1";

    // 信创门户账号秘钥
    public final static String APPID_XC = "xyjg";
    private final static String SECRET_XC = "63869804635ef931bedbec1814e8ef17";

    /**
     * 生成签名token
     *
     * @param appId  系统id
     * @param secret 系统密钥
     * @return 签名token
     */
    public static String getToken(String appId, String secret, Long timestamp, String nonce) {
        Map<String, Object> payload = new LinkedHashMap<>();
        payload.put("appId", appId);//系统id
        payload.put("timestamp", timestamp);//签注时间
        payload.put("nonce", nonce);//随机数
        payload.put("secret", secret);//MD5加密明文密钥
        //顺序不可调换,JSON串的格式实例
        //{"appId":"9999","timestamp":1626934559872,"nonce":"a71b6c61-af07-458b-afce-15bfcec280ff","secret":"8b0075e9f9b80321913441a26ee199be"}
        return SM3Encode(JSON.toJSONString(payload));
    }

    public static String SM3Encode(String str) {
        byte[] md = new byte[32];
        byte[] msg1 = str.getBytes();
        SM3Digest sm3 = new SM3Digest();
        sm3.update(msg1, 0, msg1.length);
        sm3.doFinal(md, 0);
        return new String(Hex.encode(md));
    }

    /**
     * MD5加密，
     * Spring 环境可用 DigestUtils.md5DigestAsHex(secret.getBytes())代替
     *
     * @param s
     * @return
     */
    public static String MD5Encode(String s) {
        return DigestUtils.md5DigestAsHex(s.getBytes());
    }

    public static boolean isValid(String appId, Long timestamp, String nonce, String Md5Secret, String signature) {
        Map<String, Object> payload = new LinkedHashMap<>();
        payload.put("appId", appId);//系统id
        payload.put("timestamp", timestamp);//签注时间
        payload.put("nonce", nonce);//随机数
        payload.put("secret", Md5Secret);
        return StringUtils.equals(SM3Encode(JSON.toJSONString(payload)), signature);
    }


    /**
     * 设置请求头
     * @author ymc
     * @date 2022年6月25日 16:00
     * @param request
     * @return
     */
    public static void setForestRequestHeader(ForestRequest request) {
        Long timestamp = System.currentTimeMillis();
        String nonce = UUID.randomUUID().toString();

        Map<String, Object> payload = new LinkedHashMap<>();
        payload.put("appId", APPID);//系统id
        payload.put("timestamp", timestamp);//签注时间
        payload.put("nonce", nonce);//随机数
        payload.put("secret", SECRET);
        String signature = SM3Encode(JSON.toJSONString(payload));

        request.addHeader("appid", APPID);
        request.addHeader("nonce", nonce);
        request.addHeader("timestamp", timestamp);
        request.addHeader("signature", signature);
    }

    /**
     * 设置请求头 xc门户
     * @author ymc
     * @date 2023年1月6日 16:00
     * @param request
     * @return
     */
    public static void setForestRequestHeaderForXC(ForestRequest request) {
        Long timestamp = System.currentTimeMillis();
        String nonce = UUID.randomUUID().toString();

        Map<String, Object> payload = new LinkedHashMap<>();
        payload.put("appId", APPID_XC);//系统id
        payload.put("timestamp", timestamp);//签注时间
        payload.put("nonce", nonce);//随机数
        payload.put("secret", SECRET_XC);
        String signature = SM3Encode(JSON.toJSONString(payload));

        request.addHeader("appid", APPID_XC);
        request.addHeader("nonce", nonce);
        request.addHeader("timestamp", timestamp);
        request.addHeader("signature", signature);
    }

    /**
     * 过滤、封装CAS单点登录票据校验数据
     * @author ymc
     * @date 2022年6月28日 14:17
     * @param xml
     * @return
     */
    public static Map<String, String> parseCasXmlInfo(String xml) {
        Map<String, String> resultMap = new HashMap<>();

        Document document = XmlUtil.parseXml(xml);
        // success
        if (XmlUtil.elementText(document.getDocumentElement(), "cas:authenticationFailure") == null) {
            resultMap.put("code", "1");
            resultMap.put("data", XmlUtil.elementText(document.getDocumentElement(), "cas:authenticationSuccess").trim());
        } else { // error
            resultMap.put("code", "0");
            resultMap.put("data", XmlUtil.getElement(document.getDocumentElement(), "cas:authenticationFailure").getAttribute("code"));
            log.error("统一门户CAS票据校验失败, {}", XmlUtil.elementText(document.getDocumentElement(), "cas:authenticationFailure"));
        }

        return resultMap;
    }

    /**
     * 封装统一门户待办数据
     * @author ymc
     * @date 2022年6月28日 20:10
     * @param taskId
     * @param busName
     * @param linkName
     * @param createUserId
     * @param receiveUserId
     * @return
     */
    public static DoorTask getDoorTask(String taskId, String busName, String linkName, String createUserId, String receiveUserId, String redirectUrl, boolean isEnd) {
        return new DoorTask()
                .setTaskId(taskId)
                .setTitle(busName)
                .setContent(linkName)
                .setCreateUserId(createUserId)
                .setReceiveUserId(receiveUserId)
                .setAppId(APPID)
                .setUrgency("1")
                .setRedirectType("1")
                .setRedirectUrl(redirectUrl)
                .setStatus(isEnd ? "2" : "1");
    }

    /**
     * 封装信创门户待办数据
     * @author ymc
     * @date 2023年1月10日 17:20
     * @param taskId
     * @param busName
     * @param linkName
     * @param createUserId
     * @param receiveUserId
     * @return
     */
    public static DoorTask getDoorTask_XC(String taskId, String busName, String linkName, String createUserId, String receiveUserId, String redirectUrl, boolean isEnd) {
        return new DoorTask()
                .setTaskId(taskId)
                .setTitle(busName)
                .setContent(linkName)
                .setCreateUserId(createUserId)
                .setReceiveUserId(receiveUserId)
                .setAppId(APPID_XC)
                .setUrgency("1")
                .setRedirectType("1")
                .setRedirectUrl(redirectUrl)
                .setStatus(isEnd ? "2" : "1");
    }



    public static void main(String[] args) throws Exception {
        String appId = APPID;//appid
        String secret = SECRET;//appSecret
        Long timestamp = System.currentTimeMillis();
        String nonce = "b38c11c1-2675-4fbb-941b-25bf681226f9";
        System.out.println(nonce);
        System.out.println(timestamp);
        Map<String, Object> payload = new LinkedHashMap<>();
        payload.put("appId", appId);//系统id
        payload.put("timestamp", timestamp);//签注时间
        payload.put("nonce", nonce);//随机数
        payload.put("secret", secret);
        String signature = SM3Encode(JSON.toJSONString(payload));
        System.out.println(signature);
        //生成 token
//        System.out.println("签名有效:" + isValid(appId, timestamp, nonce, secret, signature));
    }
}