using Bogus;

using CloudGaming.Code.DataAccess;

using Flurl;

using HuanMeng.DotNetCore.CacheHelper;
using HuanMeng.DotNetCore.CacheHelper.Contract;

using Microsoft.Extensions.Caching.Memory;

using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models;

using StackExchange.Redis;

using System.Collections.Concurrent;

using static SKIT.FlurlHttpClient.Wechat.TenpayV3.ExtendedSDK.Global.Models.QueryPartnerRefundsResponse.Types;
using static SKIT.FlurlHttpClient.Wechat.TenpayV3.Models.CreateNewTaxControlFapiaoApplicationRequest.Types.Fapiao.Types;
using static System.Net.Mime.MediaTypeNames;

namespace CloudGaming.Code.Cache.Special;

/// <summary>
/// 图片缓存表  
/// 流程==》
/// 1.先去本地内存中去找，如果没找打则去找本地缓存默认的图
/// 2.如果本地默认的也没找到，则去redis中去找，如果redis中没找到当前语言，就去找redis默认的
/// </summary>
public class ImageEntityCache : ICacheClearData, ICacheReloadData, ICacheClearLocalData
{
    private readonly DAO dao;
    private readonly AppConfig appConfig;
    private readonly IDatabase database;
    /// <summary>
    /// 多语言列表
    /// </summary>
    private List<string> languages;
    /// <summary>
    /// 当前多语言
    /// </summary>
    private string languae;
    /// <summary>
    /// 本地内存图片缓存key
    /// </summary>
    private readonly string memoryCacheKey;

    /// <summary>
    /// Redis图片缓存key
    /// </summary>
    private readonly string redisKey = "cache:Image";

    /// <summary>
    /// 图片缓存数据
    /// </summary>
    private ConcurrentDictionary<int, string> imageData;

    public ImageEntityCache(DAO dao, AppConfig appConfig, IDatabase database, string language)
    {
        this.dao = dao;
        this.appConfig = appConfig;
        this.database = database;
        this.languae = language;
        languages = appConfig.GetLanguages();
        if (!languages.Contains(languae))
        {
            languae = appConfig.DefaultLanguage;
        }
        if (string.IsNullOrEmpty(languae))
        {
            languae = appConfig.DefaultLanguage;
        }
        this.memoryCacheKey = $"{appConfig.Identifier}:App:Image:{languae}";

    }
    /// <summary>
    /// 按语言和图片ID获取图片URL
    /// </summary>
    public string this[int imageId]
    {
        get
        {

            if (imageId == 0) return string.Empty;
            if (this.imageData == null)
            {
                var t = MemoryCacheHelper.GetCache<ConcurrentDictionary<int, string>>(memoryCacheKey);
                if (t == null)
                {
                    t = new ConcurrentDictionary<int, string>();
                    MemoryCacheHelper.SetCache(this.memoryCacheKey, t);
                }
                this.imageData = t;
            }
            var images = this.imageData;
            if (!images.TryGetValue(imageId, out var imageUrl))
            {
                imageUrl = LoadImageFromRedis(this.languae, imageId);
                if (!string.IsNullOrEmpty(imageUrl))
                {
                    images[imageId] = imageUrl;
                }
            }

            return imageUrl ?? string.Empty;
        }
    }


    private string LoadImageFromRedis(string language, int imageId)
    {
        var redisValue = database.StringGet($"{redisKey}:{language}:{imageId}");
        if (redisValue.IsNullOrEmpty)
        {
            redisValue = database.StringGet($"{redisKey}:default:{imageId}");
        }
        return redisValue;
    }

