using Elasticsearch.Net;
using JiaZhiQuan.Common.ElasticSearch;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Senparc.Weixin.MP.Containers;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Dynamic;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Wicture.DbRESTFul;
using Wicture.DbRESTFul.Cache;
using Wicture.DbRESTFul.Infrastructure.Repository;

namespace JiaZhiQuan.Common
{
    public static partial class RepositoryExtension
    {
        /// <summary>
        /// 获取用户的通知配置
        /// </summary>
        public static async Task<UserMessagePushConfig> GetUserMessagePushConfig(this DbRESTFulRepository repository, RedisCacheProvider cacheProvider, long userId, IDbConnection conn = null)
        {
            var key = CacheKeys.PushMsgUserConfig(userId);
            UserMessagePushConfig config;
            if (!(await cacheProvider.KeyExist(key)))
            {
                // 如果未找到此用户的配置，则从数据库获取
                config = await repository.QuerySingleOrDefaultAsync<UserMessagePushConfig>("select `all`, thumbsup, newfan, `comment`, `at`, focusPost, sys, recommend, followTopic from n_user_msgpush_setting where userId=" + userId + " limit 1", null, conn);
                await cacheProvider.Set(key, config, CacheKeys.PushMsgUserConfigCacheSecs);
            }
            else
            {
                config = await cacheProvider.Get<UserMessagePushConfig>(key);
                await cacheProvider.SetExpiration(key, CacheKeys.PushMsgUserConfigCacheSecs);
            }
            return config;
        }

        /// <summary>
        /// 判断用户的通知配置
        /// </summary>
        public static async Task<bool> CheckPushConfig(this DbRESTFulRepository repository, string configPropName, RedisCacheProvider cacheProvider, long targetUserId)
        {
            // 发送通知
            UserMessagePushConfig config = await repository.GetUserMessagePushConfig(cacheProvider, targetUserId);
            // 判断是否需要给这个用户推送消息，如果设置了不推送，则忽略
            if (config == null || !(config.all || (bool)config.GetType().GetProperty(configPropName).GetValue(config)))
            {
                return true;
            }
            return false;
        }


        /// <summary>
        /// 关注某一个用户，对于同一ID反复关注同一ID，24小时内只提醒一次
        /// </summary>
        /// <param name="fromUserId">关注用户Id</param>
        /// <param name="toUserId">被关注的用户Id</param>
        /// <returns></returns>
        public async static Task<bool> PushMsgCheckFocusRepeatability(this DbRESTFulRepository repository, RedisCacheProvider cacheProvider, long fromUserId, long toUserId)
        {
            // 检查Redis中是否有此用户的点赞记录，如果有，则返回False
            var key = CacheKeys.PushMsgFocusRepeatability(fromUserId, toUserId);
            if (await cacheProvider.Get(key) != null)
            {
                return false;
            }
            return true;
        }
        
        public async static Task PushMsgCheckFocusRepeatabilityAdd(this DbRESTFulRepository repository, RedisCacheProvider cacheProvider, long fromUserId, long toUserId)
        {
            // 检查Redis中是否有此用户的点赞记录，如果有，则返回False
            var key = CacheKeys.PushMsgFocusRepeatability(fromUserId, toUserId);
            if (await cacheProvider.Get(key) != null)
            {
                return;
            }
            await cacheProvider.Set(key, 1, CacheKeys.PushMsgFocusUserCacheSecs);
        }


        /// <summary>
        /// 检查是否需要给用户发送极光推送信息。用户一个小时内只能收到前2个关注通知，一天内最多收3个关注通知。
        /// </summary>
        /// <param name="toUserId">收到通知消息的用户Id</param>
        public async static Task<bool> PushMsgCheckFocusCount(this DbRESTFulRepository repository, RedisCacheProvider cacheProvider, long toUserId)
        {

            // 检查用户1个小时内收到关注通知数量
            var key1 = CacheKeys.PushMsgFocusReceivePerHour(toUserId);
            if (await cacheProvider.KeyExist(key1))
            {
                var count = await cacheProvider.Get<int>(key1);
                if (count >= 2)
                {
                    return false;
                }
            }
            // 检查用户1天内收到关注通知数量
            var key2 = CacheKeys.PushMsgFocusReceivePerDay(toUserId);
            if (await cacheProvider.KeyExist(key2))
            {
                var count = await cacheProvider.Get<int>(key2);
                if (count >= 3)
                {
                    return false;
                }
            }
            return true;
        }


