package com.yiboshi.science.config.aspect;

import com.alibaba.fastjson.JSON;
import com.yiboshi.science.config.annotation.Logs;
import com.yiboshi.science.config.security.SecurityUserHolder;
import com.yiboshi.science.entity.LogsOperation;
import com.yiboshi.science.enumeration.CommonEnum;
import com.yiboshi.science.service.LogsExceptionService;
import com.yiboshi.science.service.LogsLoginService;
import com.yiboshi.science.service.LogsOperationService;
import com.yiboshi.science.utils.CustomerIPAddress;
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.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * class: 系统日志切面
 * create by: dracula$
 * description:
 * create time: 2021-09-14$
 *
 * @param: $
 */
@Aspect
@Component
public class LogAspect {

    @Autowired
    private LogsLoginService logsLoginService;

    @Autowired
    private LogsOperationService logsOperationService;

    @Autowired
    private LogsExceptionService logsExceptionService;

    //定义切点 @Pointcut
    //在注解的位置切入代码
    @Pointcut("@annotation(com.yiboshi.science.config.annotation.Logs)")
    public void logPointCut() {
    }

    //切面 配置通知
    @AfterReturning("logPointCut()")
    public void saveSysLog(JoinPoint joinPoint) {
        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        //从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
//        //获取请求的类名
//        String className = joinPoint.getTarget().getClass().getName();
//        //获取请求的方法名
//        String methodName = method.getName();
//        //类名方法名
//        methodName = className + "." + methodName;
        //请求的参数
        Object[] args = joinPoint.getArgs();
        //将参数所在的数组转换成json
        String params = JSON.toJSONString(args[0]);
        String logParams = "参数:{" + params + "}";
        Logs logs = method.getAnnotation(Logs.class);
        if (logs != null) {
            CommonEnum.logType logType = logs.value();
            String userId = null;
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication != null && authentication.isAuthenticated() && !(authentication instanceof AnonymousAuthenticationToken)) {
                userId = SecurityUserHolder.getPersonId();
            }
            createOperationLog(request, userId, logType, logParams);
        }
    }

    /**
     * 创建操作日志
     *
     * @param request
     * @return
     */
    private void createOperationLog(HttpServletRequest request, String userId, CommonEnum.logType logType, String logParams) {
        LogsOperation log = new LogsOperation();
        log.setBrowser("");
        log.setCustomerId(userId);
        log.setIpAddress(CustomerIPAddress.getIPAddress(request));
        log.setLogParam(logParams);
        log.setLogKey(logType.getKey());
        log.setRequestUrl(request.getRequestURI());
        logsOperationService.insert(log);
    }
}
