package com.sy.coinage.core.aop.aspect;

import com.alibaba.fastjson2.JSON;
import com.sy.coinage.core.constants.Constants;
import com.sy.coinage.core.vo.CacheUserVO;
import com.sy.coinage.core.interceptor.TokenVerify;
import com.sy.coinage.core.aop.annotation.Operation;
import com.sy.coinage.core.aop.util.RequestUtil;
import com.sy.coinage.log.dao.OperateLogDao;
import com.sy.coinage.log.model.OperateLog;

import com.sy.coinage.log.service.IOperateLogService;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

import java.util.Date;
import java.util.Map;

/**
 * -记录日志切面
 */
@Aspect
@Component
public class RequestLogAspect {

    private OperateLog operateLog = new OperateLog();

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private TokenVerify tokenVerify;

    @Autowired
    private IOperateLogService operateLogService;

    /**
     * 自定义请求日志接口
     *
     * @param @param operation
     * @return void 返回类型
     * @Title: serviceStatistics
     * @date 2019年5月17日 下午5:22:02
     */
    @Pointcut(value = "@annotation(operation)")
    public void serviceStatistics(Operation operation) {
        System.out.println("切入点");
    }

    /**
     * 前置通知
     *
     * @param @param joinpoint
     * @param @param operation
     * @return void 返回类型
     * @Title: doBefore
     * @date 2019年5月20日 上午9:26:41
     */
    @Before("serviceStatistics(operation)")
    public void doBefore(JoinPoint joinpoint, Operation operation) {
        Map<String, Object> joinPointinfo = RequestUtil.getJoinpointInfoMap(joinpoint);
        try {
            // 开始时间
            operateLog.setId(null);
            operateLog.setStartTime(new Date());
            operateLog.setIp(RequestUtil.getRequestIp(request));
            operateLog.setClassName(joinPointinfo.get(RequestUtil.CLASS_NAME).toString() + ":"
                            + joinPointinfo.get(RequestUtil.METHOD_NAME).toString());
            operateLog.setName(operation.value());
            operateLog.setWay(request.getMethod());
            CacheUserVO user = null;
            String userJson = String.valueOf(joinPointinfo.get(RequestUtil.USER));
            if (StringUtils.isNotBlank(userJson) && !"null".equals(userJson)) {
                user = JSON.parseObject(userJson, CacheUserVO.class);
            } else {
                String token = request.getHeader(Constants.TOKEN);
                user = this.tokenVerify.getCacheUser(token);
                operateLog.setRealName(user.getRealName());
            }
            if (user != null) {
                operateLog.setRealName(user.getRealName());
            }
            operateLog.setParam(joinPointinfo.get(RequestUtil.PARAM).toString());
            operateLog.setType(RequestUtil.getRequestType(request));
            operateLog.setUrl(request.getRequestURI());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 方法后置
     *
     * @param @param operation
     * @param @param returnValue
     * @return void 返回类型
     * @Title: doAfterReturn
     * @date 2019年5月20日 上午9:29:58
     */
    @AfterReturning(value = "serviceStatistics(operation)", returning = "returnValue")
    public void doAfterReturn(Operation operation, Object returnValue) {
        // 完善请求信息;
        operateLog.setStatus(1);
        operateLog.setReturnTime(new Date());
        // 保存数据
        this.operateLogService.save(operateLog);
    }

    /**
     * 异常通知
     *
     * @param @param operation
     * @param @param e
     * @return void 返回类型
     * @Title: doAfterThrowing
     * @date 2019年5月20日 上午9:46:31
     */
    @AfterThrowing(value = "serviceStatistics(operation)", throwing = "e")
    public void doAfterThrowing(Operation operation, Throwable e) {
        operateLog.setStatus(2);
        operateLog.setErrMsg(e.getMessage());
        operateLog.setReturnTime(new Date());
        // 保存异常信息
        this.operateLogService.save(operateLog);
    }

}
