using Microsoft.Extensions.Caching.Memory;
using System.Collections.Concurrent;

namespace TakeoutSaaS.Infrastructure.Dictionary.Caching;

/// <summary>
/// 本地内存缓存封装。
/// </summary>
public sealed class MemoryCacheService(IMemoryCache cache)
{
    private readonly ConcurrentDictionary<string, byte> _keys = new(StringComparer.Ordinal);

    /// <summary>
    /// 读取缓存。
    /// </summary>
    public Task<T?> GetAsync<T>(string key, CancellationToken cancellationToken = default)
    {
        return Task.FromResult(cache.TryGetValue(key, out T? value) ? value : default);
    }

    /// <summary>
    /// 写入缓存。
    /// </summary>
    public Task SetAsync<T>(string key, T value, TimeSpan ttl, CancellationToken cancellationToken = default)
    {
        cache.Set(key, value, new MemoryCacheEntryOptions
        {
            SlidingExpiration = ttl
        });
        _keys.TryAdd(key, 0);
        return Task.CompletedTask;
    }

    /// <summary>
    /// 删除缓存键。
    /// </summary>
    public void Remove(string key)
    {
        cache.Remove(key);
        _keys.TryRemove(key, out _);
    }

    /// <summary>
    /// 按前缀删除缓存键。
    /// </summary>
    public void RemoveByPrefix(string prefix)
        => RemoveByPrefixWithCount(prefix);

    /// <summary>
    /// 按前缀删除缓存键并返回数量。
    /// </summary>
    public int RemoveByPrefixWithCount(string prefix)
    {
        if (string.IsNullOrWhiteSpace(prefix))
        {
            return 0;
        }

        var removed = 0;
        foreach (var key in _keys.Keys)
        {
            if (key.StartsWith(prefix, StringComparison.Ordinal))
            {
                Remove(key);
                removed += 1;
            }
        }

        return removed;
    }

    /// <summary>
    /// 清理所有缓存。
    /// </summary>
    public void Clear()
    {
        foreach (var key in _keys.Keys)
        {
            Remove(key);
        }
    }
}
