package com.yanzuoguang.cloud.aop;

import com.yanzuoguang.cloud.aop.log.AspectLogResult;
import com.yanzuoguang.cloud.aop.log.AspectLogStart;
import com.yanzuoguang.mq.service.MessageLogService;
import com.yanzuoguang.util.exception.ExceptionHelper;
import com.yanzuoguang.util.vo.LogVo;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.amqp.core.Message;
import org.springframework.stereotype.Component;

/**
 * MQ处理切面
 *
 * @author 颜佐光
 */
@Aspect
@Component
public class AspectMq {

    private static final String TAG = AspectMq.class.getSimpleName();

    private final MessageLogService logService;
    private final AspectLogUrl aspectLogUrl;
    private final AspectLogBody aspectLogBody;
    private final AspectLogStart aspectLogStart;
    private final AspectLogResult aspectLogResult;

    public AspectMq(MessageLogService logService, AspectLogUrl aspectLogUrl, AspectLogBody aspectLogBody, AspectLogStart aspectLogStart, AspectLogResult aspectLogResult) {
        this.logService = logService;
        this.aspectLogUrl = aspectLogUrl;
        this.aspectLogBody = aspectLogBody;
        this.aspectLogStart = aspectLogStart;
        this.aspectLogResult = aspectLogResult;
    }

    /**
     * exec aop point aspect
     */
    @Pointcut("execution(* *..mq..*Consumer.*(..))")
    // @Pointcut("execution(* org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter.onMessage(..))")
    public void mqAspect() {
    }

    /**
     * 执行环形切面
     *
     * @param joinPoint 方法提
     * @return 执行回掉
     */
    @Around(value = "mqAspect()")
    public Object requestMqAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Class<?> declaringType = joinPoint.getSignature().getDeclaringType();
        Message message = aspectLogUrl.getMessage(joinPoint);
        if (message == null) {
            return executeMethod(joinPoint);
        }
        logService.logCurrent(message);
        String url = aspectLogUrl.getMessageUrl(joinPoint, message);
        String requestBody = aspectLogBody.getRequestBody(message);

        boolean clear = true;
        aspectLogStart.requestLogInit();
        LogVo log = aspectLogStart.requestLog(declaringType, TAG, url, requestBody, clear);
        Object result = null;
        Exception ex = null;
        try {
            result = executeMethod(joinPoint);
            return result;
        } catch (Exception e) {
            // 消费消息出错
            result = ExceptionHelper.getError(e);
            ex = e;
            throw e;
        } finally {
            logService.logCurrentRemove();
            aspectLogResult.responseLog(declaringType, TAG, url, clear, requestBody, result, ex, log);
        }
    }

    /**
     * 执行函数
     *
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    private Object executeMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        return joinPoint.proceed();
    }
}