using Mall.CacheKey;
using Mall.CacheManager.Base;
using Mall.CacheManager.DataStatistic;
using Mall.Common;
using Mall.Common.Plugin;
using Mall.Model.Extend.User;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Mall.CacheManager.User
{
    /// <summary>
    /// redis缓存（只适用于数据统计）
    /// </summary>
    public class UserReidsCache
    {
        static readonly RedisHelper redis = new RedisHelper(DataConstant.REDIS_DB2);

        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <param name="model"></param>
        public static void UserInfoSet(string cacheKey, UserInfo model, int JwtExpirTime)
        {
            try
            {
                TimeSpan ts = GetExpirTime(JwtExpirTime);
                redis.StringSet<UserInfo>(cacheKey, model, ts);
            }
            catch (Exception ex)
            {
                Common.Plugin.LogHelper.Write(ex, "UserInfoSet缓存设置失败");
            }
        }

        /// <summary>
        /// 获取缓存时长
        /// </summary>
        /// <param name="JwtExpirTime"></param>
        /// <returns></returns>
        private static TimeSpan GetExpirTime(int JwtExpirTime)
        {
            DateTime dt = DateTime.Now;
            DateTime dt2 = DateTime.Now;
            TimeSpan ts = dt.AddSeconds(JwtExpirTime) - dt2;
            return ts;
        }

        /// <summary>
        /// 判断key是否存在
        /// </summary>
        /// <param name="cacheKey"></param>
        /// <returns></returns>
        public static bool Exists(string cacheKey)
        {
            return redis.KeyExists(cacheKey);
        }

        /// <summary>
        /// 删除Key
        /// </summary>
        /// <param name="cacheKey"></param>
        /// <returns></returns>
        public static bool Delete(string UserId)
        {
            string cacheKey = UserModuleCacheKeyConfig.Applet_Login_Info + UserId;
            if (Exists(cacheKey))
            {
                return redis.KeyDelete(cacheKey);
            }
            return false;
        }

        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <param name="cacheKey"></param>
        /// <param name="Data"></param>
        /// <param name="JwtExpirTime"></param>
        public static void Set(string cacheKey, object Data, int JwtExpirTime)
        {
            try
            {
                TimeSpan ts = GetExpirTime(JwtExpirTime);
                redis.StringSet(cacheKey, Data, ts);
            }
            catch (Exception)
            {
            }
        }

        /// <summary>
        /// 商户信息仓储层对象
        /// </summary>
        private static readonly Mall.Repository.User.RB_TenantRepository tenantRepository = new Repository.User.RB_TenantRepository();

        /// <summary>
        /// 用户登录日志仓储层对象
        /// </summary>
        private static readonly Repository.User.RB_Login_LogRepository login_LogRepository = new Repository.User.RB_Login_LogRepository();

        /// <summary>
        /// 缓存用户OpenId
        /// </summary>
        /// <param name="TenantId">商户Id</param>
        /// <returns></returns>
        public static void SetMiniAppUsetOpenId(string cacheKey, MiniAppUserCache cacheModel)
        {
            try
            {
                TimeSpan ts = GetExpirTime(Config.JwtExpirTime);
                redis.StringSet<MiniAppUserCache>(cacheKey, cacheModel, ts);
            }
            catch (Exception ex)
            {
                Common.Plugin.LogHelper.Write(ex, "SetMiniAppUsetOpenId");
            }
        }

        /// <summary>
        /// 获取缓存用户OpenId
        /// </summary>
        /// <param name="TenantId">商户Id</param>
        /// <returns></returns>
        public static MiniAppUserCache GetMiniAppUsetOpenId(string cacheKey)
        {
            MiniAppUserCache miniAppUserCache = null;
            try
            {
                miniAppUserCache =  redis.StringGet<MiniAppUserCache>(cacheKey);
            }
            catch (Exception ex)
            {
                Common.Plugin.LogHelper.Write(ex, "SetMiniAppUsetOpenId");
            }
            return miniAppUserCache;
        }

        /// <summary>
        /// 删除OpenId缓存
        /// </summary>
        /// <param name="TenantId">商户Id</param>
        /// <returns></returns>
        public static void DeleteMiniAppUsetOpenId(string cacheKey)
        {
            try
            {
                redis.KeyDelete(cacheKey);
            }
            catch (Exception ex)
            {
                Common.Plugin.LogHelper.Write(ex, "DeleteMiniAppUsetOpenId");
            }
     
        }

        /// <summary>
        /// 获取用户登录信息
        /// </summary>
        /// <param name="TenantId">商户Id</param>
        /// <returns></returns>
        public static UserInfo GetUserLoginInfo(object TenantId)
        {
            UserInfo userInfo = null;
            if (TenantId != null)
            {
                string cacheKey = UserModuleCacheKeyConfig.Mall_Login_Info + TenantId.ToString();
                try
                {
                    userInfo = redis.StringGet<UserInfo>(cacheKey);
                }
                catch (Exception ex)
                {
                    LogHelper.Write(ex, "GetUserLoginInfo");
                }
                if (userInfo == null)
                {
                    Int32.TryParse(TenantId.ToString(), out int NewTenantId);
                    if (NewTenantId > 0)
                    {
                        string token = "";
                        var extModel = tenantRepository.GetEntity<RB_Tenant_Extend>(NewTenantId);
                        if (extModel != null)
                        {
                            userInfo = new UserInfo
                            {
                                TenantId = extModel.TenantId,
                                Account = extModel.Account,
                                Name = extModel.Name,
                                MobilePhone = extModel.MobilePhone,
                                WeChatNum = extModel.WeChatNum,
                                IsEffective = extModel.IsEffective,
                                AccountValidate = extModel.AccountValidate,
                                CreateMiniPrograme = extModel.CreateMiniPrograme,
                                //MallName = extModel.MallName,
                                AccountStatus = extModel.AccountStatus,
                                Token = token,
                                SecretKey = "",
                            };
                            UserInfoSet(UserModuleCacheKeyConfig.Mall_Login_Info + TenantId, userInfo, Config.JwtExpirTime);
                        }
                    }
                }
            }
            else
            {
                userInfo = new UserInfo();
            }

            return userInfo;
        }

        /// <summary>
        /// 设置小程序用户缓存
        /// </summary>
        /// <param name="model"></param>
        public static void AppletUserInfoSet(string cacheKey, AppletUserInfo model, int JwtExpirTime)
        {
            try
            {
                TimeSpan ts = GetExpirTime(JwtExpirTime);
                redis.StringSet<AppletUserInfo>(cacheKey, model, ts);
                try
                {
                    login_LogRepository.Insert(new Model.Entity.User.RB_Login_Log()
                    {
                        UserId = model.UserId,
                        LoginTime = DateTime.Now
                    });
                }
                catch(Exception ex2)
                {
                    Common.Plugin.LogHelper.Write(ex2, "UserInfoSet_SetSignBit缓存设置失败");
                }
            }
            catch (Exception ex)
            {
                Common.Plugin.LogHelper.Write(ex, "UserInfoSet缓存设置失败");
            }
        }



        /// <summary>
        /// 用户
        /// </summary>

        private static readonly Repository.User.RB_Member_UserRepository member_UserRepository = new Repository.User.RB_Member_UserRepository();

        /// <summary>
        /// 获取小程序用户登录信息
        /// </summary>
        /// <param name="UserId">用户Id</param>
        /// <returns></returns>
        public static AppletUserInfo GetAppletUserLoginInfo(object UserId)
        {
            if (UserId != null)
            {
                string cacheKey = UserModuleCacheKeyConfig.Applet_Login_Info + UserId.ToString();
                AppletUserInfo userInfo = null;
                try
                {
                    userInfo = redis.StringGet<AppletUserInfo>(cacheKey);
                }
                catch (Exception ex)
                {
                    LogHelper.Write(ex, "GetAppletUserLoginInfo");
                }
                if (userInfo == null)
                {
                    Int32.TryParse(UserId.ToString(), out int NewUserId);
                    if (NewUserId > 0)
                    {
                        string token = "";
                        var umodel = member_UserRepository.GetEntity<RB_Member_User_Extend>(NewUserId);
                        if (umodel != null && (umodel.Blacklist??0) == 0)
                        {
                            userInfo = new AppletUserInfo
                            {
                                MallBaseId = umodel.MallBaseId,
                                MallName = "",
                                Mobile = umodel.Moblie,
                                UserId = NewUserId,
                                TenantId = umodel.TenantId,
                                Name = umodel.Name,
                                OpenId = umodel.OpenId,
                                Photo = umodel.Photo,
                                Source = umodel.Source,
                                SecretKey = umodel.SecretKey,
                                SuperiorId = umodel.SuperiorId ?? 0,
                                Token = token
                            };
                            AppletUserInfoSet(UserModuleCacheKeyConfig.Applet_Login_Info + UserId, userInfo, Config.JwtExpirTime);
                        }
                    }
                }
                return userInfo;
            }
            return null;
        }

        /// <summary>
        /// 获取小程序用户黑名单信息
        /// </summary>
        /// <param name="UserId"></param>
        /// <returns></returns>
        public static AppletUserInfo GetAppletUserBlacklistInfo(object UserId)
        {
            if (UserId != null)
            {
                string cacheKey = UserModuleCacheKeyConfig.Applet_Blacklist_Info + UserId.ToString();
                AppletUserInfo userInfo = null;
                try
                {
                    userInfo = redis.StringGet<AppletUserInfo>(cacheKey);
                }
                catch (Exception ex)
                {
                    LogHelper.Write(ex, "GetAppletUserBlacklistInfo");
                }
                if (userInfo == null)
                {
                    Int32.TryParse(UserId.ToString(), out int NewUserId);
                    if (NewUserId > 0)
                    {
                        var umodel = member_UserRepository.GetEntity<RB_Member_User_Extend>(NewUserId);
                        if (umodel != null)
                        {
                            userInfo = new AppletUserInfo
                            {
                                MallBaseId = umodel.MallBaseId,
                                UserId = NewUserId,
                                TenantId = umodel.TenantId,
                                Name = umodel.Name,
                                SuperiorId = umodel.SuperiorId ?? 0,                                
                                Blacklist = umodel.Blacklist
                            };
                            AppletUserInfoSet(UserModuleCacheKeyConfig.Applet_Blacklist_Info + UserId, userInfo, Config.JwtExpirTime);
                        }
                    }
                }
                return userInfo;
            }
            return null;
        }


        #region 不可开发票总金额

        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <param name="model"></param>
        public static void TransactionPriceSet(string cacheKey, TransactionPriceInfo  model, int JwtExpirTime)
        {
            try
            {
                TimeSpan ts = GetExpirTime(31536000);//365天不过期
                redis.StringSet<TransactionPriceInfo>(cacheKey, model, ts);
            }
            catch (Exception ex)
            {
                Common.Plugin.LogHelper.Write(ex, "TransactionPriceSet缓存设置失败");
            }
        }




        /// <summary>
        /// 获取不可开发票总金额
        /// </summary>
        /// <param name="TenantId">商户Id</param>
        /// <returns></returns>
        public static TransactionPriceInfo GetTransactionPriceInfo(int MallBaseId)
        {
            TransactionPriceInfo transactionPriceInfo = null;
            if (MallBaseId > 0)
            {
                string cacheKey = UserModuleCacheKeyConfig.Transaction_Price_ + MallBaseId.ToString();
                try
                {
                    transactionPriceInfo = redis.StringGet<TransactionPriceInfo>(cacheKey);
                }
                catch (Exception ex)
                {
                    LogHelper.Write(ex, "GetTransactionPriceInfo");
                }
                //if (transactionPriceInfo == null)
                //{
                //    if (MallBaseId > 0 && TenantId > 0)
                //    {
                //        transactionPriceInfo = new TransactionPriceInfo
                //        {
                //            TenantId = (int)TenantId,
                //            MallBaseId = (int)MallBaseId,
                //            TotalPrice = TotalPrice
                //        };
                //        TransactionPriceSet(UserModuleCacheKeyConfig.Transaction_Price_ + MallBaseId, transactionPriceInfo, Config.JwtExpirTime);
                //    }
                //}
            }
            else
            {
                transactionPriceInfo = new TransactionPriceInfo();
            }
            return transactionPriceInfo;
        }
        #endregion




        /// <summary>
        /// 添加用户发送验证码时间记录
        /// </summary>
        /// <param name="mobileNumber">手机号码</param>
        public static bool AddUserSendCodeHistory(string mobileNumber)
        {
            string key = string.Concat(CacheKey.UserModuleCacheKeyConfig.User_Send_Code_List, mobileNumber);
            List<DateTime> codeTimeList = redis.StringGet<List<DateTime>>(key);
            if (codeTimeList == null)
            {
                codeTimeList = new List<DateTime>();
            }
            codeTimeList.Add(DateTime.Now);
            TimeSpan ts = GetExpirTime(Common.Config.JwtExpirTime);
            return redis.StringSet<List<DateTime>>(key, codeTimeList, ts);
        }



        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <param name="cacheKey"></param>
        /// <param name="Data"></param>
        /// <param name="JwtExpirTime"></param>
        public static void SetSendCode(string cacheKey, object Data, int JwtExpirTime)
        {
            try
            {
                TimeSpan ts = GetExpirTime(JwtExpirTime);
                redis.StringSet(cacheKey, Data, ts);
            }
            catch (Exception)
            {
            }
        }

        /// <summary>
        /// 获取短信验证码
        /// </summary>
        /// <param name="Id">账号Id</param>
        /// <param name="apiRequestFromEnum">请求来源</param>
        /// <returns></returns>
        public static string GetUserCode(object Id)
        {
            string code = string.Empty;
            if (Id != null)
            {
                string cacheKey = Id.ToString();
                try
                {
                    code = redis.StringGet<string>(cacheKey);
                }
                catch (Exception ex)
                {
                    Common.Plugin.LogHelper.Write(ex, "GetUserCode");
                }
            }
            return code;
        }
        /// <summary>
        /// 验证是否可以发送验证码
        /// </summary>
        /// <param name="mobileNumber">手机号码</param>
        /// <param name="message">返回消息</param>
        public static bool CheckCanSendCode(string mobileNumber, out string message)
        {
            message = "";
            //Monitor.Enter和Monitor.Exit
            string key = string.Concat(CacheKey.UserModuleCacheKeyConfig.User_Send_Code_List, mobileNumber);
            List<DateTime> codeTimeList = redis.StringGet<List<DateTime>>(key);
            if (codeTimeList != null)
            {
                //计算阿里短信业务限流
                codeTimeList = codeTimeList.Where(t => t >= DateTime.Now.AddDays(-1)).ToList();
                //去除一天以外的记录
                TimeSpan ts = GetExpirTime(Common.Config.JwtExpirTime);
                redis.StringSet(key, codeTimeList, ts);
                if (codeTimeList.Count() >= 10)
                {
                    message = "24小时内不能发送超过10条验证码";
                    return false;
                }
                if (codeTimeList.Where(t => t >= DateTime.Now.AddHours(-1)).Count() >= 5)
                {
                    message = "1小时内不能发送超过5条验证码";
                    return false;
                }
                if (codeTimeList.Where(t => t >= DateTime.Now.AddMinutes(-1)).Count() >= 1)
                {
                    message = "1分钟内只能发送1条验证码";
                    return false;
                }
                return true;
            }
            else
            {
                return true;
            }
        }





        /// <summary>
        /// 设置首店下载缓存
        /// </summary>
        /// <param name="cacheKey"></param>
        /// <param name="Data"></param>
        /// <param name="JwtExpirTime"></param>
        public static void SetMallDownLoadInfo(string cacheKey, object Data, int JwtExpirTime)
        {
            try
            {
                TimeSpan ts = GetExpirTime(JwtExpirTime);
                redis.StringSet(cacheKey, Data, ts);
            }
            catch (Exception)
            {
            }
        }

        /// <summary>
        /// 获取首店下载
        /// </summary>
        /// <param name="Id">账号Id</param>
        /// <param name="apiRequestFromEnum">请求来源</param>
        /// <returns></returns>
        public static Model.Extend.TradePavilion.DownLoad GetMallDownLoadInfo(object Id)
        {
            Model.Extend.TradePavilion.DownLoad downLoad = new Model.Extend.TradePavilion.DownLoad();
            if (Id != null)
            {
                string cacheKey = Id.ToString();
                try
                {
                    downLoad = redis.StringGet<Model.Extend.TradePavilion.DownLoad>(cacheKey);
                }
                catch (Exception ex)
                {
                    downLoad = new Model.Extend.TradePavilion.DownLoad();
                    Common.Plugin.LogHelper.Write(ex, "GetMallDownLoadInfo");
                }
            }
            return downLoad;
        }

    }
}
