package com.changhu.common.cache;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import com.changhu.common.annotation.IsExtData;
import com.changhu.common.db.BaseEnum;
import com.changhu.common.pojo.vo.SelectNodeVo;
import lombok.extern.slf4j.Slf4j;
import org.ehcache.impl.internal.concurrent.ConcurrentHashMap;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author 20252
 * @createTime 2024/11/15 上午9:03
 * @desc GlobalCacheManager...
 */
@Slf4j
public class GlobalCacheManager {
    /**
     * 枚举缓存
     */
    public static final Map<Class<?>, Map<BaseEnum<?>, SelectNodeVo<?>>> ENUM_CACHE = new ConcurrentHashMap<>();

    static {
        //初始化枚举数据
        initEnum();
    }

    static void initEnum() {
        log.info("初始化枚举字典数据----");
        Set<Class<?>> classes = ClassUtil.scanPackageBySuper("com.changhu.common.db.enums", BaseEnum.class);
        Method superSerializer = ClassUtil.getDeclaredMethod(BaseEnum.class, "serializer");
        for (Class<?> aClass : classes) {
            Method childrenSerializer = ClassUtil.getDeclaredMethod(aClass, "serializer");
            BaseEnum<?>[] enumConstants = (BaseEnum<?>[]) aClass.getEnumConstants();
            if (enumConstants == null) {
                continue;
            }
            // 获取所有字段
            Field[] fields = aClass.getDeclaredFields();
            // 过滤出非静态字段并带有 IsExtData 注解的字段
            List<Field> extDataFields = Arrays.stream(fields)
                    .filter(field -> !Modifier.isStatic(field.getModifiers()))
                    .filter(field -> field.getAnnotation(IsExtData.class) != null)
                    .collect(Collectors.toList());

            Map<BaseEnum<?>, SelectNodeVo<?>> map = new LinkedHashMap<>();

            Stream.of(enumConstants).forEach(v -> {
                //如果子类重写父类的方法 则直接使用子类的结果
                if (!superSerializer.equals(childrenSerializer)) {
                    map.put(v, v.serializer());
                } else {
                    SelectNodeVo<Object> vo = new SelectNodeVo<>();
                    vo.setValue(v.getValue());
                    vo.setLabel(v.getLabel());
                    if (CollUtil.isNotEmpty(extDataFields)) {
                        Dict extData = Dict.create();
                        for (Field extDataField : extDataFields) {
                            extData.put(extDataField.getName(), ReflectUtil.getFieldValue(v, extDataField));
                        }
                        vo.setExtData(extData);
                    }
                    map.put(v, vo);
                }
            });
            GlobalCacheManager.ENUM_CACHE.put(aClass, map);
        }
        log.info("初始化枚举字典数据----完成");
    }
}