        public async static Task PushMsgCheckFocusCountAdd(this DbRESTFulRepository repository, RedisCacheProvider cacheProvider, long toUserId)
        {

            // 检查用户1个小时内收到关注通知数量
            var needAddKey1 = false;
            var key1 = CacheKeys.PushMsgFocusReceivePerHour(toUserId);
            if (await cacheProvider.KeyExist(key1))
            {
                await cacheProvider.Increase(key1);
            }
            else
            {
                needAddKey1 = true;
            }

            // 检查用户1天内收到关注通知数量
            var key2 = CacheKeys.PushMsgFocusReceivePerDay(toUserId);
            var needAddKey2 = false;
            if (await cacheProvider.KeyExist(key2))
            {
                await cacheProvider.Increase(key2);
            }
            else
            {
                needAddKey2 = true;
            }

            if (needAddKey1) await cacheProvider.SetString(key1, "1", 60 * 60);
            if (needAddKey2) await cacheProvider.SetString(key2, "1", 60 * 60 * 24);
        }




        /// <summary>
        /// 给用户发送点赞通知，规则：对于同一类型（文章、评论、回复）用户A，一天内限收一条用户B的点赞通知
        /// </summary>
        /// <param name="fromUserId">点赞人的Id</param>
        /// <param name="type">0 动态 1 评论 2 回复</param>
        /// <param name="targetId">对应的Id</param>
        /// <returns>是否可以推送</returns>
        public async static Task<bool> PushMsgCheckThumbsupMessage(this DbRESTFulRepository repository, RedisCacheProvider cacheProvider, long fromUserId, ThumbsupTargetType type, long targetId)
        {
            // 检查Redis中是否有此用户的点赞记录，如果有，则返回False
            var key = CacheKeys.PushMsgThumbsupRepeatability(fromUserId, type, targetId);
            if (!(await cacheProvider.KeyExist(key)))
            {
                return true;
            }
            return false;
        }

        public async static Task PushMsgCheckThumbsupMessageAdd(this DbRESTFulRepository repository, RedisCacheProvider cacheProvider, long fromUserId, ThumbsupTargetType type, long targetId)
        {
            // 检查Redis中是否有此用户的点赞记录，如果有，则返回False
            var key = CacheKeys.PushMsgThumbsupRepeatability(fromUserId, type, targetId);
            if (!(await cacheProvider.KeyExist(key)))
            {
                await cacheProvider.Set(key, 1, CacheKeys.PushMsgThumbsupCacheSecs);
            }
        }


        /// <summary>
        /// 检查是否需要给用户发送极光推送信息。用户一个小时内只能收到前2个点赞通知，一天内最多收3个点赞通知。
        /// </summary>
        /// <param name="toUserId">收到通知消息的用户Id</param>
        public async static Task<bool> PushMsgCheckThumbsupCount(this DbRESTFulRepository repository, RedisCacheProvider cacheProvider, long toUserId)
        {
            //var key1 = CacheKeys.PushMsgThumbsupReceivePerMin(toUserId);
            //if (await cacheProvider.KeyExist(key1))
            //{
            //    if (await cacheProvider.KeyExist(key1))
            //    {
            //        return false;
            //    }
            //}
            var key2 = CacheKeys.PushMsgThumbsupReceivePerHour(toUserId);
            if (await cacheProvider.KeyExist(key2))
            {
                var count = await cacheProvider.Get<int>(key2);
                if (count >= 2)
                {
                    return false;
                }
            }
            var key3 = CacheKeys.PushMsgThumbsupReceivePerDay(toUserId);
            if (await cacheProvider.KeyExist(key3))
            {
                var count = await cacheProvider.Get<int>(key3);
                if (count >= 3)
                {
                    return false;
                }
            }
            return true;
        }

