package com.sysu.admin.api.interceptor;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
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.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;

/**
 * 用于记录web请求/响应日志
 */
@Component
@Aspect
@Slf4j
public class WebLogAspect {

    public WebLogAspect(){
        log.info("WebLogAspect started! ");
    }
    /**
     * 切面, xxx.xxx.xxx.web.ctl是Controller包名
     */
    @Pointcut("@annotation(LogAspect)")
    private void parameterPointCut() {}


    public static boolean startLog = true;

    /**
     * 方法执行前，记录请求
     * @param joinPoint
     */
    @Before("parameterPointCut()")
    public void requestLog(JoinPoint joinPoint){
        if(startLog) {
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();//这个RequestContextHolder是Springmvc提供来获得请求的东西
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            String queryStr = request.getQueryString();
            if (StringUtils.isNotEmpty(queryStr)) {
                log.warn("请求地址: [{}] {}", request.getMethod(), request.getRequestURI());
            } else {
                log.warn("请求地址: [{}] {}?{} ", request.getMethod(), request.getRequestURI(), queryStr);
            }
            printRequestArgs(joinPoint);
        }
    }

    private void printRequestArgs(JoinPoint joinPoint){
        log.warn("请求方法: {}", joinPoint.toString());
        Object[] reqArgs = joinPoint.getArgs();
        if(null == reqArgs){
            return;
        }
        int c = 0;
        for(Object arg: reqArgs){
            if(arg instanceof ServletRequest){
                continue;
            }
            try{
                log.warn("请求入参[{}]: {}", c, arg);
            }catch (Exception ex){
                log.error("请求入参转换异常", ex);
            }
            c++;
        }
    }

    /**
     * 方法执行后,记录响应
     * @param joinPoint
     * @param ret 方法执行结果注入对象
     * @return
     */
    @AfterReturning(returning = "ret",pointcut = "parameterPointCut()")
    public Object responeLog(JoinPoint joinPoint, Object ret){
        if(startLog) {
            try {
                log.warn("响应出参: {}", JSON.toJSONString(ret));
            } catch (Throwable ex) {
                log.error("响应异常", ex);
            }
        }
        return ret;
    }
}