package com.hz.pm.api.meta.helper.basic;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.IterUtil;
import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.hz.pm.api.meta.constant.DictTypeEnum;
import com.hz.pm.api.meta.helper.DictionaryCache;
import com.hz.pm.api.meta.model.dto.DictionaryDTO;
import com.hz.pm.api.meta.service.IMetaDictionaryService;
import com.ningdatech.basic.util.CollUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.springframework.beans.factory.InitializingBean;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author liuxinxin
 * @date 2022/12/22 上午11:03
 */
@Slf4j
@RequiredArgsConstructor
public abstract class AbstractDictionaryCache implements InitializingBean, DictionaryCache {

    private final IMetaDictionaryService metaDictionaryService;

    protected Map<String, DictionaryDTO> dictionaryMap = new ConcurrentHashMap<>();
    protected LoadingCache<String, List<DictionaryDTO>> dictCache;

    @Override
    public void afterPropertiesSet() {
        dictCache = Caffeine.newBuilder()
                .refreshAfterWrite(7, TimeUnit.DAYS)
                .build(new CacheLoader<String, List<DictionaryDTO>>() {
                    @Override
                    public List<DictionaryDTO> load(@NonNull String key) {
                        log.info("刷新字典数据：{}", key);
                        List<DictionaryDTO> dicts = metaDictionaryService.queryByDictType(key);
                        dicts.forEach(dict -> dictionaryMap.put(dict.getDictionaryCode(), dict));
                        return dicts;
                    }

                    @Override
                    public @NonNull Map<String, List<DictionaryDTO>> loadAll(@NonNull Iterable<? extends String> keys) {
                        log.info("刷新字典数据[loadAll]：数量 -> {}", IterUtil.size(keys));
                        if (CollUtil.isEmpty(keys)) {
                            return Collections.emptyMap();
                        }
                        List<String> keysList = IterUtil.toList(keys).stream().map(String::toString).collect(Collectors.toList());
                        List<DictionaryDTO> allDicts = metaDictionaryService.queryByDictTypes(keysList);
                        allDicts.forEach(dict -> dictionaryMap.put(dict.getDictionaryCode(), dict));
                        return CollUtils.group(allDicts, DictionaryDTO::getDictionaryType);
                    }
                });
        // 初始化所有字典信息
        initAllDicts();
    }

    private void initAllDicts() {
        List<String> dictTypes = Arrays.stream(DictTypeEnum.values())
                .map(DictTypeEnum::getKey)
                .collect(Collectors.toList());
        dictCache.getAll(dictTypes);
    }

}
