package com.codvision.logcore.aop;

import cn.hutool.json.JSONUtil;
import com.codvision.authcore.bean.SysUserBean;
import com.codvision.authcore.util.AuthUtil;
import com.codvision.commoncore.utils.NetworkUtils;
import com.codvision.logcore.annotation.MyLog;
import com.codvision.logcore.bean.SysLogMessage;
import com.codvision.mqcore.service.MQSender;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author: huxb
 * @description: 系统日志记录类
 * @program: gongshu_command_platform_server
 * @creat: 2020-04-27 14:43
 **/
@Aspect
public class SysLogAspect {

    public static final String SYS_LOG_QUEUE_NAME = "SYS-LOG-QUEUE";

    @Resource
    private MQSender mqSender;


    //定义切点 @Pointcut
    //在注解MyLog的位置切入代码
    @Pointcut("@annotation(com.codvision.logcore.annotation.MyLog)")
    private void logPointCut() {

    }


    @AfterReturning(value = "logPointCut()", returning = "obj")
    public void saveSysLog(JoinPoint joinpoint, Object obj) throws IOException {
        SysLogMessage sysLog = new SysLogMessage();
        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature methodSignature = (MethodSignature) joinpoint.getSignature();
        //获取切入点所在的方法
        Method method = methodSignature.getMethod();
        //获取操作
        MyLog myLog = method.getAnnotation(MyLog.class);
        if (myLog != null) {
            String value = myLog.value();
            sysLog.setContent(value);
        }
        if (null != obj) {
            sysLog.setCode(obj.toString());
        }
        //获取请求的类名
        String className = joinpoint.getTarget().getClass().getName();
        //获取请求的方法名
        String methodName = method.getName();
        sysLog.setMethod(className + "." + methodName);

        //将参数所在的数组转换成json,设置请求参数
        Object[] args = joinpoint.getArgs();
        //joinPoint.getArgs()返回的数组中携带有Request或者Response对象，导致序列化异常
        Stream<?> stream = ArrayUtils.isEmpty(args) ? Stream.empty() : Arrays.asList(args).stream();
        List<Object> logArgs = stream
                .filter(arg -> (!(arg instanceof HttpServletRequest) && !(arg instanceof HttpServletResponse) && !(arg instanceof MultipartFile)))
                .collect(Collectors.toList());
        String param = JSONUtil.toJsonStr(logArgs);
        sysLog.setParams(param);

        //获取用户ip地址
        // 接收到请求，记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (null != attributes) {
            HttpServletRequest request = attributes.getRequest();
            HttpSession session = request.getSession();
            SysUserBean user = AuthUtil.getCurrentUser();
            if (user != null) {
                sysLog.setOperator(user.getLoginName());
                sysLog.setOperatorUid(Math.toIntExact(user.getId()));
            }
            sysLog.setIp(NetworkUtils.getIpAddress(request));
        }

        sysLog.setType("系统操作日志");

        mqSender.sendMessage(SYS_LOG_QUEUE_NAME, sysLog);
    }

}
