package com.judong.chuanyiserver.annotation;

import cn.hutool.extra.servlet.ServletUtil;
import com.judong.chuanyiserver.entity.Log;
import com.judong.chuanyiserver.service.LogService;
import com.judong.chuanyiserver.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

@Component
@Aspect
@Slf4j
@Order(100)
public class WebLogAspect {

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private LogService logService;

    @Resource
    private HttpServletRequest request;

    private String methodName;

    private String requestArgs;


    /**
     * 定义切点 @Pointcut
     * 在注解的位置切入代码
     */
    @Pointcut("execution(* com.judong.chuanyiserver..*.*(..))")
    public void webLog() {
    }

    /**
     * 环绕通知
     */
    @Around(value = "webLog() && @annotation(WebLog)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取签名
        Signature signature = joinPoint.getSignature();
        // 获取切入的包名
        String declaringTypeName = signature.getDeclaringTypeName();
        // 获取即将执行的方法名
        String funcName = signature.getName();
        Map<String, Object> params = new HashMap<>();
        String[] keys = ((MethodSignature) signature).getParameterNames();
        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < keys.length; i++) {
            params.put(keys[i], args[i]);
        }
        methodName = declaringTypeName + "." + funcName;
        requestArgs = params.toString();
        log.info("即将执行{}包下的方法，方法名为: {}", declaringTypeName, funcName);
        log.info("请求的参数有: {}", params.toString());
        return joinPoint.proceed();
    }

    @Before(value = "webLog() && @annotation(WebLog)")
    public void before(JoinPoint joinPoint) {
        System.out.println("Before");
    }

    @After(value = "webLog() && @annotation(WebLog)")
    public void after() {
        System.out.println("After");
    }

    @AfterReturning(value = "webLog() && @annotation(WebLog)", returning = "result")
    public void doAfterReturning(JoinPoint joinPoint, Object result) {
        Log log = new Log();

        //获取抽象方法
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        //获取目标对象上的Method对象
        Method method = methodSignature.getMethod();
        //获取注解
        WebLog webLog = method.getAnnotation(WebLog.class);
        if (webLog != null) {
            log.setServerName(webLog.ServerEnum().getName());
            log.setModelName(webLog.ModelEnum().getValue());
        }
        log.setMethodName(methodName);
        log.setOperationStatus(1);
        log.setContent("操作：" + webLog.OperationEnum().getValue() + "<br>请求的参数有：" + requestArgs + "<br>返回的结果为：" + result.toString());
        log.setUserId((String) redisUtil.get(request.getHeader("token")));
        ServletUtil.getClientIP(request, null);
        log.setIpAddress(ServletUtil.getClientIP(request, null));
        // 处理完请求，返回内容
//        System.out.println("AfterReturning ");
//        System.out.println("方法的返回值 : " + result);
        logService.insertLog(log);
    }

    //后置异常通知
    @AfterThrowing(value = "webLog() && @annotation(WebLog)")
    public void afterThrowing(JoinPoint jp) {
        System.out.println("AfterThrowing");
    }

}
