using Furion.JsonSerialization;
using Microsoft.Extensions.Caching.Distributed;
using System.Text;
using YBEE.EQM.Core;

namespace YBEE.EQM.Application;

/// <summary>
/// 缓存服务
/// </summary>
public class CacheService : ICacheService, ISingleton
{
    private readonly IDistributedCache _cache;

    public CacheService(IDistributedCache cache)
    {
        _cache = cache;
    }

    /// <summary>
    /// 获取数据范围缓存（机构Id集合）
    /// </summary>
    /// <param name="userId"></param>
    /// <returns></returns>
    public async Task<List<int>> GetDataScope(int userId)
    {
        var cacheKey = $"{CommonConst.CACHE_KEY_DATASCOPE}{userId}";
        var res = await _cache.GetStringAsync(cacheKey);
        return string.IsNullOrWhiteSpace(res) ? null : JSON.Deserialize<List<int>>(res);
    }

    /// <summary>
    /// 缓存数据范围（机构Id集合）
    /// </summary>
    /// <param name="userId"></param>
    /// <param name="dataScopes"></param>
    /// <returns></returns>
    public async Task SetDataScope(int userId, List<int> dataScopes)
    {
        var cacheKey = $"{CommonConst.CACHE_KEY_DATASCOPE}{userId}";
        await _cache.SetStringAsync(cacheKey, JSON.Serialize(dataScopes));

        await AddCacheKey(cacheKey);
    }

    #region Permission
    /// <summary>
    /// 获取权限缓存（按钮）
    /// </summary>
    /// <param name="userId"></param>
    /// <returns></returns>
    public async Task<List<string>> GetPermission(int userId)
    {
        var cacheKey = $"{CommonConst.CACHE_KEY_PERMISSION}{userId}";
        var res = await _cache.GetStringAsync(cacheKey);
        return string.IsNullOrWhiteSpace(res) ? null : JSON.Deserialize<List<string>>(res);
    }
    /// <summary>
    /// 删除权限缓存
    /// </summary>
    /// <param name="userId"></param>
    /// <returns></returns>
    public async Task RemovePermission(int userId)
    {
        var cacheKey = $"{CommonConst.CACHE_KEY_PERMISSION}{userId}";
        await RemoveAsync(cacheKey);
    }
    /// <summary>
    /// 缓存权限
    /// </summary>
    /// <param name="userId"></param>
    /// <param name="permissions"></param>
    /// <returns></returns>
    public async Task SetPermission(int userId, List<string> permissions)
    {
        var cacheKey = $"{CommonConst.CACHE_KEY_PERMISSION}{userId}";
        await _cache.SetStringAsync(cacheKey, JSON.Serialize(permissions));

        await AddCacheKey(cacheKey);
    }
    #endregion

    #region 角色数据范围权限缓存
    /// <summary>
    /// 获取角色数据范围权限缓存
    /// </summary>
    /// <param name="userId"></param>
    /// <returns></returns>
    public async Task<List<SysRoleOutput>> GetRoleDataScope(int userId)
    {
        var cacheKey = $"{CommonConst.CACHE_KEY_ROLE_DATASCOPE}{userId}";
        var res = await _cache.GetStringAsync(cacheKey);
        return string.IsNullOrWhiteSpace(res) ? null : JSON.Deserialize<List<SysRoleOutput>>(res);
    }
    /// <summary>
    /// 删除角色数据范围权限缓存
    /// </summary>
    /// <param name="userId"></param>
    /// <returns></returns>
    public async Task RemoveRoleDataScope(int userId)
    {
        var cacheKey = $"{CommonConst.CACHE_KEY_ROLE_DATASCOPE}{userId}";
        await RemoveAsync(cacheKey);
    }
    /// <summary>
    /// 缓存角色数据范围权限
    /// </summary>
    /// <param name="userId"></param>
    /// <param name="roles"></param>
    /// <returns></returns>
    public async Task SetRoleDataScope(int userId, List<SysRoleOutput> roles)
    {
        var cacheKey = $"{CommonConst.CACHE_KEY_ROLE_DATASCOPE}{userId}";
        await _cache.SetStringAsync(cacheKey, JSON.Serialize(roles));

        await AddCacheKey(cacheKey);
    }
    #endregion

    /// <summary>
    /// 获取所有缓存关键字
    /// </summary>
    /// <returns></returns>
    //[HttpGet("sysCache/keyList")]
    public async Task<List<string>> GetAllCacheKeys()
    {
        var res = await _cache.GetStringAsync(CommonConst.CACHE_KEY_ALL);
        return string.IsNullOrWhiteSpace(res) ? null : JSON.Deserialize<List<string>>(res);
    }

    /// <summary>
    /// 删除指定关键字缓存
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    //[HttpGet("sysCache/remove")]
    public async Task RemoveAsync(string key)
    {
        await _cache.RemoveAsync(key);

        await DelCacheKey(key);
    }