        public async static Task PushMsgCheckThumbsupCountAdd(this DbRESTFulRepository repository, RedisCacheProvider cacheProvider, long toUserId)
        {

            var key1 = CacheKeys.PushMsgThumbsupReceivePerMin(toUserId);
            var key2 = CacheKeys.PushMsgThumbsupReceivePerHour(toUserId);
            var key3 = CacheKeys.PushMsgThumbsupReceivePerDay(toUserId);
            
            await cacheProvider.SetString(key1, "1", CacheKeys.PushMsgThumbsupReceivePerMinCacheSecs);
            
            if (await cacheProvider.KeyExist(key2))
            {
                await cacheProvider.Increase(key2);
            }
            else
            {
                await cacheProvider.SetString(key2, "1", CacheKeys.PushMsgThumbsupReceivePerHourCacheSecs);
            }

            if (await cacheProvider.KeyExist(key3))
            {
                await cacheProvider.Increase(key3);
            }
            else
            {
                await cacheProvider.SetString(key3, "1", CacheKeys.PushMsgThumbsupReceivePerDayCacheSecs);
            }
        }


        /// <summary>
        /// 给用户发送评论通知，规则：同一ID对另一ID用户，一天最多3次评论，除非楼主回复了后，再进行提醒（清除逻辑放在了评论通知中）
        /// </summary>
        /// <param name="fromUserId">评论的人</param>
        /// <param name="toUserId">被评论的人</param>
        /// <returns></returns>
        public async static Task<bool> PushMsgCheckCommentPerDay(this DbRESTFulRepository repository, RedisCacheProvider cacheProvider, long fromUserId, long toUserId)
        {
            // 检查Redis中是否有此用户的点赞记录，如果有，则返回False
            var key = CacheKeys.PushMsgCommentPertDay(fromUserId, toUserId);
            if (await cacheProvider.KeyExist(key))
            {
                var count = await cacheProvider.Get<int>(key);
                if (count > 3)
                {
                    return false;
                }
            }
            return true;
        }

        public async static Task PushMsgCheckCommentPerDayAdd(this DbRESTFulRepository repository, RedisCacheProvider cacheProvider, long fromUserId, long toUserId)
        {
            // 检查Redis中是否有此用户的点赞记录，如果有，则返回False
            var key = CacheKeys.PushMsgCommentPertDay(fromUserId, toUserId);
            if (await cacheProvider.KeyExist(key))
            {
                await cacheProvider.Increase(key);
            }
            else
            {
                await cacheProvider.Set(key, 1, CacheKeys.PushMsgCommentPerDayCacheSecs);
            }
        }

        /// <summary>
        /// 检查是否需要给用户发送极光推送信息。收到评论的用户一个小时内只能收到前4个评论通知，一天内最多收20个评论通知
        /// </summary>
        /// <param name="toUserId">收到通知消息的用户Id</param>
        public async static Task<bool> PushMsgCheckCommentReceive(this DbRESTFulRepository repository, RedisCacheProvider cacheProvider, long toUserId)
        {

            // 检查用户1个小时内收到评论通知数量
            var key1 = CacheKeys.PushMsgCommentReceivePerHour(toUserId);
            if (await cacheProvider.KeyExist(key1))
            {
                var count = await cacheProvider.Get<int>(key1);
                if (count >= 4)
                {
                    return false;
                }
            }
            // 检查用户1天内收到评论通知数量
            var key2 = CacheKeys.PushMsgCommentReceivePerDay(toUserId);
            if (await cacheProvider.KeyExist(key2))
            {
                var count = await cacheProvider.Get<int>(key2);
                if (count >= 20)
                {
                    return false;
                }
            }

            return true;
        }


        public async static Task PushMsgCheckCommentReceiveAdd(this DbRESTFulRepository repository, RedisCacheProvider cacheProvider, long toUserId)
        {

            // 检查用户1个小时内收到评论通知数量
            var needAddKey1 = false;
            var key1 = CacheKeys.PushMsgCommentReceivePerHour(toUserId);
            if (await cacheProvider.KeyExist(key1))
            {
                await cacheProvider.Increase(key1);
            }
            else
            {
                needAddKey1 = true;
            }

            // 检查用户1天内收到评论通知数量
            var key2 = CacheKeys.PushMsgCommentReceivePerDay(toUserId);
            var needAddKey2 = false;
            if (await cacheProvider.KeyExist(key2))
            {
                await cacheProvider.Increase(key2);
            }
            else
            {
                needAddKey2 = true;
            }

            if (needAddKey1) await cacheProvider.SetString(key1, "1", CacheKeys.PushMsgCommentReceivePerHourCacheSecs);
            if (needAddKey2) await cacheProvider.SetString(key2, "1", CacheKeys.PushMsgCommentReceivePerDayCacheSecs);
        }

    }

}
