package com.skr.mdm.aop;

import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import cn.hutool.crypto.symmetric.SM4;
import cn.hutool.json.JSONUtil;
import com.skr.mdm.enums.MdmEncryptEnum;
import com.skr.mdm.util.SmUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * @author nfq
 * @date 2022-09-18 9:13
 */
@Component
@Aspect
@Slf4j
public class DecryptHandler {

    @Value("${mdm.encrypt}")
    private String mdmEncrypt;

    /**
     * 请求参数解密处理
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("execution(* com.skr.mdm.controller..*.*(..))")
    public Object paramDecrypt(ProceedingJoinPoint point) throws Throwable {
        if (MdmEncryptEnum.SM.getMdmEncrypt().equals(mdmEncrypt)) {
            HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(
                    RequestContextHolder.getRequestAttributes())).getRequest();
            SM4 sm4 = null;
            String secretKey = request.getHeader("secretKey");
            log.debug("secretKey:{}", secretKey);
            if (StringUtils.isNotBlank(secretKey)) {
                SM2 sm2 = SmUtils.sm2Sign();
                byte[] secretKeyBytes = sm2.decrypt(secretKey, KeyType.PrivateKey);
                log.debug("secretKeyBytes长度：{}", secretKeyBytes.length);
                sm4 = SmUtil.sm4(secretKeyBytes);
            }
            Object[] args = point.getArgs();
            if (sm4 != null) {
                for (int i = 0; i < args.length; i++) {
                    if (args[i] == null) {
                        continue;
                    }
                    if (args[i] instanceof MultipartFile) {
                        continue;
                    }
                    if (args[i] instanceof Authentication) {
                        continue;
                    }
                    log.debug("请求地址：{} 解密前参数：{}", request.getRequestURI(), JSONUtil.toJsonStr(args));
                    args[i] = sm4.decryptStr(args[i].toString());
                    log.debug("请求地址：{} 解密后参数：{}", request.getRequestURI(), JSONUtil.toJsonStr(args));
                }
            }
            return point.proceed(args);
        }
        return point.proceed();
    }
}
