package com.tmerclub.cloud.common.cache.config;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.tmerclub.cloud.common.cache.bo.MultiRedisBO;
import com.tmerclub.cloud.common.exception.LuckException;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.redisson.spring.data.connection.RedissonConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * 多个redis管理
 * @author LGH
 */
@Component
@ConditionalOnProperty(value = "redis.multi.enable", havingValue = "true")
public class MultiRedisConfig implements DisposableBean {

    private static final Logger LOGGER = LoggerFactory.getLogger(MultiRedisConfig.class);

    private final List<StringRedisTemplate> stringRedisTemplates = new ArrayList<>();

    private final List<RedissonClient> redissonClients = new ArrayList<>();


    public MultiRedisConfig(MultiRedisBO multiRedis) {

        if (CollUtil.isEmpty(multiRedis.getRedisAddrs())) {
            throw new LuckException("请在yml配置好 multiRedis 的配置，见 com.tmerclub.cloud.common.cache.bo.MultiRedisBO");
        }

        Config config = new Config();

        SingleServerConfig singleServerConfig = config.useSingleServer();
        if (StrUtil.isNotBlank(multiRedis.getPassword())) {
            singleServerConfig.setPassword(multiRedis.getPassword());
        }
        if (multiRedis.getDatabase() != null) {
            singleServerConfig.setDatabase(multiRedis.getDatabase());
        } else {
            singleServerConfig.setDatabase(0);
        }

        for (String addr : multiRedis.getRedisAddrs()) {
            singleServerConfig.setAddress("redis://" + addr);
            initRedisConnection(config);
        }
    }

    private void initRedisConnection(Config config) {
        RedissonClient redisson = Redisson.create(config);
        LOGGER.info("创建redisson, redisson={}", redisson);

        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
        stringRedisTemplate.setConnectionFactory(new RedissonConnectionFactory(redisson));
        stringRedisTemplate.setValueSerializer(StringRedisSerializer.UTF_8);
        stringRedisTemplate.setKeySerializer(StringRedisSerializer.UTF_8);

        stringRedisTemplate.afterPropertiesSet();
        stringRedisTemplates.add(stringRedisTemplate);
        redissonClients.add(redisson);
    }

    public int getRedisCount() {
        return stringRedisTemplates.size();
    }

    public StringRedisTemplate getRedisByIndex(int index) {
        return stringRedisTemplates.get(index);
    }

    public int getIndex(Long userId) {
        int hashKey = Math.abs(userId.toString().hashCode());
        return hashKey % getRedisCount();
    }

    @Override
    public void destroy() throws Exception {
        for (RedissonClient redissonClient : redissonClients) {
            LOGGER.info("关闭redissonClient, redissonClient={}", redissonClient);
            redissonClient.shutdown();
        }
    }
}
