using AutoMapper;

using CloudGaming.Code.AppExtend;
using CloudGaming.Code.Cache.Special;
using CloudGaming.DtoModel;
using CloudGaming.DtoModel.Game;
using CloudGaming.DtoModel.Mall;
using CloudGaming.DtoModel.RedemptionCode;
using CloudGaming.DtoModel.SevenSign;

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

using System.Collections.Concurrent;
using System.Globalization;
using System.Linq.Expressions;

namespace CloudGaming.Code.Cache;

/// <summary>
/// 缓存数据表
/// </summary>
public class CloudGamingCache
{
    private readonly CloudGamingBase _gamingBase;

    public CloudGamingCache(CloudGamingBase gamingBase)
    {
        _gamingBase = gamingBase;
    }

    #region 通用缓存获取方法

    /// <summary>
    /// 通用缓存获取方法，适用于所有类型
    /// </summary>
    private List<T> GetCacheList<T>(ref CommonDataEntityCache<T>? cache, Expression<Func<T, bool>>? expWhere = null) where T : class
    {
        if (cache == null)
        {
            cache = CloudGamingCacheExtend.GetDataEntityCache(_gamingBase, expWhere);
        }
        return cache.DataList ?? new List<T>();
    }

    #endregion



    #region 配置缓存表

    private AppConfigEntityCache? _appConfigCache;
    /// <summary>
    /// 系统配置缓存表
    /// </summary>
    public AppConfigEntityCache AppConfigCache
    {
        get
        {
            if (_appConfigCache == null)
            {
                _appConfigCache = new AppConfigEntityCache(_gamingBase.Dao, _gamingBase.RedisCache, _gamingBase.Mapper, _gamingBase.AppConfig);
            }
            return _appConfigCache;
        }
    }
    /// <summary>
    /// 配置缓存列表
    /// </summary>
    public List<AppConfigCache> AppConfigList
    {
        get
        {
            return AppConfigCache.DataList ?? new List<AppConfigCache>();
        }
    }


    #endregion

    #region 首页缓存表

    private CommonDataEntityCache<T_Epg_CategoryCfg>? _epgCategoryCfg;

    /// <summary>
    /// 菜单分类
    /// </summary>
    public List<T_Epg_CategoryCfg> EpgCategoryCfg => GetCacheList(ref _epgCategoryCfg, it => it.IsOnline);
    #endregion


    private GameEntityCache? gameEntityCache;

    /// <summary>
    /// 游戏缓存
    /// </summary>
    public GameEntityCache GameEntityCache
    {
        get
        {
            if (gameEntityCache == null)
            {
                gameEntityCache = new GameEntityCache(_gamingBase.Dao, _gamingBase.RedisCache, _gamingBase.Mapper, _gamingBase.AppConfig);
            }
            return gameEntityCache;
        }
    }
    /// <summary>
    /// 游戏列表
    /// </summary>
    public List<GameInfo> GameInfos
    {
        get
        {

            return GameEntityCache?.DataList ?? new List<GameInfo>();
        }
    }

    #region 图片缓存

    /// <summary>
    /// 
    /// </summary>
    private ImageEntityCache appImageCache;

    /// <summary>
    /// 图片缓存 
    /// </summary>
    public ImageEntityCache AppImageCache
    {
        get
        {
            if (appImageCache == null)
            {
                appImageCache = new ImageEntityCache(_gamingBase.Dao, _gamingBase.AppConfig, _gamingBase.RedisCache, _gamingBase.AppRequestInfo.Language);
            }
            return appImageCache;
        }
    }
    #endregion

    /// <summary>
    /// 
    /// </summary>
    private ProductCacheEntityCache productCacheEntityCache;

    /// <summary>
    /// 产品缓存 
    /// </summary>
    public ProductCacheEntityCache ProductCacheEntityCache
    {
        get
        {
            if (productCacheEntityCache == null)
            {
                productCacheEntityCache = new ProductCacheEntityCache(_gamingBase.Dao, _gamingBase.RedisCache, _gamingBase.Mapper);
            }
            return productCacheEntityCache;
        }
    }

    /// <summary>
    /// 产品列表
    /// </summary>
    public List<ProductCache> ProductCacheList
    {
        get
        {

            return ProductCacheEntityCache.DataList ?? new List<ProductCache>();
        }
    }

    #region 七天签到
    /// <summary>
    /// 
    /// </summary>
    private SevenDayEntityCache sevenDayEntityCache;

