package com.hdkj.lt.core.sys.service.impl;

import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hdkj.lt.base.constants.DictConstants;
import com.hdkj.lt.base.constants.RedisKeyConstants;
import com.hdkj.lt.base.constants.SymbolConstants;
import com.hdkj.lt.core.sys.service.ISysDicRefService;
import com.hdkj.lt.core.sys.service.ISysDictService;
import com.hdkj.lt.core.sys.service.ISysDictTypeService;
import com.hdkj.lt.utils.cache.RedisRepository;
import com.hdkj.lt.core.sys.model.po.DicSingle;
import com.hdkj.lt.core.sys.model.po.DicType;
import com.hdkj.lt.core.sys.model.vo.DicLevelTreeVo;
import com.hdkj.lt.core.sys.model.vo.DicVo;
import com.hdkj.lt.core.sys.model.vo.DictVo;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Author: wenhao
 * @Create: 2024/04/03 13:40
 * @Version: 1.0
 */
@Service
@AllArgsConstructor
public class SysDictServiceImpl implements ISysDictService {

    private final ISysDictTypeService sysDictTypeService;

    private final ISysDicRefService sysDicRefService;

    private final RedisRepository redisRepository;

    @Override
    public void putAllToCache() {
        redisRepository.del(RedisKeyConstants.CACHE_KEY_DICT_HASH);
        List<String> allTypeNames = sysDictTypeService.list().stream().map(DicType::getTypeName).collect(Collectors.toList());
        Map<String, Object> dbMap = this.getDictMapByTypeNames(allTypeNames);
        for (String typeName : allTypeNames) {
            if (!dbMap.containsKey(typeName)) {
                dbMap.put(typeName, Maps.newHashMap());
            }
        }
        redisRepository.putHashValues(RedisKeyConstants.CACHE_KEY_DICT_HASH, dbMap);
    }

    @SuppressWarnings("unchecked")
    @Override
    public Map<String, Map<String, String>> getCacheByTypeNames(String... typeNames) {
        Map<String, Object> cacheMap = redisRepository.getHashValue(RedisKeyConstants.CACHE_KEY_DICT_HASH);
        Map<String, Map<String, String>> resultMap = Maps.newHashMap();
        for (String typeName : typeNames) {
            Optional.ofNullable(cacheMap.get(typeName)).ifPresent(e -> resultMap.put(typeName, (Map<String, String>) e));
        }
        Set<String> queriedDicts = resultMap.keySet();
        if (CollectionUtils.size(queriedDicts) != ArrayUtils.getLength(typeNames)) {
            List<String> typeNameList = Lists.newArrayList(typeNames);
            List<String> notFoundDicts = (List<String>) CollectionUtils.removeAll(typeNameList, queriedDicts);
            Map<String, Object> dbMap = this.getDictMapByTypeNames(notFoundDicts);
            dbMap.forEach((typeName, value) -> resultMap.put(typeName, (Map<String, String>) value));
        }
        return resultMap;
    }

    @Override
    public String getLabelByValue(String typeName, String value) {
        Map<String, Map<String, String>> dictMap = this.getCacheByTypeNames(typeName);
        return dictMap.get(typeName).get(value);
    }

    private Map<String, Object> getDictMapByTypeNames(List<String> typeNames) {
        List<DictVo> dictVoList = sysDicRefService.getDictVosByTypeNames(typeNames);
        return dictVoList.stream().collect(Collectors.toMap(DictVo::getTypeName, (e) -> {
            List<DicSingle> singleList = e.getSingleList();
            if (CollectionUtils.isEmpty(singleList)) {
                return Maps.newHashMap();
            }
            return singleList.stream().filter(en -> !StringUtils.equals("隐藏", en.getBak3()))
                    .sorted(Comparator.comparingInt(DicSingle::getSort))
                    .collect(Collectors.toMap(DicSingle::getValue, DicSingle::getLabel, (k1, k2) -> k1));
        }));
    }

    @Override
    public List<DictVo> getDictVosByTypeNames(String... typeNames) {
        List<DictVo> dictVoLists = sysDicRefService.getDictVosByTypeNames(Lists.newArrayList(typeNames));
        return dictVoLists.stream().peek(o -> o.getSingleList().sort(Comparator.comparing(DicSingle::getSort))).collect(Collectors.toList());
    }

    @Override
    public String getDictLabel(Map<String, Map<String, String>> dictMap, String dictType, String dictValue) {
        Map<String, String> dictItem = dictMap.get(dictType);
        if (MapUtils.isEmpty(dictItem)) {
            return null;
        }
        return dictItem.get(dictValue);
    }

    @Override
    public List<DicLevelTreeVo> getLevelDictByTypeName(String typeName) {
        return sysDicRefService.getLevelDictByTypeName(typeName);
    }

