using System.Text.Json;
using Application.Abstractions.Cache;
using Application.Abstractions.YouTube;
using StackExchange.Redis;

namespace Infrastructure.YouTube;

internal sealed class YouTubeChannelCache(IConnectionMultiplexer redis) : IYouTubeChannelCache
{
    private static readonly TimeSpan CacheTtl = TimeSpan.FromHours(24);

    public async Task SetAsync(YouTubeChannelInfo info)
    {
        var db = redis.GetDatabase();
        var key = CacheKeys.YouTubeChannel(info.ChannelID);
        var json = JsonSerializer.Serialize(info);

        await db.StringSetAsync(key, json, CacheTtl);
    }

    public async Task<YouTubeChannelInfo?> GetAsync(string channelID)
    {
        var db = redis.GetDatabase();
        var key = CacheKeys.YouTubeChannel(channelID);
        var json = await db.StringGetAsync(key);

        if (json.IsNullOrEmpty)
        {
            return null;
        }

        return JsonSerializer.Deserialize<YouTubeChannelInfo>((string)json!);
    }

    public async Task<Dictionary<string, YouTubeChannelInfo>> GetManyAsync(IEnumerable<string> channelIds)
    {
        var db = redis.GetDatabase();
        var ids = channelIds.ToList();
        var keys = ids.Select(id => (RedisKey)CacheKeys.YouTubeChannel(id)).ToArray();
        var values = await db.StringGetAsync(keys);

        var result = new Dictionary<string, YouTubeChannelInfo>();
        for (var i = 0; i < ids.Count; i++)
        {
            if (!values[i].IsNullOrEmpty)
            {
                var info = JsonSerializer.Deserialize<YouTubeChannelInfo>((string)values[i]!);
                if (info is not null)
                {
                    result[ids[i]] = info;
                }
            }
        }

        return result;
    }

    public async Task RemoveAsync(string channelID)
    {
        var db = redis.GetDatabase();
        var key = CacheKeys.YouTubeChannel(channelID);
        await db.KeyDeleteAsync(key);
    }
}