    /// <summary>
    /// 七天签到缓存 
    /// </summary>
    public SevenDayEntityCache SevenDayEntityCache
    {
        get
        {
            if (sevenDayEntityCache == null)
            {
                sevenDayEntityCache = new SevenDayEntityCache(_gamingBase.Dao, _gamingBase.RedisCache, _gamingBase.Mapper);
            }
            return sevenDayEntityCache;
        }
    }

    /// <summary>
    /// 七天签到列表
    /// </summary>
    public List<SevenDayCache> SevenDayList
    {
        get
        {
            return SevenDayEntityCache.DataList ?? new List<SevenDayCache>();
        }
    }
    #endregion

    #region 兑换码
    /// <summary>
    /// 
    /// </summary>
    private RedemptionCodeEntityCache redemptionCodeEntityCache;

    /// <summary>
    /// 兑换码缓存 
    /// </summary>
    public RedemptionCodeEntityCache RedemptionCodeEntityCache
    {
        get
        {
            if (redemptionCodeEntityCache == null)
            {
                redemptionCodeEntityCache = new RedemptionCodeEntityCache(_gamingBase.Dao, _gamingBase.RedisCache, _gamingBase.Mapper);
            }
            return redemptionCodeEntityCache;
        }
    }

    /// <summary>
    /// 兑换码列表
    /// </summary>
    public List<RedemptionCodeCache> RedemptionCodeList
    {
        get
        {
            return RedemptionCodeEntityCache.DataList ?? new List<RedemptionCodeCache>();
        }
    }
    #endregion



}

/// <summary>
/// 游戏缓存扩展
/// </summary>
public static class CloudGamingCacheExtend
{
    public static readonly ConcurrentDictionary<Type, object> ExtCacheLockList = new ConcurrentDictionary<Type, object>();
    public static readonly ConcurrentDictionary<Type, object> GameCacheLockList = new ConcurrentDictionary<Type, object>();
    public static readonly ConcurrentDictionary<Type, object> AppCacheLockList = new ConcurrentDictionary<Type, object>();
    public static readonly ConcurrentDictionary<Type, object> UserCacheLockList = new ConcurrentDictionary<Type, object>();

    /// <summary>
    /// 命名空间与缓存映射
    /// </summary>
    private static readonly Dictionary<string, (ConcurrentDictionary<Type, object> cacheList, AppDataBaseType dbType)> NamespaceMapping;

    static CloudGamingCacheExtend()
    {
        NamespaceMapping = new Dictionary<string, (ConcurrentDictionary<Type, object> cacheList, AppDataBaseType dbType)>
        {
            { "CloudGaming.GameModel.Db.Db_Ext", (ExtCacheLockList, AppDataBaseType.Ext) },
            { "CloudGaming.GameModel.Db.Db_Game", (GameCacheLockList, AppDataBaseType.Game) },
            { "CloudGaming.Model.DbSqlServer.Db_Phone", (AppCacheLockList, AppDataBaseType.App) },
            { "CloudGaming.Model.DbSqlServer.Db_User", (UserCacheLockList, AppDataBaseType.User) }
        };
    }

    /// <summary>
    /// 清除本地缓存
    /// </summary>
    /// <param name="cloudGamingBase"></param>
    public static void ClearLocalDataCache(this CloudGamingBase cloudGamingBase)
    {

        foreach (var item in CloudGamingCacheExtend.ExtCacheLockList)
        {
            var c = cloudGamingBase.ToCacheBaseConfig(AppDataBaseType.Ext);
            var t = item.Key;
            Type cacheType = typeof(DataBaseEntityCache<>).MakeGenericType(t);
            var shujuduixiang = Activator.CreateInstance(cacheType, c, item.Value, 36000, null);
            var x = shujuduixiang as ICacheClearData;
            if (x != null)
            {
                x.ClearData();
            }
        }

        foreach (var item in CloudGamingCacheExtend.GameCacheLockList)
        {
            var c = cloudGamingBase.ToCacheBaseConfig(AppDataBaseType.Game);
            var t = item.Key;
            Type cacheType = typeof(DataBaseEntityCache<>).MakeGenericType(t);
            var shujuduixiang = Activator.CreateInstance(cacheType, c, item.Value, 36000, null);
            var x = shujuduixiang as ICacheClearData;
            if (x != null)
            {
                x.ClearData();
            }
        }

        foreach (var item in CloudGamingCacheExtend.AppCacheLockList)
        {
            var c = cloudGamingBase.ToCacheBaseConfig(AppDataBaseType.App);
            var t = item.Key;
            Type cacheType = typeof(DataBaseEntityCache<>).MakeGenericType(t);
            var shujuduixiang = Activator.CreateInstance(cacheType, c, item.Value, 36000, null);
            var x = shujuduixiang as ICacheClearData;
            if (x != null)
            {
                x.ClearData();
            }
        }

        foreach (var item in CloudGamingCacheExtend.UserCacheLockList)
        {
            var c = cloudGamingBase.ToCacheBaseConfig(AppDataBaseType.User);
            var t = item.Key;
            Type cacheType = typeof(DataBaseEntityCache<>).MakeGenericType(t);
            var shujuduixiang = Activator.CreateInstance(cacheType, c, item.Value, 36000);
            var x = shujuduixiang as ICacheClearData;
            if (x != null)
            {
                x.ClearData();
            }
        }
        cloudGamingBase.Cache.AppConfigCache.ClearLocalData();
        cloudGamingBase.Cache.ProductCacheEntityCache.ClearLocalData();
        cloudGamingBase.Cache.AppImageCache.ClearLocalData();
        cloudGamingBase.Cache.GameEntityCache.ClearLocalData();
        cloudGamingBase.Cache.RedemptionCodeEntityCache.ClearLocalData();
        cloudGamingBase.Cache.SevenDayEntityCache.ClearLocalData();
    }


