package cn.ey.biz.module.system.dal.redis.category;

import cn.ey.biz.common.util.collection.CollectionUtils;
import cn.ey.biz.common.util.json.JsonUtils;
import cn.ey.biz.module.system.api.category.dto.CategoryDataV2ReqDTO;
import cn.ey.biz.module.system.api.category.dto.CategoryDataV2RespDTO;
import cn.ey.biz.module.system.dal.dataobject.category.CategoryDataDO;
import cn.ey.biz.module.system.dal.redis.RedisKeyConstants;
import cn.ey.biz.module.system.enums.ErrorCodeConstants;
import cn.hutool.core.util.StrUtil;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import static cn.ey.biz.common.exception.util.ServiceExceptionUtil.exception;

/**
 * {@link CategoryDataDO} 的 RedisDAO
 */
@Repository
public class CategoryRedisDAO {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private RedissonClient redissonClient;

    public List<CategoryDataV2RespDTO> getCategoryData(CategoryDataV2ReqDTO req) {
        String redisKey = formatPublicDictDataKey(JsonUtils.toJsonString(req));
        return JsonUtils.parseArray(stringRedisTemplate.opsForValue().get(redisKey), CategoryDataV2RespDTO.class);
    }

    public void set(String queryKeyString, List<CategoryDataV2RespDTO> value) {
        String redisKey = formatPublicDictDataKey(queryKeyString);
        stringRedisTemplate.opsForValue().set(redisKey, JsonUtils.toJsonString(value));
    }

    public void delete(String queryKeyString) {
        String redisKey = formatPublicDictDataKey(queryKeyString);
        stringRedisTemplate.delete(redisKey);
    }

    public void deleteList(Collection<String> queryKeyList) {
        List<String> redisKeys = CollectionUtils.convertList(queryKeyList, CategoryRedisDAO::formatPublicDictDataKey);
        stringRedisTemplate.delete(redisKeys);
    }

    private static String formatPublicDictDataKey(String key) {
        return String.format(RedisKeyConstants.DICT_PUBLIC_DATA.getKeyTemplate(), key);
    }

    public void deleteGroup(String groupKey) {
        Set<String> keys = stringRedisTemplate.keys(groupKey + ":*");
        if (keys != null) {
            stringRedisTemplate.delete(keys);
        }
    }

    public Long getCategoryVersion(String prefix) {
        String key = RedisKeyConstants.DICT_VERSION.formatKey(prefix);
        long increNum;
        try {
            RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
            increNum = atomicLong.incrementAndGet();
        } catch (Exception e) {
            throw exception(ErrorCodeConstants.CATEGORY_DATA_CREATE_VERSION_ERROR);
        }
        return increNum;
    }

    public RLock getCategoryVersionLock(String suffix) {
        String lockKey = StrUtil.join(StrUtil.COLON, RedisKeyConstants.DICT_VERSION_LOCK_PREFIX, suffix);
        return redissonClient.getLock(lockKey);
    }
}