    private void LoadImagesFromDatabase()
    {
        var isadd = database.StringGet<List<string>>($"{redisKey}:language");
        if (isadd != null && isadd.Count > 0)
        {
            foreach (var _language in isadd)
            {
                var mKey = $"{appConfig.Identifier}:App:Image:{_language}";
                var imageRedis = database.StringGet<Dictionary<int, string>>($"{redisKey}:language:{_language}");
                //database.StringGet<>
                var imagex = new ConcurrentDictionary<int, string>(imageRedis ?? new Dictionary<int, string>());
                MemoryCacheHelper.SetCache(mKey, imagex);
            }
            return;
        }
        var data = new ConcurrentDictionary<string, ConcurrentDictionary<int, string>>();
        var images = dao.DaoExt.Context.T_App_Image
            .Where(it => !string.IsNullOrEmpty(it.Url))
            .AsNoTracking()
            .Select(it => new { it.ImageId, it.Language, it.Url })
            .ToList();
        // 设置默认语言
        if (string.IsNullOrEmpty(appConfig.DefaultLanguage))
        {
            appConfig.DefaultLanguage = "zh";
        }
        // 创建默认语言的图像字典
        var defaultImage = images
            .Where(it => it.Language == appConfig.DefaultLanguage)
            .GroupBy(it => it.ImageId)
            .ToDictionary(group => group.Key, group => appConfig.AliyunConfig.ImagePrefix + group.Last().Url);
        if (defaultImage == null)
        {
            defaultImage = new Dictionary<int, string>();
        }
        foreach (var image in images)
        {
            if (string.IsNullOrEmpty(image.Url))
            {
                continue;
            }
            var languageCache = data.GetOrAdd(image.Language, _ => new ConcurrentDictionary<int, string>());
            var url = string.Empty;
            if (image.Url.StartsWith("http://") || image.Url.StartsWith("https://"))
            {
                url = $"{image.Url}";
            }
            else
            {
                url = $"{appConfig.AliyunConfig.ImagePrefix}{image.Url}";
            }
            languageCache[image.ImageId] = url;
            // 如果默认图像字典中没有此ImageId，加入默认图像字典
            if (!defaultImage.ContainsKey(image.ImageId))
            {
                defaultImage[image.ImageId] = url;
            }
        }
        #region 保存默认图片
        var defaultLanguageCache = new ConcurrentDictionary<int, string>(defaultImage);
        foreach (var kv in defaultLanguageCache)
        {
            database.StringSet($"{redisKey}:default:{kv.Key}", kv.Value);
        }
        //data.TryAdd("default", defaultLanguageCache);
        #endregion
        #region 保存其他图片
        foreach (var _language in languages)
        {
            var mKey = $"{appConfig.Identifier}:App:Image:{_language}";
            if (!data.TryGetValue(_language, out var d))
            {
                d = defaultLanguageCache;
            }
            foreach (var kv in d)
            {
                database.StringSet($"{redisKey}:{_language}:{kv.Key}", kv.Value);
            }
            MemoryCacheHelper.SetCache(mKey, d, 60 * 60 * 24);
            database.StringSet($"{redisKey}:language:{_language}", d);
        }
        database.StringSet($"{redisKey}:language", languages);
        database.StringSet($"time:{redisKey.Replace(":", ".")}", $"刷新图片缓存时间{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
        #endregion
        return;
    }


    public void LoadRedisDatabase()
    {

        var data = new ConcurrentDictionary<string, ConcurrentDictionary<int, string>>();
        var images = dao.DaoExt.Context.T_App_Image
            .Where(it => !string.IsNullOrEmpty(it.Url))
            .AsNoTracking()
            .Select(it => new { it.ImageId, it.Language, it.Url })
            .ToList();
        // 设置默认语言
        if (string.IsNullOrEmpty(appConfig.DefaultLanguage))
        {
            appConfig.DefaultLanguage = "zh";
        }
        // 创建默认语言的图像字典
        var defaultImage = images
            .Where(it => it.Language == appConfig.DefaultLanguage)
            .GroupBy(it => it.ImageId)
            .ToDictionary(group => group.Key, group => appConfig.AliyunConfig.ImagePrefix + group.Last().Url);
        if (defaultImage == null)
        {
            defaultImage = new Dictionary<int, string>();
        }
        foreach (var image in images)
        {
            if (string.IsNullOrEmpty(image.Url))
            {
                continue;
            }
            var languageCache = data.GetOrAdd(image.Language, _ => new ConcurrentDictionary<int, string>());
            var url = string.Empty;
            if (image.Url.StartsWith("http://") || image.Url.StartsWith("https://"))
            {
                url = $"{image.Url}";
            }
            else
            {
                url = $"{appConfig.AliyunConfig.ImagePrefix}{image.Url}";
            }
            languageCache[image.ImageId] = url;
            // 如果默认图像字典中没有此ImageId，加入默认图像字典
            if (!defaultImage.ContainsKey(image.ImageId))
            {
                defaultImage[image.ImageId] = url;
            }
        }
        #region 保存默认图片
        var defaultLanguageCache = new ConcurrentDictionary<int, string>(defaultImage);
        foreach (var kv in defaultLanguageCache)
        {
            database.StringSet($"{redisKey}:default:{kv.Key}", kv.Value);
        }
        //data.TryAdd("default", defaultLanguageCache);
        #endregion
        #region 保存其他图片
        foreach (var _language in languages)
        {
            var mKey = $"{appConfig.Identifier}:App:Image:{_language}";
            if (!data.TryGetValue(_language, out var d))
            {
                d = defaultLanguageCache;
            }
            foreach (var kv in d)
            {
                database.StringSet($"{redisKey}:{_language}:{kv.Key}", kv.Value);
            }
            database.StringSet($"{redisKey}:language:{_language}", d);
        }
        database.StringSet($"{redisKey}:language", languages);
        database.StringSet($"time:{redisKey.Replace(":", ".")}", $"刷新图片缓存时间{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
        #endregion
        return;
    }

    public bool ClearData()
    {

        foreach (var _language in languages)
        {
            var mKey = $"{appConfig.Identifier}:App:Image:{_language}";
            MemoryCacheHelper.cache.Remove(mKey);
        }


        return true;
    }

    public void ReloadData()
    {
        LoadImagesFromDatabase();
    }

    public bool ClearLocalData()
    {
        foreach (var _language in languages)
        {
            var mKey = $"{appConfig.Identifier}:App:Image:{_language}";
            MemoryCacheHelper.cache.Remove(mKey);
        }
        imageData = null;
        return true;
    }
}
