package com.yanzuoguang.cloud.aop;

import com.yanzuoguang.util.contants.ResultConstants;
import com.yanzuoguang.util.exception.CodeException;
import com.yanzuoguang.util.exception.ExceptionHelper;
import com.yanzuoguang.util.vo.LogVo;
import com.yanzuoguang.util.vo.ResponseResult;
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.stereotype.Component;

/**
 * 接口切面,用于验证接口回调返回参数
 *
 * @author 颜佐光
 */
@Aspect
@Component
public class AspectFeign {

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

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

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

    /**
     * AOP的表达式
     */
    @Pointcut("execution(* *..feign..*Feign.*(..))")
    public void feignAspect() {
    }

    /**
     * 执行环形切面
     *
     * @param joinPoint 切面对象
     * @return 切面结果
     */
    @Around(value = "feignAspect()")
    public Object requestFeignAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Class<?> declaringType = joinPoint.getSignature().getDeclaringType();
        String url = aspectLogUrl.getWebMethodUrl(joinPoint);
        Object requestBody = aspectLogBody.getRequestBody(joinPoint);
        boolean clear = aspectLogStart.requestLogInit();

        LogVo log = new LogVo();
        aspectLogStart.requestLog(declaringType, TAG, url, requestBody, log, clear);
        long start = System.currentTimeMillis();

        Object result = null;
        Exception ex = null;

        try {
            result = joinPoint.proceed();
            // 假如是标准格式,则验证接口是否成功,不成功则抛出异常
            if (result instanceof ResponseResult) {
                ResponseResult<?> responseResult = (ResponseResult<?>) result;
                if (!ResultConstants.SUCCESS.equals(responseResult.getCode())) {
                    throw new CodeException(responseResult.getCode(), responseResult.getMessage(), responseResult.getTarget());
                }
            }

            return result;
        } catch (CodeException e) {
            ex = e;
            throw e;
        } catch (Exception e) {
            result = ExceptionHelper.getError(e);
            ex = e;
            throw e;
        } finally {
            aspectLogResult.responseLog(declaringType, TAG, url, clear, start, requestBody, result, ex, log);
        }
    }


}