package com.yc.ship.module.trade.framework.web;

import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import com.yc.ship.module.trade.framework.annotation.RequestDecryption;
import com.yc.ship.module.trade.utils.StreamUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;

import static com.yc.ship.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.yc.ship.module.trade.enums.ErrorCodeConstants.ORDER_DECRYPTION_EXCEPTION;


/**
 * &#064;Description ：请求体解密
 * &#064;Author ：qsl
 * &#064;Date ：2025/9/9 15:04
 */
@ControllerAdvice
@Slf4j
public class DecryptRequestBodyAdvice implements RequestBodyAdvice {

    @Value("${huilv.trade.private-key}")
    public String privateKey;
    @Override
    public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return methodParameter.hasMethodAnnotation(RequestDecryption.class);
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
        //暂时只使用一种加密逻辑，后期可根据注解参数进行配置
        String encryptBody = StreamUtils.readText(inputMessage.getBody());
        //使用了此注解，就必须加密请求，不然就直接解密失败。
        //加密算法，先对文本进行base64编码，然后再用RSA加密
        try {
            RSA rsa = new RSA(privateKey,null);
            String base64Body = rsa.decryptStr(encryptBody, KeyType.PrivateKey);
            String decryptBody = Base64.decodeStr(base64Body,"utf-8");
            return new HttpInputMessage() {
                @Override
                public InputStream getBody() throws IOException {
                    return new ByteArrayInputStream(decryptBody.getBytes("utf-8"));
                }

                @Override
                public HttpHeaders getHeaders() {
                    return inputMessage.getHeaders();
                }
            };
        }catch (Exception e){
            log.error("请求体解密失败",e);
            throw exception(ORDER_DECRYPTION_EXCEPTION);
        }
    }

    @Override
    public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        log.debug("解密后报文:{}",body);
        return body;
    }

    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return body;
    }

}
