package com.unicorn.hgzero.meeting.infra.config;

import io.lettuce.core.ClientOptions;
import io.lettuce.core.SocketOptions;
import io.lettuce.core.TimeoutOptions;
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.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

/**
 * Redis 설정
 * Standalone 모드로 연결
 *
 * - ReadFrom 설정 제거: Master-Replica 자동 탐색 비활성화
 * - 로컬 개발 환경에서 Kubernetes 내부 DNS 해석 오류 방지
 */
@Configuration
@Slf4j
public class RedisConfig {

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

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

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

    @Value("${spring.data.redis.database:0}")
    private int redisDatabase;

    /**
     * Lettuce 클라이언트 설정
     * - Standalone 모드: ReadFrom 설정 제거로 Master-Replica 자동 탐색 비활성화
     * - AutoReconnect: 연결 끊김 시 자동 재연결
     * - DisconnectedBehavior.REJECT_COMMANDS: 연결 끊김 시 명령 거부
     */
    @Bean
    public LettuceClientConfiguration lettuceClientConfiguration() {

        // 소켓 옵션 설정
        SocketOptions socketOptions = SocketOptions.builder()
                .connectTimeout(Duration.ofSeconds(10))
                .keepAlive(true)
                .build();

        // 타임아웃 옵션 설정
        TimeoutOptions timeoutOptions = TimeoutOptions.builder()
                .fixedTimeout(Duration.ofSeconds(10))
                .build();

        // 클라이언트 옵션 설정
        ClientOptions clientOptions = ClientOptions.builder()
                .socketOptions(socketOptions)
                .timeoutOptions(timeoutOptions)
                .autoReconnect(true)
                .disconnectedBehavior(ClientOptions.DisconnectedBehavior.REJECT_COMMANDS)
                .build();

        // Lettuce 클라이언트 설정
        // ReadFrom 설정 제거: Standalone 모드로 동작, Master-Replica 자동 탐색 비활성화
        LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
                .clientOptions(clientOptions)
                .commandTimeout(Duration.ofSeconds(10))
                .build();

        log.info("Redis Lettuce Client 설정 완료 - Standalone 모드 (Master-Replica 자동 탐색 비활성화)");

        return clientConfig;
    }

    /**
     * LettuceConnectionFactory 설정
     * Standalone 설정과 Lettuce Client 설정 결합
     */
    @Bean
    public LettuceConnectionFactory redisConnectionFactory(LettuceClientConfiguration lettuceClientConfiguration) {

        // Standalone 설정
        RedisStandaloneConfiguration standaloneConfig = new RedisStandaloneConfiguration();
        standaloneConfig.setHostName(redisHost);
        standaloneConfig.setPort(redisPort);
        standaloneConfig.setPassword(redisPassword);
        standaloneConfig.setDatabase(redisDatabase);

        // LettuceConnectionFactory 생성
        LettuceConnectionFactory factory = new LettuceConnectionFactory(standaloneConfig, lettuceClientConfiguration);

        log.info("LettuceConnectionFactory 설정 완료 - Host: {}:{}, Database: {}",
                redisHost, redisPort, redisDatabase);

        return factory;
    }

    /**
     * RedisTemplate 설정
     * String Serializer 사용
     */
    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, String> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);

        // String Serializer 사용
        StringRedisSerializer stringSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringSerializer);
        template.setValueSerializer(stringSerializer);
        template.setHashKeySerializer(stringSerializer);
        template.setHashValueSerializer(stringSerializer);

        template.afterPropertiesSet();

        log.info("RedisTemplate 설정 완료");

        return template;
    }
}
