using System.Text.Json;
using Microsoft.Extensions.Configuration;
using StackExchange.Redis;

namespace HoneyBox.Infrastructure.Cache;

/// <summary>
/// Redis 缓存服务实现
/// </summary>
public class RedisCacheService : ICacheService, IDisposable
{
    private readonly ConnectionMultiplexer? _connection;
    private readonly IDatabase? _database;
    private readonly bool _isConnected;

    public RedisCacheService(IConfiguration configuration)
    {
        var connectionString = configuration.GetConnectionString("Redis") ?? "localhost:6379";
        
        try
        {
            var options = ConfigurationOptions.Parse(connectionString);
            options.AbortOnConnectFail = false;
            options.ConnectTimeout = 5000;
            
            _connection = ConnectionMultiplexer.Connect(options);
            _database = _connection.GetDatabase();
            _isConnected = _connection.IsConnected;
        }
        catch
        {
            _isConnected = false;
        }
    }

    public async Task<T?> GetAsync<T>(string key)
    {
        if (_database == null || !_isConnected)
            return default;

        var value = await _database.StringGetAsync(key);
        if (value.IsNullOrEmpty)
            return default;

        return JsonSerializer.Deserialize<T>(value.ToString());
    }


    public async Task SetAsync<T>(string key, T value, TimeSpan? expiry = null)
    {
        if (_database == null || !_isConnected)
            return;

        var json = JsonSerializer.Serialize(value);
        await _database.StringSetAsync(key, json, expiry,When.Always);
    }

    public async Task RemoveAsync(string key)
    {
        if (_database == null || !_isConnected)
            return;

        await _database.KeyDeleteAsync(key);
    }

    public async Task<bool> ExistsAsync(string key)
    {
        if (_database == null || !_isConnected)
            return false;

        return await _database.KeyExistsAsync(key);
    }

    public Task<bool> IsConnectedAsync()
    {
        return Task.FromResult(_connection?.IsConnected ?? false);
    }

    public void Dispose()
    {
        _connection?.Dispose();
    }
}
