package cn.com.capcloud.core.system.configuration;

import cn.com.capcloud.core.util.MinioUtils;
import cn.com.capcloud.core.websocket.RedisSubscription;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author LiaoJiaHui
 * @Create 2025/5/29
 */
@Configuration
@EnableCaching
public class CacheConfig {
    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(MinioUtils.class);

    @Value("${rzth.cache.type:local}")  // 从配置文件中读取缓存类型，默认为 "local"
    private String cacheType;

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        if ("redis".equalsIgnoreCase(cacheType)) {
            // 如果配置了 "redis"，使用 Redis 缓存
            logger.info("缓存类型： Redis 缓存");
            return redisCacheManager(redisConnectionFactory);
        } else {
            // 否则，使用本地缓存
            logger.info("缓存类型： Local 缓存");
            return localCacheManager();
        }
    }

    private CacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
        //初始化一个RedisCacheWriter
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
        //设置CacheManager的key序列化方式为json序列化
        RedisSerializer<String> strSerialize = new StringRedisSerializer();
        RedisSerializationContext.SerializationPair<String> strSerializePair = RedisSerializationContext.SerializationPair.fromSerializer(strSerialize);
        //设置CacheManager的值序列化方式为json序列化
        RedisSerializer<Object> jsonSerializer = new GenericJackson2JsonRedisSerializer();
        RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair
                .fromSerializer(jsonSerializer);
        RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig()
                // 设置过期时间 60*60*2 = 2小时|120分钟
                .entryTtl(Duration.ofSeconds(60*60*2))
                // 设置 value 序列化
                .serializeValuesWith(pair)
                //禁止缓存null
                //.disableCachingNullValues()
                ;
        return new RedisConfigCacheManager(redisCacheWriter, defaultCacheConfig);
    }

    // 正则表达式，提取 value 中的过期时间部分
    private static final Pattern EXPIRY_PATTERN = Pattern.compile("(\\w+)#(\\d+)");

    public CacheManager localCacheManager() {
        return new ConcurrentMapCacheManager() {
            @Override
            protected Cache createConcurrentMapCache(String name) {
                // 默认的过期时间为2小时
                long expireAfterWriteSeconds = 2 * 60 * 60;

                // 使用正则解析 value 中的过期时间
                Matcher matcher = EXPIRY_PATTERN.matcher(name);
                if (matcher.find()) {
                    expireAfterWriteSeconds = Long.parseLong(matcher.group(2)); // 提取过期时间
                    name = matcher.group(1); // 提取缓存名称部分
                }

                return new ExpiringCache(name, expireAfterWriteSeconds); // 创建自定义的缓存对象
            }
        };
    }

    @Bean
    @ConditionalOnProperty(name = "rzth.cache.type", havingValue = "redis", matchIfMissing = false)
    MessageListenerAdapter messageListenerAdapter(RedisSubscription redisSubscription) {
        return new MessageListenerAdapter(redisSubscription, "onMessage");
    }

    @Bean
    @ConditionalOnProperty(name = "rzth.cache.type", havingValue = "redis", matchIfMissing = false)
    StringRedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        return new StringRedisTemplate(redisConnectionFactory);
    }

}