    @Override
    public String valuesConvertLabels(String valueStr, String splitStr, Map<String, String> dictMap) {
        StringBuilder labelStr = new StringBuilder();
        if (StringUtils.isNotBlank(valueStr)) {
            String[] values = valueStr.split(splitStr);
            for (int i = 0; i < values.length; i++) {
                String label = dictMap.get(values[i]);
                if (StringUtils.isNotBlank(label)) {
                    labelStr.append(label);
                    if (i != values.length - 1) {
                        labelStr.append(SymbolConstants.SEMICOLON_EN);
                    }
                }
            }
        }
        return labelStr.toString();
    }

    @Override
    public String valuesConvertLabels(String valueStr, String typeName, String splitStr) {
        StringBuilder stringBuilder = new StringBuilder();
        if (StringUtils.isNotBlank(valueStr)) {
            String[] values = valueStr.split(splitStr);
            for (int i = 0; i < values.length; i++) {
                String value = values[i];
                String label = this.getLabelByValue(typeName, value);
                if (StringUtils.isNotBlank(label)) {
                    stringBuilder.append(label);
                    if (i < values.length - 1) {
                        stringBuilder.append(SymbolConstants.SEMICOLON_EN);
                    }
                }
            }
        }
        return stringBuilder.toString();
    }

    @Override
    public Integer dictValueToSort(List<DicSingle> dictSingles, String value) {
        List<DicSingle> dictSingleList = dictSingles.stream()
                .filter(dictSingle -> dictSingle.getValue().equals(value)).collect(Collectors.toList());
        if (dictSingleList.size() > 0) {
            return dictSingleList.get(0).getSort();
        }
        return 9999;
    }

    @Override
    public Map<String, Map<String, String>> getDictVosByTypeNamesLabelToKey(String... typeNames) {
        // 接口获取字典值根据字典编码
        List<DictVo> dictVoLists = sysDicRefService.getDictVosByTypeNames(Arrays.asList(typeNames));
        // 字典名称为key的字典值对象转换
        Map<String, Map<String, String>> collect = new HashMap<>();
        if (ObjectUtils.isNotEmpty(dictVoLists)) {
            collect = dictVoLists.stream().collect(Collectors.toMap(DictVo::getTypeName, (o) -> {
                List<DicSingle> singleList = o.getSingleList();
                if (singleList == null) {
                    return Collections.emptyMap();
                }
                return singleList.stream().sorted((o1, o2) -> ObjectUtils.compare(o1.getSort(), o2.getSort())).collect(Collectors.toMap(DicSingle::getLabel, DicSingle::getValue, (k1, k2) -> k1));
            }, (k1, k2) -> k1));
        }
        for (String typeName : typeNames) {
            if (!collect.containsKey(typeName)) {
                collect.put(typeName, Collections.emptyMap());
            }
        }
        return collect;
    }

    @Override
    public List<DictVo> getPsrState(String zxbType) {
        String dictKey = DictConstants.PSR_STATE;
        if (StringUtils.isNotBlank(zxbType)) {
            // 设备运行状态映射
            Map<String, Map<String, String>> zxbMapping = this.getCacheByTypeNames(DictConstants.PSR_STATE_MAPPING_ZXB);
            dictKey = getPsrStateDictKey(zxbMapping.get(DictConstants.PSR_STATE_MAPPING_ZXB), zxbType);
        }
        // 设备运行状态
        List<DictVo> dictVosByTypeNames = this.getDictVosByTypeNames(dictKey);
        if (ObjectUtils.isNotEmpty(dictVosByTypeNames) && ObjectUtils.isNotEmpty(dictVosByTypeNames.get(0).getSingleList())) {
            DicSingle nullDict = new DicSingle();
            nullDict.setValue("-1");
            nullDict.setLabel(StrUtil.DASHED);
            dictVosByTypeNames.get(0).getSingleList().add(nullDict);
        }
        return dictVosByTypeNames;
    }

    /**
     * 设备运行状态根据根据键获取值
     */
    private String getPsrStateDictKey(Map<String, String> dictMap, String key) {
        for (Map.Entry<String, String> entry : dictMap.entrySet()) {
            String value = entry.getKey();
            HashSet<String> strings = new HashSet<>(Arrays.asList(value.split(StrUtil.COMMA)));
            if (strings.contains(key)) {
                return entry.getValue();
            }
        }
        return null;
    }

    /**
     * 根据单个类型名称查询字典集合
     *
     * @param typeName 字典类型名称
     * @return 字典集合
     */
    @Override
    public List<DicVo> getDicListByType(String typeName) {
        return sysDicRefService.getDicListByType(typeName);
    }
}
