package com.huiju.estateagents.property.aop;

import com.alibaba.fastjson.JSONObject;
import com.huiju.estateagents.property.log.LogAnnotation;
import com.huiju.estateagents.property.log.LogEnums;
import com.huiju.estateagents.property.log.LogFactory;
import com.huiju.estateagents.property.log.LogFileManager;
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.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
@Slf4j
public class LogAOP {

    @Pointcut("@annotation(com.huiju.estateagents.property.log.LogAnnotation)")
    public void pointLog() {

    }

    @Around("pointLog()")
    public Object logAround(ProceedingJoinPoint point) throws Throwable {

        // 获取切面的点的实例
        Object target = point.getTarget();
        // 获取反射对象
        Class<?> zClass = target.getClass();
        // 获取切面点
        Signature signature = point.getSignature();

        // 判断日志注解是否用在方法上
        if (!(signature instanceof MethodSignature)) {
            throw new RuntimeException("该注解只允许在方法上使用！");
        }

        // 方法名称
        String methodName = signature.getName();
        // 获取方法参数类型
        Class<?>[] parameterTypes = ((MethodSignature) signature).getMethod().getParameterTypes();

        // 通过方法名称和方法参数类型
        // 获取当前正在执行切面的方法
        Method method = zClass.getMethod(methodName, parameterTypes);

        // 所有方法输入参数
        Object[] args = point.getArgs();
        // 执行方法的返回值
        Object result = null;
        if (null != method && method.isAnnotationPresent(LogAnnotation.class)) {

            // 获取这个注解
            LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
            // 大苏操作
            if (logAnnotation.record() && logAnnotation.value() == LogEnums.DA_SU) {
                String alias = "".equals(logAnnotation.alias()) ? "未设置别名" : logAnnotation.alias();
                    log.info("AOP拦截----大苏操作----执行方法:{}，方法别名:{}, 请求参数:{}", methodName, alias,args);
                    // 方法返回值
                    result = point.proceed();
                    log.info("AOP拦截----大苏操作----执行方法:{}，方法别名:{},请求参数:{}，返回结果:{}", methodName, alias,args, result);

                    String strPararmeter = String.format( "AOP拦截----大苏操作----执行方法:%s，方法别名:%s,请求参数:%s", methodName, alias, JSONObject.toJSONString(args));
                    String strReturn = String.format("AOP拦截----大苏操作----执行方法:%s，方法别名:%s, 请求参数:%s，返回结果:%s", methodName, alias , JSONObject.toJSONString(args), JSONObject.toJSONString(result));

                    LogFileManager.getInstance().executeLog(LogFactory.parametersAndReturn(strPararmeter, strReturn));

            }

        }

        return result;
    }

    @AfterThrowing(value = "pointLog()", throwing = "cause")
    public void doException(JoinPoint joinPoint, Throwable cause) {
        if (null != cause) {
//            throw new FuShiException(cause.getMessage());
        }
    }

}
