package com.ruoyi.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.solon.service.impl.ServiceImpl;
import com.ruoyi.common.constants.CacheConstant;
import com.ruoyi.common.enums.DictEnum;
import com.ruoyi.common.utils.RedisUtil;
import com.ruoyi.system.domain.SysDictData;
import com.ruoyi.system.mapper.SysDictDataMapper;
import com.ruoyi.system.service.ISysDictDataService;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 数据字典 服务层实现
 * @author ruoyi
 */
@Component
public class SysDictDataServiceImpl extends ServiceImpl<SysDictDataMapper, SysDictData> implements ISysDictDataService {

    @Inject
    SysDictDataMapper sysDictDataMapper;

    @Inject
    RedisUtil redisUtil;

    /**
     * 根据字典类型查询数据字典
     * @param dictType
     */
    @Override
    public List<SysDictData> getDataByType(String dictType) {
        String cacheKey = getCacheKey(dictType);
        List<SysDictData> cacheList = redisUtil.getCacheList(cacheKey);
        if(CollectionUtil.isNotEmpty(cacheList)) {
            return cacheList;
        } else {
            List<SysDictData> list = getData(dictType);
            if(CollectionUtil.isNotEmpty(list)) {
                redisUtil.deleteCacheList(cacheKey);
                redisUtil.setCacheList(cacheKey, list);
                return list;
            } else {
                return new ArrayList<>();
            }
        }
    }

    /**
     * 统计字典数据
     * @param dictType
     * @return
     */
    @Override
    public long countDictDataByType(String dictType) {
        QueryWrapper qw = QueryWrapper.create();
        qw.where(SysDictData::getDictType).eq(dictType);
        return sysDictDataMapper.selectCountByQuery(qw);
    }

    /**
     * 新增数据字典
     * @param sysDictData
     * @return
     */
    @Override
    public int add(SysDictData sysDictData) {
        int row = sysDictDataMapper.insert(sysDictData);
        if(row > 0) {
            cacheDictDataType(sysDictData.getDictType());
        }
        return row;
    }

    /**
     * 修改数据字典
     * @param sysDictData
     * @return
     */
    @Override
    public int edit(SysDictData sysDictData) {
        int row = sysDictDataMapper.update(sysDictData);
        if (row > 0) {
            cacheDictDataType(sysDictData.getDictType());
        }
        return row;
    }

    /**
     * 修改字典类型
     * @param oldDictType
     * @param newDictType
     * @param cache 是否缓存
     */
    @Override
    public void updateDictDataType(String oldDictType, String newDictType, boolean cache) {
        SysDictData sysDictData = new SysDictData();
        sysDictData.setDictType(newDictType);
        QueryWrapper qw = QueryWrapper.create();
        qw.where(SysDictData::getDictType).eq(oldDictType);
        sysDictDataMapper.updateByQuery(sysDictData, qw);
        if(cache) {
            cacheDictDataType(newDictType);
        }
    }

    /**
     * 缓存数据字典
     * @param dictType
     */
    @Override
    public void cacheDictDataType(String dictType) {
        List<SysDictData> list = getData(dictType);
        String cacheKey = getCacheKey(dictType);
        redisUtil.deleteCacheList(cacheKey);
        redisUtil.setCacheList(cacheKey, list);
    }

    /**
     * 删除数据字典
     * @param dictCodes
     */
    @Override
    public void delete(List<Long> dictCodes) {
        List<SysDictData> list = sysDictDataMapper.selectListByIds(dictCodes);
        for (SysDictData sysDictData : list) {
            sysDictDataMapper.deleteById(sysDictData.getDictCode());
            cacheDictDataType(sysDictData.getDictType());
        }
    }

    /**
     * 缓存所有数据字典
     */
    public void loadingDictCache() {
        QueryWrapper qw = QueryWrapper.create();
        qw.where(SysDictData::getStatus).eq(DictEnum.COMMON_STATUS.OK.getValue());
        List<SysDictData> list = sysDictDataMapper.selectListByQuery(qw);
        Map<String, List<SysDictData>> dictDataMap = list.stream().collect(Collectors.groupingBy(SysDictData::getDictType));
        redisUtil.deleteCacheListAll(getCacheKey("*"));
        for (Map.Entry<String, List<SysDictData>> entry : dictDataMap.entrySet()) {
            redisUtil.setCacheList(getCacheKey(entry.getKey()), entry.getValue().stream().sorted(Comparator.comparing(SysDictData::getDictSort)).collect(Collectors.toList()));
        }
    }

    private List<SysDictData> getData(String dictType) {
        QueryWrapper qw = QueryWrapper.create();
        qw.and(SysDictData::getDictType).eq(dictType);
        qw.and(SysDictData::getStatus).eq(DictEnum.COMMON_STATUS.OK.getValue());
        qw.orderBy(SysDictData::getDictSort).asc();
        return sysDictDataMapper.selectListByQuery(qw);
    }

    private String getCacheKey(String key) {
        return CacheConstant.SYS_DICT_KEY + key;
    }

}