    /// <summary>
    /// 重新加载本地缓存
    /// </summary>
    /// <param name="cloudGamingBase"></param>
    public static void ReloadLocalDataCache(this CloudGamingBase cloudGamingBase)
    {

        cloudGamingBase.Cache.AppConfigCache.ReloadData();
        cloudGamingBase.Cache.ProductCacheEntityCache.ReloadData();
        cloudGamingBase.Cache.AppImageCache.ReloadData();
        cloudGamingBase.Cache.GameEntityCache.ReloadData();
        cloudGamingBase.Cache.RedemptionCodeEntityCache.ReloadData();
        cloudGamingBase.Cache.SevenDayEntityCache.ReloadData();
    }


    /// <summary>
    /// 获取实体缓存
    /// </summary>
    public static CommonDataEntityCache<T> GetDataEntityCache<T>(CloudGamingBase cloudGamingBase, Expression<Func<T, bool>>? expWhere = null, int cacheTime = 36000) where T : class
    {
        var typeLock = typeof(T);
        var namespaceKey = typeLock.Namespace;

        if (namespaceKey == null || !NamespaceMapping.ContainsKey(namespaceKey))
        {
            throw new Exception($"缓存数据不存在或命名空间不匹配：{namespaceKey}");
        }

        var (cacheList, dbType) = NamespaceMapping[namespaceKey];
        object cacheLock = GetOrAddCacheLock(typeLock, cacheList);
        CacheBaseConfig cacheBaseConfig = cloudGamingBase.ToCacheBaseConfig(dbType);

        return new DataBaseEntityCache<T>(cacheBaseConfig, cacheLock, cacheTime, expWhere);
    }

    /// <summary>
    /// 获取或添加缓存锁对象
    /// </summary>
    private static object GetOrAddCacheLock(Type typeLock, ConcurrentDictionary<Type, object> cacheList)
    {
        return cacheList.GetOrAdd(typeLock, _ =>
        {
            Log($"没有找到锁对象 ==> {typeLock.Name}");
            return new object();
        });
    }

    /// <summary>
    /// 根据数据库类型生成缓存配置
    /// </summary>
    public static CacheBaseConfig ToCacheBaseConfig(this CloudGamingBase cloudGamingBase, AppDataBaseType appDataBaseType)
    {
        return appDataBaseType switch
        {
            AppDataBaseType.App => new CacheBaseConfig { AppConfig = cloudGamingBase.AppConfig, Mapper = cloudGamingBase.Mapper, DbContext = cloudGamingBase.Dao.DaoPhone.Context },
            AppDataBaseType.User => new CacheBaseConfig { AppConfig = cloudGamingBase.AppConfig, Mapper = cloudGamingBase.Mapper, DbContext = cloudGamingBase.Dao.DaoUser.Context },
            AppDataBaseType.Ext => new CacheBaseConfig { AppConfig = cloudGamingBase.AppConfig, Mapper = cloudGamingBase.Mapper, DbContext = cloudGamingBase.Dao.DaoExt.Context },
            AppDataBaseType.Game => new CacheBaseConfig { AppConfig = cloudGamingBase.AppConfig, Mapper = cloudGamingBase.Mapper, DbContext = cloudGamingBase.Dao.DaoGame.Context },
            _ => throw new Exception("未找到对应的数据连接")
        };
    }

    /// <summary>
    /// 日志方法
    /// </summary>
    private static void Log(string message)
    {
        // 替换为其他日志记录系统，例如 NLog, Serilog 等
        //Console.WriteLine(message);
    }
}
