using HoneyBox.Core.Interfaces;

using Microsoft.Extensions.Configuration;

using StackExchange.Redis;

namespace HoneyBox.Infrastructure.Cache;

/// <summary>
/// Redis服务实现 - 提供更细粒度的Redis操作
/// </summary>
public class RedisService : IRedisService, IDisposable
{
    private readonly ConnectionMultiplexer? _connection;
    private readonly IDatabase? _database;
    private readonly bool _isConnected;

    public RedisService(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<string?> GetStringAsync(string key)
    {
        if (_database == null || !_isConnected)
            return null;

        var value = await _database.StringGetAsync(key);
        return value.IsNullOrEmpty ? null : value.ToString();
    }

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

        await _database.StringSetAsync(key, value, expiry, When.Always);
    }

    public async Task DeleteAsync(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 async Task<bool> ExpireAsync(string key, TimeSpan expiry)
    {
        if (_database == null || !_isConnected)
            return false;

        return await _database.KeyExpireAsync(key, expiry);
    }

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

        var ttl = await _database.KeyTimeToLiveAsync(key);
        return ttl.HasValue ? ttl.Value : null;
    }

    public async Task<bool> TryAcquireLockAsync(string key, string value, TimeSpan expiry)
    {
        if (_database == null || !_isConnected)
            return false;

        return await _database.StringSetAsync(key, value, expiry, When.NotExists);
    }

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

        var currentValue = await _database.StringGetAsync(key);
        if (currentValue.IsNullOrEmpty || currentValue.ToString() != value)
            return false;

        return await _database.KeyDeleteAsync(key);
    }

    public async Task<IEnumerable<string>> GetKeysAsync(string pattern)
    {
        if (_connection == null)
            return Enumerable.Empty<string>();

        // 检查当前连接状态（而不是构造时的状态）
        if (!_connection.IsConnected)
            return Enumerable.Empty<string>();

        var keys = new List<string>();
        var endpoints = _connection.GetEndPoints();

        foreach (var endpoint in endpoints)
        {
            var server = _connection.GetServer(endpoint);
            if (server == null || !server.IsConnected)
                continue;

            await foreach (var key in server.KeysAsync(pattern: pattern))
            {
                keys.Add(key.ToString());
            }
        }

        return keys;
    }

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