package com.blueland.core.util;

import cn.hutool.core.collection.CollUtil;
import com.blueland.constant.RedisConstant;
import com.blueland.bo.DictEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Component;

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

/**
 * @description: 字典工具类型
 * @author: bigTian
 * @create: 2021-10-28 09:36
 */
@Component("remoteDictUtils")
@Slf4j
public class RemoteDictUtils {
    @Autowired
    private RedisUtils redisUtils;


    /**
     * 根据appid和字典父Code返回对应的子数据
     *
     * @param parentCode 字典父Code
     * @param appId      租户id
     * @return
     */
    public List<DictEntity> getDictByParentCodeAndAppId(String appId, String parentCode) {
        Map<String, DictEntity> parentMap = getParentMap(appId, parentCode);
        ArrayList<DictEntity> list = new ArrayList<>(parentMap.values());
        if (CollUtil.isNotEmpty(list)) {
            list.sort(Comparator.comparing(DictEntity::getSort));
        }
        return list;
    }

    /**
     * 根据appid返回对应的子数据
     *
     * @param appId 租户id
     * @return
     */
    public List<DictEntity> getDictByAppId(String appId) {
        Map<String, DictEntity> parentMap = getAppMap(appId);
        ArrayList<DictEntity> list = new ArrayList<>(parentMap.values());
        if (CollUtil.isNotEmpty(list)) {
            list.sort(Comparator.comparing(DictEntity::getSort));
        }
        return list;
    }

    /**
     * excel导入，以名称为key
     *
     * @param parentCode 字典父Code
     * @param appId      租户id
     * @return
     */
    public Map<String, DictEntity> getDictByNames(String appId, String parentCode) {
        Map<String, DictEntity> parentMap = getParentMap(appId, parentCode);
        parentMap = parentMap.values().stream().collect(Collectors.toMap(DictEntity::getDictName, el -> el));
        return parentMap;
    }

    /**
     * 返回所有的字典数据
     *
     * @return
     */
    public Map<String, Map<String, Map<String, DictEntity>>> getDictMaps() {
        return redisUtils.hashEntries(RedisConstant.SYS_DICT_CACHE);
    }

    /**
     * 根据父级code和字典code查询
     *
     * @param parentCode 父级code
     * @param code       需要查询的字典code
     * @param appId      租户id
     * @return
     */
    public DictEntity getDict(String appId, String parentCode, String code) {
        Map<String, DictEntity> parentMap = getParentMap(appId, parentCode);
        return parentMap.get(code);
    }

    /**
     * 根据租户id和父code查询相关字典
     *
     * @param appId
     * @param parentCode
     * @return
     */
    private Map<String, DictEntity> getParentMap(String appId, String parentCode) {
        Map<String, DictEntity> appIdMaps = new HashMap<>();
        ScanOptions options = new ScanOptions.ScanOptionsBuilder()
                .match(appId + RedisConstant.DIVISION + parentCode + RedisConstant.DIVISION + RedisConstant.WILDCARD)
                .count(100)
                .build();
        Cursor<Map.Entry<String, DictEntity>> cursor = redisUtils.hashScan(RedisConstant.SYS_DICT_CACHE, options);
        Map.Entry<String, DictEntity> entry = null;
        DictEntity value = null;
        while (cursor.hasNext()) {
            entry = cursor.next();
            value = entry.getValue();
            appIdMaps.putIfAbsent(value.getDictCode(), value);
        }
        cursor.close();
        return appIdMaps;
    }

    /**
     * 根据租户id查询相关字典
     *
     * @param appId
     * @return
     */
    private Map<String, DictEntity> getAppMap(String appId) {
        Map<String, DictEntity> appIdMaps = new HashMap<>();
        ScanOptions options = new ScanOptions.ScanOptionsBuilder()
                .match(appId + RedisConstant.DIVISION + RedisConstant.WILDCARD)
                .count(100)
                .build();
        Cursor<Map.Entry<String, DictEntity>> cursor = redisUtils.hashScan(RedisConstant.SYS_DICT_CACHE, options);
        Map.Entry<String, DictEntity> entry = null;
        DictEntity value = null;
        while (cursor.hasNext()) {
            entry = cursor.next();
            value = entry.getValue();
            appIdMaps.putIfAbsent(value.getDictCode(), value);
        }
        cursor.close();
        return appIdMaps;
    }

    /**
     * 根据租户id和父code查询相关字典
     *
     * @param appId
     * @param code
     * @return
     */
    public Map<String, DictEntity> getDict(String appId, String code) {
        Map<String, DictEntity> appIdMaps = new HashMap<>();
        ScanOptions options = new ScanOptions.ScanOptionsBuilder()
                .match(appId + RedisConstant.DIVISION + RedisConstant.WILDCARD + RedisConstant.DIVISION + code)
                .count(100)
                .build();
        Cursor<Map.Entry<String, DictEntity>> cursor = redisUtils.hashScan(RedisConstant.SYS_DICT_CACHE, options);
        Map.Entry<String, DictEntity> entry = null;
        DictEntity value = null;
        while (cursor.hasNext()) {
            entry = cursor.next();
            value = entry.getValue();
            appIdMaps.putIfAbsent(value.getDictCode(), value);
        }
        cursor.close();
        return appIdMaps;
    }
}
