package com.caliverse.admin.global.configuration;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;

import java.time.Duration;

@Slf4j
@Configuration
public class RedisConfig {

    @Value("${redis.host}")
    private String host;

    @Value("${redis.port}")
    private int port;

    @Value("${redis.password}")
    private String password;

    @Value("${redis.async-timeout}")
    private int asyncTimeout;

    @Value("${redis.sync-timeout}")
    private int syncTimeout;

    @Value("${redis.ssl}")
    private boolean ssl;

    @Value("${redis.abort-connect}")
    private boolean abortConnect;

    @Value("${spring.profiles.active}")
    private String activeProfile;

    @Bean
    public JedisConnectionFactory jedisConnectionFactory() {
//        String activeProfile = System.getProperty("active.profile", "local");
        log.info("RedisConfig Active profile: {}", activeProfile);

        if(activeProfile.equals("local") || activeProfile.equals("dev")){
            log.info("RedisConfig local config Set");
            /// Redis Standalone 설정
            RedisStandaloneConfiguration standaloneConfig = new RedisStandaloneConfiguration();
            standaloneConfig.setHostName(host);
            standaloneConfig.setPort(port);
            if (password != null && !password.isEmpty()) {
                standaloneConfig.setPassword(password);
            }

            JedisClientConfiguration.JedisClientConfigurationBuilder jedisClientConfig = JedisClientConfiguration.builder();
            jedisClientConfig.connectTimeout(java.time.Duration.ofMillis(asyncTimeout)); // AsyncTimeout
            jedisClientConfig.readTimeout(java.time.Duration.ofMillis(syncTimeout)); // SyncTimeout
            if (ssl) {
                jedisClientConfig.useSsl();
            }
            //if (!abortConnect) { jedisClientConfig.blockOnReconnect(false);}

            return new JedisConnectionFactory(standaloneConfig, jedisClientConfig.build());
        }

        log.info("RedisConfig deploy config Set");
        //cluster로 변경 수정
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(128); // 연결 풀 설정

        // Redis 클러스터 진입점 노드만 지정
        RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration();
        clusterConfig.clusterNode(host, port);
        clusterConfig.setPassword(password); // 패스워드 설정
        clusterConfig.setMaxRedirects(5);
        var builder = JedisClientConfiguration.builder();
        builder.usePooling().poolConfig(poolConfig);
        if(ssl){
            builder.useSsl();
        }
        JedisClientConfiguration clientConfig = builder.build();

        JedisConnectionFactory factory = new JedisConnectionFactory(clusterConfig, clientConfig);

        factory.afterPropertiesSet();

        try {
            factory.getConnection().ping(); // Redis 서버에 Ping 명령어를 전송해 응답을 확인
            log.info("Successfully connected to Redis server: {}", factory.getHostName());
        } catch (Exception e) {
            log.error("Failed to connect to Redis server: {}", e.getMessage());
        }

        return factory;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(jedisConnectionFactory());
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(new StringRedisSerializer());

        try {
            template.getConnectionFactory().getConnection().ping();
            log.info("redisTemplate Successfully connected to Redis server");
        } catch (Exception e) {
            log.error("redisTemplate Failed to connect to Redis server: {}", e.getMessage());
        }

        return template;
    }

    @Bean
    public RedisCacheManager cacheManager(JedisConnectionFactory jedisConnectionFactory) {
        RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofMinutes(60)) // 캐시 TTL 설정
                .disableCachingNullValues(); // null 값 캐싱 금지

        return RedisCacheManager.builder(jedisConnectionFactory)
                .cacheDefaults(cacheConfig)
                .build();
    }
}
