using System.Text.Json;
using StackExchange.Redis;

namespace bitforum.Repository
{
    public record RedisConfig(string Host, int Port, string Password);

    public interface IRedisRepository
    {
        // 문자열 저장
        Task SetStringAsync(string key, string value, int expirationMinutes);

        // 문자열 조회
        Task<string?> GetStringAsync(string key);

        // 객체 저장 (JSON 직렬화)
        Task SetObjectAsync<T>(string key, T value, int expirationMinutes);

        // 객체 가져오기 (JSON 역직렬화)
        Task<T?> GetObjectAsync<T>(string key);

        // 삭제 메소드 추가
        Task<bool> DeleteAsync(string key);

        // 키 존재 여부 확인
        Task<bool> ExistsAsync(string key);

        // 모든 키 삭제
        Task ClearAllAsync();
    }

    public class RedisRepository: IRedisRepository
    {
        private readonly IDatabase _db;
        private readonly IConnectionMultiplexer _redis;
        private const int _expirationMinutes = 10;

        public RedisRepository(IConnectionMultiplexer redis)
        {
            _db = redis.GetDatabase();
            _redis = redis;
        }
    
        public async Task SetStringAsync(string key, string value, int expirationMinutes = _expirationMinutes)
        {
            await _db.StringSetAsync(key, value, TimeSpan.FromMinutes(expirationMinutes));
        }
      
        public async Task<string?> GetStringAsync(string key)
        {
            return await _db.StringGetAsync(key);
        }
        
        public async Task SetObjectAsync<T>(string key, T value, int expirationMinutes = _expirationMinutes)
        {
            string jsonData = JsonSerializer.Serialize(value);
            await _db.StringSetAsync(key, jsonData, TimeSpan.FromMinutes(expirationMinutes));
        }
      
        public async Task<T?> GetObjectAsync<T>(string key)
        {
            string? jsonData = await _db.StringGetAsync(key);
            return jsonData == null ? default : JsonSerializer.Deserialize<T>(jsonData);
        }

        public async Task<bool> DeleteAsync(string key)
        {
            return await _db.KeyDeleteAsync(key);
        }

        public async Task<bool> ExistsAsync(string key)
        {
            return await _db.KeyExistsAsync(key);
        }

        public async Task ClearAllAsync()
        {
            foreach (var endpoint in _redis.GetEndPoints())
            {
                await _redis.GetServer(endpoint).FlushDatabaseAsync();
            }
        }
    }
}
