package com.brilliance.isc.common.aop.watch;

import cn.hutool.core.date.StopWatch;
import cn.hutool.core.lang.Assert;
import com.brilliance.isc.annotation.WatchDog;
import com.brilliance.isc.common.aop.IBaseAspect;
import com.brilliance.isc.constant.ErrorCode;
import com.brilliance.isc.exception.RestBizException;
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.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class WatchDogAspect implements IBaseAspect {

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

    @Pointcut("@annotation(com.brilliance.isc.annotation.WatchDog)")
    @Override
    public void pointcut() {

    }

    @Around("pointcut()")
    @Override
    public Object around(ProceedingJoinPoint joinPoint) {
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        MethodSignature methodSignature= (MethodSignature) joinPoint.getSignature();
        WatchDog watchdog = null;
        StopWatch stopWatch = null;
        try {
            watchdog = methodSignature.getMethod()
                    .getAnnotation(WatchDog.class);

            stopWatch = new StopWatch();
            stopWatch.start();
            logger.info("###########WATCH DOG START WATCH{}:[{}:{}()]", watchdog.name(), className, methodName);
            return joinPoint.proceed();
        } catch (Throwable throwable) {
            logger.error("#############WATCH DOG: an exception has been throwing in " + className + ":" + methodName + "():{}", throwable);
            if (throwable instanceof RestBizException) {
                throw (RestBizException) throwable;
            } else {
                throw new RestBizException(ErrorCode.BIZ_COMMON_ERROR, throwable.getMessage());
            }
        } finally {
            if (stopWatch != null){
                stopWatch.stop();
            }
            Assert.notNull(watchdog);
            logger.info("################WATCH DOG {}:[{}:{}()]total run time(seconds) ===> {} ", watchdog.name(), className, methodName, stopWatch.getTotalTimeSeconds());
        }
    }

}
