package org.springblade.thirdparty.wps.interceptor;

import feign.RequestInterceptor;
import feign.RequestTemplate;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.tool.utils.CollectionUtil;
import org.springblade.core.tool.utils.DigestUtil;
import org.springblade.thirdparty.wps.config.WpsProperties;
import org.springblade.thirdparty.wps.constant.WpsConstant;
import org.springblade.thirdparty.wps.exception.WpsException;
import org.springframework.util.StringUtils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

/**
 *  wps请求拦截器
 * @author bfhuange
 * @date 2024/10/30
 */
@Slf4j
@AllArgsConstructor
public class WpsRequestInterceptor implements RequestInterceptor {

    private final WpsProperties wpsProperties;

    @Override
    public void apply(RequestTemplate template) {
        //获取uri路径
        String path = template.path();
        if(StringUtils.hasText(template.queryLine())) {
            path = path + template.queryLine();
        }

        //获取Content-type，“application/json"
        Collection<String> contentTypes = template.headers().get("Content-Type");
        String contentType = CollectionUtil.isEmpty(contentTypes) ? "" : contentTypes.iterator().next();

        //日期格式化
        DateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = dateFormat.format(new Date());

        //open不参与签名，做替换处理
        if (path.startsWith("/open")) {
            path = path.replace("/open", "");
        }

        String sha256body;

        //body为空则为空，否则返回sha256(body)
        byte[] body = template.body();
        if (body != null && body.length > 0) {
            sha256body = this.getSHA256StrJava(body);
        } else {
            sha256body = "";
        }

        //hmac-sha256(secret_key, Ver + HttpMethod + URI + Content-Type + Wps-Date + sha256(HttpBody))
        String signature = null;
        try {
            signature = DigestUtil.hmacSha256Hex(WpsConstant.SIGN_METHOD + template.method().toUpperCase(Locale.ROOT) + path + contentType + date + sha256body, wpsProperties.getSecretKey());
        } catch (Exception e) {
            log.error("签名异常", e);
            throw new WpsException("请求签名异常");
        }

        template.header(WpsConstant.DATE_HEADER, date);
        template.header(WpsConstant.AUTHORIZATION_HEADER, String.format(WpsConstant.SIGN_METHOD + " %s:%s", wpsProperties.getAccessKey(), signature));
    }

    /**
     * 利用java原生的摘要实现SHA256加密
     * @param str 加密后的报文
     * @return
     */
    public String getSHA256StrJava(byte[] str){
        MessageDigest messageDigest;
        String encodeStr = "";
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(str);
            encodeStr = byte2Hex(messageDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            log.error("加密异常", e);
            throw new WpsException("加密异常");
        }
        return encodeStr;
    }

    /**
     * 将byte转为16进制
     * @param bytes
     * @return
     */
    private static String byte2Hex(byte[] bytes){
        StringBuilder builder = new StringBuilder();
        String temp = null;
        for (byte aByte : bytes) {
            temp = Integer.toHexString(aByte & 0xFF);
            if (temp.length() == 1) {
                //1得到一位的进行补0操作
                builder.append("0");
            }
            builder.append(temp);
        }
        return builder.toString();
    }
}
