package cn.axzo.msg.center.notices.client.aspect;

import cn.axzo.msg.center.notices.client.annotation.PlatCheckSign;
import cn.axzo.msg.center.notices.common.enums.ReturnCodeEnum;
import cn.axzo.msg.center.notices.common.exception.BizException;
import cn.hutool.crypto.SecureUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

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

@Slf4j
@Aspect
@Order(1)
@Component
public class PlatCheckSignAspect {

	private static final String appKey = "msg-center";

	// mns-plat 32位小写
	private static final String appSecret = "dd744893b1a3470269d0f687961ed3b2";

	@Pointcut(value = "@annotation(org.springframework.web.bind.annotation.RequestMapping)")
	public void requestMapping() {
	}

	@Pointcut(value = "@annotation(org.springframework.web.bind.annotation.PostMapping)")
	public void postMapping() {
	}

	@Pointcut(value = "@annotation(org.springframework.web.bind.annotation.GetMapping)")
	public void getMapping() {
	}

	@Pointcut(value = "@annotation(org.springframework.web.bind.annotation.PutMapping)")
	public void putMapping() {
	}

	@Pointcut(value = "@annotation(org.springframework.web.bind.annotation.DeleteMapping)")
	public void deleteMapping() {
	}

	@Pointcut(value = "@annotation(org.springframework.web.bind.annotation.PatchMapping)")
	public void patchMapping() {
	}

	@Pointcut("requestMapping() || postMapping() || getMapping() || putMapping() || deleteMapping()|| patchMapping()")
	public void mappingAnnotations() {
	}

	/**
	 * 切入含有@PlatCheckSign && @RestController 注解的类
	 */
	@Before(value = "@within(platCheckSign) && @within(restController)")
	public void classHandler(JoinPoint joinPoint, PlatCheckSign platCheckSign, RestController restController) {
		handle(joinPoint, platCheckSign);
	}

	/**
	 * 切入含有@PlatCheckSign && @RequestMapping/@PostMapping/@GetMapping/@PutMapping/@DeleteMapping/@PatchMapping 之一注解的方法
	 */
	@Before(value = "@annotation(platCheckSign) && mappingAnnotations()")
	public void methodHandler(JoinPoint joinPoint, PlatCheckSign platCheckSign) {
		handle(joinPoint, platCheckSign);
	}

	@SneakyThrows
	public void handle(JoinPoint joinPoint, PlatCheckSign platCheckSign) {
		// 验签
		sign();
	}

	private void sign() {
		HttpServletRequest httpRequest = ((ServletRequestAttributes) Objects
				.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
		String reqAppKey = httpRequest.getHeader("appKey");
		String reqBusinessNo = httpRequest.getHeader("businessNo");
		String reqTimestamp = httpRequest.getHeader("timestamp");
		String reqSign = httpRequest.getHeader("sign");

		if(!StringUtils.equals(appKey, reqAppKey)){
			throw new BizException(ReturnCodeEnum.FAIL,"验签失败");
		}
		String msg = "appKey=" + reqAppKey + "&appSecret="+ appSecret + "&businessNo=" + (reqBusinessNo == null ? "" : reqBusinessNo)  + "&timestamp=" + reqTimestamp;
		log.info(msg);
		String checkSign = SecureUtil.md5(msg);
		log.info(checkSign);
		if(!StringUtils.equals(checkSign, reqSign)){
			throw new BizException(ReturnCodeEnum.FAIL,"验签失败");
		}
	}
}
