package com.skr.mdm.util;

import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.SM2;
import com.skr.mdm.authentication.user.IllegalUserRequestException;
import com.skr.mdm.authentication.user.UserTokenHandler;
import com.skr.mdm.constant.RequestHeaderConstants;
import com.skr.mdm.dto.LoginUserDTO;
import io.netty.handler.codec.http.FullHttpRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;


/**
 * @author nfq
 * @date 2020/7/27 16:28
 */
@Slf4j
@Component
public class WsAntiReplayUtil {

    @Value("${request.expire.seconds}")
    private Long requestExpire;
    @Value("${request.secret}")
    private String secret;

    private final String nonceParameter = RequestHeaderConstants.REQUEST_HEADER_NONCE;
    private final String timestampHeaderParameter = RequestHeaderConstants.REQUEST_HEADER_TIMESTAMP;
    private final String signParameter = RequestHeaderConstants.REQUEST_HEADER_SIGN;
    private final String tokenParameter = RequestHeaderConstants.REQUEST_HEADER_TOKEN;

    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private UserTokenHandler userTokenHandler;

    /**
     * 防重放检查
     * @param request
     */
    public LoginUserDTO antiReplay(FullHttpRequest request) {

        String token = request.headers().get(this.tokenParameter);

        String nonce = request.headers().get(this.nonceParameter);
        String timestampParameter = request.headers().get(this.timestampHeaderParameter);
        String sign = request.headers().get(this.signParameter);
        if (StringUtils.isBlank(token) || StringUtils.isBlank(nonce) || StringUtils.isBlank(timestampParameter) || StringUtils.isBlank(sign)) {
            log.warn("请求头内容不完整：token：{} nonce：{} timestampParameter：{} sign：{}", token, nonce, timestampParameter, sign);
            throw new IllegalUserRequestException();
        }
        long timestamp = Long.parseLong(timestampParameter);
//        long expireTime = requestExpire * 1000L;
//        boolean flag = timestamp > System.currentTimeMillis() && (timestamp - System.currentTimeMillis()) > requestExpire * 1000;
//        if (flag || (System.currentTimeMillis() - timestamp) > expireTime) {
//            log.warn("请求超时:{}", timestamp);
//            throw new IllegalRequestException();
//        }
        // 校验签名
        String data = timestamp + nonce + secret;
        String sm3 = SmUtil.sm3(data);
        SM2 sm2 = SmUtils.sm2Crypt();
        if (!sm2.verifyHex(sm3, sign)) {
            // 请求被篡改，拒绝访问
            log.warn("websocket验签错误:{}", sign);
            throw new IllegalUserRequestException();
        }
        // 校验随机数
//        if (redisUtils.get(RedisGetKeyUtil.getAdminQuestNonceKey(nonce)) != null) {
//            // 随机数重复，拒绝访问
//            log.warn("随机数重复:{}", nonce);
//            throw new IllegalUserRequestException();
//        }
        // 随机值放入缓存
//        redisUtils.set(RedisGetKeyUtil.getAdminQuestNonceKey(nonce), nonce, requestExpire);

        LoginUserDTO loginUser = null;
        loginUser = userTokenHandler.getLoginUserByJwt(token);
        if (loginUser == null) {
            log.warn("客户端websocket连接认证失败");
        }
        return loginUser;
    }

}
