package com.hotent.base.aop;

import com.hotent.base.annotation.OpenApi;
import com.hotent.base.cache.annotation.CachePut;
import com.hotent.base.cache.annotation.FirstCache;
import com.hotent.base.constants.CacheKeyConst;
import com.hotent.base.constants.JmsConstant;
import com.hotent.base.entity.URIEntity;
import com.hotent.base.jms.JmsProducer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ClassUtils;
import org.springframework.web.bind.annotation.RequestMapping;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Set;
import java.util.concurrent.*;

/**
 * @Author: Cola
 * @Date: 2021/8/18 21:58
 * 要求所有外部接口，都是基于@RequestMapping注解去配置
 **/
@Configuration
public class OpenApiProcessor implements BeanPostProcessor {

    public static Set<URIEntity> uriEntitySet = new CopyOnWriteArraySet<URIEntity>();
    @Value("${openApi.prefix:'openApi'}")
    private String PREFIX;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        OpenApi classAnnotation = AnnotationUtils.findAnnotation(bean.getClass(), OpenApi.class);
        if (classAnnotation==null || !classAnnotation.open()){
            return bean;
        }
        Class<?> clazz = bean.getClass();
        // 获取到被代理前的类
        Class<?> originClazz = ClassUtils.getUserClass(clazz);
        if (originClazz.isAnnotationPresent(RequestMapping.class)){
            RequestMapping requestMapping = originClazz.getAnnotation(RequestMapping.class);
            OpenApi classOpenApi = originClazz.getAnnotation(OpenApi.class);
            Method[] methods = originClazz.getMethods();
            Arrays.stream(methods).forEach(method->{
                if (method.isAnnotationPresent(RequestMapping.class) && method.isAnnotationPresent(OpenApi.class)){
                    OpenApi methodOpenApi=method.getAnnotation(OpenApi.class);
                    if (!methodOpenApi.open()){
                        return;
                    }
                    URIEntity uriEntity = new URIEntity();
                    uriEntity.setClassURI(requestMapping.value()[0].replace("${openApi.prefix}",PREFIX).replace("//","/"));
                    uriEntity.setFunction(classOpenApi.function());
                    RequestMapping annotation = method.getAnnotation(RequestMapping.class);
                    uriEntity.setDescription(methodOpenApi.description());
                    uriEntity.setMethodURI(annotation.value()[0]);
                    uriEntity.setModuleName(classOpenApi.moduleName());
                    uriEntity.setClassName(originClazz.getSimpleName());
                    uriEntitySet.add(uriEntity);
                }
            });
        }
        return bean;
    }
}
