package com.elab.log.asepct;

import com.alibaba.fastjson.JSON;
import com.dianping.cat.Cat;
import com.dianping.cat.message.Transaction;
import com.elab.core.aop.annotations.ExceptionHandle;
import com.elab.core.bean.Info;
import com.elab.core.exception.BusinessException;
import com.elab.core.exception.CoreException;
import com.elab.core.utils.ObjectUtils;
import com.elab.core.utils.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * service业务层Cat日志拦截器
 *
 * @author : liukx
 * @create : 2018/5/31 15:45
 * @email : liukx@elab-plus.com
 */
public class CatAspect {

    private final Logger logger = LoggerFactory.getLogger(CatAspect.class);

    /**
     * 环绕通知方法
     *
     * @param pjp
     * @throws Exception
     */
    public Object aroundMethod(ProceedingJoinPoint pjp) throws Exception {
        Object proceed = null;
        MethodSignature joinPointObject = (MethodSignature) pjp.getSignature();
        Method method = joinPointObject.getMethod();

        // 获取参数的名称
        Class<?>[] par = ((MethodSignature) pjp.getSignature()).getParameterTypes();
        String methodName = pjp.getSignature().getName();
        Class<?> classTarget = pjp.getTarget().getClass();
        Method objMethod = classTarget.getMethod(methodName, par);

        // 注解是否存在
        boolean annotationExist = objMethod.isAnnotationPresent(ExceptionHandle.class);

        // 构建一个类和方法的路径
        String value = pjp.getTarget().getClass().getSimpleName();
        String fullMethodName = value;
        if (annotationExist) {
            String username = objMethod.getAnnotation(ExceptionHandle.class).username();
            if (ObjectUtils.isNotEmpty(username)) {
                value = username;
                logger.debug("--------------------进入负责人[" + value + "]区域------------------------");
            }
        } else {
            fullMethodName = fullMethodName.concat("." + methodName);
        }
        Transaction t = Cat.newTransaction(value, fullMethodName);
        logger.debug(" 开始执行方法 " + method.getName() + " 参数:" + StringUtils.logOut(JSON.toJSONString(pjp.getArgs())));
        try {
            proceed = pjp.proceed();
            t.setStatus(Transaction.SUCCESS);
        } catch (Throwable e) {
            exceptionProcess(e, t, value);
        } finally {
            if (proceed instanceof Info) {
                Info info = (Info) proceed;
                String currentMessageId = Cat.getCurrentMessageId();
                Map<String, Object> extension = info.getExtension();
                if (extension == null) {
                    extension = new HashMap<String, Object>(8);
                    info.setExtension(extension);
                }
                info.getExtension().put("messageId", currentMessageId);
                logger.debug("出参结果 : " + info.isSuccess() + " 消息内容 : " + info.getMessage());
            }
            t.complete();
        }
        return proceed;
    }

    /**
     * 业务范围内的异常
     *
     * @param e
     * @param t
     * @param value
     */
    private void exceptionProcess(Throwable e, Transaction t, String value) {
        // 属于业务参数异常和系统异常没有关系
        if (e instanceof BusinessException) {
            logger.debug(e.getMessage());
            t.setSuccessStatus();
            throw new BusinessException(((BusinessException) e).getErrorCode(), e.getMessage());
        }

        t.setStatus(e);

        if (e instanceof CoreException) {
            logger.debug(e.getMessage());
            throw new CoreException(((CoreException) e).getErrorCode(), e.getMessage());
        }
        if (value != null) {
            logger.error("[" + value + "]", e);
        } else {
            logger.error("[未知作者]", e);
        }
        throw new RuntimeException(e.getMessage());
    }

}
