package com.yuchen.saas.park.service.aspect;

import cn.hutool.json.JSONUtil;
import com.yuchen.saas.park.api.entity.park.PmgBatParkUserOperationLog;
import com.yuchen.saas.park.service.annotation.LogAnnotation;
import com.yuchen.saas.park.service.service.PmgBatParkUserOperationLogService;
import org.apache.commons.lang.time.StopWatch;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.nest.springwrap.core.secure.ContextUser;
import org.nest.springwrap.core.secure.utils.AuthUtil;
import org.nest.springwrap.core.tool.utils.Func;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Date;

/**
 * @author: 李涛
 * @date 2022/1/8 12:03
 * @description:
 */

@Aspect
@Component
public class LogAspect {

    @Resource
    private PmgBatParkUserOperationLogService pmgBatParkUserOperationLogService;

    public static final Logger logger = LoggerFactory.getLogger(LogAspect.class);

    private static final StopWatch stopWatch = new StopWatch();

    @Pointcut("@annotation(com.yuchen.saas.park.service.annotation.LogAnnotation)")
    public void annotationPointcut() {
        logger.info("日志记录切入点");
    }

    /**
     * 此处进入到方法前  可以实现一些业务逻辑
     * @param joinPoint
     */
    @Before("annotationPointcut()")
    public void beforePointcut(JoinPoint joinPoint) {
        stopWatch.reset();
        stopWatch.start();
        logger.info("before>>>>>>>>>>>>>>>>>>>>>");
    }

    /**
     * 在切入点return内容之后切入内容（可以用来对处理返回值做一些加工处理）
     * @param joinPoint
     */
    @AfterReturning(returning="rvt", value = "annotationPointcut()  && @annotation(logAnnotation)")
    public void doAfterReturning(JoinPoint joinPoint, LogAnnotation logAnnotation, Object rvt) {
        try {
            stopWatch.stop();
            //接口请求时间 单位 秒
            long userTime = stopWatch.getTime()/1000;
            logger.info("数据拦截 >> Value：{} >> param：{}",logAnnotation.value(), Arrays.toString(joinPoint.getArgs()));
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            logger.info("IP: {} >> URI: {} >> HTTP_METHOD: {} >> CLASS_METHOD: {} >> ARGS: {}",request.getRemoteAddr() ,request.getRequestURI(),request.getMethod(),
                    joinPoint.getSignature().getDeclaringTypeName() + "_" + joinPoint.getSignature().getName(),Arrays.toString(joinPoint.getArgs()));
            //获取用户信息
            ContextUser contextUser = AuthUtil.getUser();

            //保存操作日志记录
            PmgBatParkUserOperationLog pmgBatParkUserOperationLog = new PmgBatParkUserOperationLog();
            pmgBatParkUserOperationLog.setOperationType(logAnnotation.value().getValue());
            //setUserId 放getUserInfoId  create_user放userId
            if(Func.isNotEmpty(contextUser)){
                pmgBatParkUserOperationLog.setParkId(contextUser.getParkId());
                pmgBatParkUserOperationLog.setUserId(contextUser.getUserInfoId());
                pmgBatParkUserOperationLog.setUserName(contextUser.getUserName());
            }
            //pmgBatParkUserOperationLog.setUserId(contextUser.getUserId());
            pmgBatParkUserOperationLog.setRequestUrl(String.valueOf(request.getRequestURL()));
            pmgBatParkUserOperationLog.setRequestParams(JSONUtil.toJsonStr(joinPoint.getArgs()));
            pmgBatParkUserOperationLog.setRequestTime(new Date());
            pmgBatParkUserOperationLog.setUseTime(userTime);
            pmgBatParkUserOperationLog.setResponseData(String.valueOf(rvt));
            logger.info("园区操作记录插入操作{}", pmgBatParkUserOperationLog);
            pmgBatParkUserOperationLogService.save(pmgBatParkUserOperationLog);
        } catch (Exception e) {

        }
    }
}