    /// <summary>
    /// 删除某特征关键字缓存
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public async Task DelByPatternAsync(string key)
    {
        var allkeys = await GetAllCacheKeys();
        var delAllkeys = allkeys?.Where(u => u.Contains(key)).ToList();

        // 删除相应的缓存
        delAllkeys?.ForEach(u =>
        {
            _cache.Remove(u);
        });

        // 更新所有缓存键
        allkeys = allkeys?.Where(u => !u.Contains(key)).ToList();
        await _cache.SetStringAsync(CommonConst.CACHE_KEY_ALL, JSON.Serialize(allkeys));
    }

    /// <summary>
    /// 设置缓存
    /// </summary>
    /// <param name="cacheKey"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    public async Task SetAsync(string cacheKey, object value)
    {
        await _cache.SetAsync(cacheKey, Encoding.UTF8.GetBytes(JSON.Serialize(value)));

        await AddCacheKey(cacheKey);
    }

    /// <summary>
    /// 设置缓存
    /// </summary>
    /// <param name="cacheKey"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    public async Task SetStringAsync(string cacheKey, string value)
    {
        await _cache.SetStringAsync(cacheKey, value);

        await AddCacheKey(cacheKey);
    }

    /// <summary>
    /// 获取缓存
    /// </summary>
    /// <param name="cacheKey"></param>
    /// <returns></returns>
    //[HttpGet("sysCache/detail")]
    public async Task<string> GetStringAsync(string cacheKey)
    {
        return await _cache.GetStringAsync(cacheKey);
    }

    /// <summary>
    /// 获取缓存
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="cacheKey"></param>
    /// <returns></returns>
    public async Task<T> GetAsync<T>(string cacheKey)
    {
        var res = await _cache.GetAsync(cacheKey);
        return res == null ? default : JSON.Deserialize<T>(Encoding.UTF8.GetString(res));
    }

    /// <summary>
    /// 检查给定 key 是否存在
    /// </summary>
    /// <param name="cacheKey">键</param>
    /// <returns></returns>
    public bool Exists(string cacheKey)
    {
        var res = _cache.GetStringAsync(CommonConst.CACHE_KEY_ALL).GetAwaiter().GetResult();
        var allkeys = string.IsNullOrWhiteSpace(res) ? new HashSet<string>() : JSON.Deserialize<HashSet<string>>(res);
        return allkeys.Any(_ => _ == cacheKey);
    }

    /// <summary>
    /// 增加缓存Key
    /// </summary>
    /// <param name="cacheKey"></param>
    /// <returns></returns>
    public async Task AddCacheKey(string cacheKey)
    {
        var res = await _cache.GetStringAsync(CommonConst.CACHE_KEY_ALL);
        var allkeys = string.IsNullOrWhiteSpace(res) ? new HashSet<string>() : JSON.Deserialize<HashSet<string>>(res);
        if (!allkeys.Any(m => m == cacheKey))
        {
            allkeys.Add(cacheKey);
            await _cache.SetStringAsync(CommonConst.CACHE_KEY_ALL, JSON.Serialize(allkeys));
        }
    }

    /// <summary>
    /// 按KEY删除缓存
    /// </summary>
    /// <param name="cacheKey"></param>
    /// <returns></returns>
    public async Task DelCacheKey(string cacheKey)
    {
        var res = await _cache.GetStringAsync(CommonConst.CACHE_KEY_ALL);
        var allkeys = string.IsNullOrWhiteSpace(res) ? new HashSet<string>() : JSON.Deserialize<HashSet<string>>(res);
        if (allkeys.Any(m => m == cacheKey))
        {
            allkeys.Remove(cacheKey);
            await _cache.SetStringAsync(CommonConst.CACHE_KEY_ALL, JSON.Serialize(allkeys));
        }
    }

    /// <summary>
    /// 获取菜单缓存
    /// </summary>
    /// <param name="userId"></param>
    /// <returns></returns>
    public async Task<List<AntMenuOutput>> GetMenu(int userId)
    {
        var cacheKey = $"{CommonConst.CACHE_KEY_MENU}{userId}";
        var res = await _cache.GetStringAsync(cacheKey);
        return string.IsNullOrWhiteSpace(res) ? null : JSON.Deserialize<List<AntMenuOutput>>(res);
    }

    /// <summary>
    /// 缓存菜单
    /// </summary>
    /// <param name="userId"></param>
    /// <param name="menus"></param>
    /// <returns></returns>
    public async Task SetMenu(int userId, List<AntMenuOutput> menus)
    {
        var cacheKey = $"{CommonConst.CACHE_KEY_MENU}{userId}";
        await _cache.SetStringAsync(cacheKey, JSON.Serialize(menus));

        await AddCacheKey(cacheKey);
    }
}