package com.elab.spring.intercept;

import com.elab.core.utils.StringUtils;
import com.elab.spring.anno.AuthorDescription;
import com.elab.spring.componts.DefaultExpression;
import com.elab.spring.intercept.annotation.AnnotationProcessService;
import com.elab.spring.monitor.MonitorCollect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.ReflectiveMethodInvocation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.Map;

    /**
     * 对于功能定义的一些拦截描述
     *
     * @author liukaixiong
     * @Email liukx@elab-plus.com
     * @date 2021/9/27 - 11:10
     */
    public class AuthorDescriptionAnnotationProcess implements AnnotationProcessService {
        private Logger logger = LoggerFactory.getLogger(getClass());
        @Autowired
        private DefaultExpression defaultExpression;

        @Override
        public Class<? extends Annotation> annotation() {
            return AuthorDescription.class;
        }

        @Override
        public Object invokeWithinTransaction(ReflectiveMethodInvocation invocation) throws Throwable {
            Method method = invocation.getMethod();
            AuthorDescription authorDescription = AnnotationUtils.getAnnotation(method, AuthorDescription.class);
            String clazzName = method.getDeclaringClass().getSimpleName();
            String name = method.getName();
            String methodName = clazzName + "." + name;
            Object[] arguments = invocation.getArguments();
            Map<String, Object> request = new LinkedHashMap<>();
            request.put("request", arguments);

            // 用于关键搜索
            String searchKey = authorDescription.searchKey();
            if (!StringUtils.isEmpty(searchKey)) {
                searchKey = defaultExpression.getValue(request, searchKey, String.class);
            }

            // 发送数据埋点
            return MonitorCollect.SERVICE.send(authorDescription.nickname(), methodName, authorDescription.modulesName(),
                authorDescription.describe(), searchKey, request, () -> {
                    try {
                        return invocation.proceed();
                    } catch (Throwable throwable) {
                        throw new Exception(throwable);
                    }
                });
        }
    }
