using CloudGaming.Code.Account;
using CloudGaming.Code.Cache;
using CloudGaming.DtoModel.Game;

using Microsoft.IdentityModel.Tokens;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Text;
using System.Threading.Tasks;

using static CloudGaming.DtoModel.Epg.EpgEnum;
using static SKIT.FlurlHttpClient.Wechat.TenpayV3.Models.CreateMarketingMemberCardActivityRequest.Types.AwardSendPeriod.Types.AwardSendDayTime.Types;

namespace CloudGaming.Code.Game
{
    /// <summary>
    /// 游戏逻辑类
    /// </summary>
    public class GameBLL : CloudGamingBase
    {
        public GameBLL(IServiceProvider serviceProvider) : base(serviceProvider)
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public async Task<List<GameExtendedAttribute>> GetGameTypeListAsync()
        {
            var gameList = Cache.GameEntityCache?.DataList ?? new List<GameInfo>();
            var gameTypes = await Task.Run(() =>
            {
                return CloudGamingCacheExtend.GetDataEntityCache<T_Game_Types>(this, it => it.IsOnline)?.DataList
                    .Where(it => gameList.Any(item => item.GameType?.Any(gameType => gameType.Id == it.TypeId) ?? false))
                    .OrderBy(it => it.OrderId)
                    .Select(it => new GameExtendedAttribute
                    {
                        Id = it.TypeId,
                        Name = it.TypeName,
                        OrderId = it.OrderId
                    })
                    .ToList();
            });

            return gameTypes;
        }

        /// <summary>
        /// 根据游戏类型Id 获取游戏列表
        /// </summary>
        /// <param name="typeId"></param>
        /// <returns></returns>
        public async Task<List<GameListDto>> GetGameListAsync(int typeId)
        {

            var gameListDto = await Task.Run(() =>
                 {
                     var gameList = Cache.GameEntityCache?.DataList ?? new List<GameInfo>();
                     var x = gameList.Where(it => it.GameType?.Any(item => item.Id == typeId) ?? false).Select(it => new
                     GameListDto(it, ImageResStyle.游戏库)).ToList();
                     return x;
                 });
            return gameListDto;

        }
        /// <summary>
        /// 获取游戏详情
        /// </summary>
        /// <param name="gameId"></param>
        /// <returns></returns>
        public async Task<GameInfoDto> GetGameInfo(string gameId)
        {
            if (string.IsNullOrEmpty(gameId))
            {
                return null;
            }
            var game = Cache.GameEntityCache[gameId];
            if (game == null)
            {
                return null;
            }
            var gameInfo = Mapper.Map<GameInfoDto>(game);
            if (_UserId > 0)
            {
                //IsCollect
                var gameIds = await UserInfo.GetUserGameCollect(Dao, RedisCache);
                if (gameIds.Contains(gameId))
                {
                    gameInfo.IsCollect = true;
                }
            }
            return gameInfo;
        }

        /// <summary>
        /// 游戏推荐
        /// </summary>
        /// <param name="gameId"></param>
        /// <returns></returns>
        public List<GameListDto> GameRecommendations(string gameId)
        {
            List<GameInfo>? gameInfos = null;
            if (!string.IsNullOrEmpty(gameId))
            {
                var game = Cache.GameEntityCache[gameId];
                if (game != null)
                {
                    var gameTagIds = game.GameTags.Select(it => it.Id);
                    gameInfos = Cache.GameInfos.Where(it => it.GameTags.Any(tag => gameTagIds.Contains(tag.Id))).OrderBy(it => Guid.NewGuid()).Take(3).ToList();
                }
            }

            if (gameInfos == null || gameInfos.Count == 0)
            {
                gameInfos = Cache.GameInfos.OrderBy(it => Guid.NewGuid()).Take(3).ToList();
            }
            var gameList = gameInfos?.Select(it => new GameListDto(it, ImageResStyle.竖形图)).ToList();
            return gameList ?? new List<GameListDto>();
        }

        /// <summary>
        /// 游戏搜索
        /// </summary>
        /// <param name="gameName"></param>
        /// <returns></returns>
        public async Task<List<GameListDto>> GameSearch(string gameName)
        {

            try
            {
                T_User_Search gameSearch = new T_User_Search()
                {
                    SearchContent = gameName,
                    SearchDate = DateTime.Now,
                    UserId = _UserId,
                    SearchDay = int.Parse(DateTime.Now.ToString("yyyyMMdd"))
                };
                await Dao.DaoPhone.Context.T_User_Search.AddAsync(gameSearch);
                await Dao.DaoPhone.Context.SaveChangesAsync();
            }
            catch (Exception)
            {
            }
            var gameIdMatches = Cache.GameInfos
          .Where(it => it.GameId.Contains(gameName))
          .Select(it => new GameListDto(it, ImageResStyle.中等LOGO))
          .ToList();

            var gameNameMatches = Cache.GameInfos
                .Where(it => it.GameName.Contains(gameName))
                .Select(it => new GameListDto(it, ImageResStyle.中等LOGO))
                .ToList();

            var gameIntroduceMatches = Cache.GameInfos
                .Where(it => it.GameIntroduce.Contains(gameName))
                .Select(it => new GameListDto(it, ImageResStyle.中等LOGO))
                .ToList();

            var otherMatches = Cache.GameInfos
                .Where(it => !it.GameId.Contains(gameName) && !it.GameName.Contains(gameName) && !it.GameIntroduce.Contains(gameName) &&
                             (it.GameTags.Any(tag => tag.Name.Contains(gameName)) || it.GameType.Any(types => types.Name.Contains(gameName))))
                .Select(it => new GameListDto(it, ImageResStyle.中等LOGO))
                .ToList();

            var list = gameIdMatches
                .Concat(gameNameMatches)
                .Concat(gameIntroduceMatches)
                .Concat(otherMatches)
                .Distinct()
                .ToList();
            return list;
        }

        /// <summary>
        /// 热门搜索
        /// </summary>
        /// <returns></returns>
        public async Task<List<string>> GameHotSearch()
        {
            var list = await Dao.DaoPhone.Context.T_Search.Where(it => !string.IsNullOrEmpty(it.Search)).OrderBy(it => it.OrderId).Take(10).Select(it => it.Search).ToListAsync();
            return list;
        }

        /// <summary>
        /// 我的收藏
        /// </summary>
        /// <returns></returns>
        public async Task<List<GameListDto>> GetGameCollect()
        {
            if (_UserId == 0)
            {
                return new List<GameListDto>();
            }
            var favorite = await Dao.DaoUser.Context.T_User_GameFavorite.Where(it => it.UserId == _UserId).OrderByDescending(it => it.FavoriteTime).ToListAsync();
            if (favorite == null || favorite.Count == 0)
            {
                return new List<GameListDto>();
            }
            List<GameListDto> list = new List<GameListDto>();
            var gameData = Cache.GameEntityCache;
            favorite.ForEach(it =>
            {
                if (string.IsNullOrEmpty(it.GameId))
                {
                    return;
                }
                var game = gameData[it.GameId];
                if (game == null)
                {
                    return;
                }
                var o = new GameListDto()
                {
                    GameId = it.GameId,
                    GameName = game.GameName ?? "",
                    GameIconImage = game.ImageIconId
                };
                list.Add(o);
            });
            return list;
        }

        /// <summary>
        /// 游戏收藏
        /// </summary>
        /// <param name="gameId"></param>
        /// <returns></returns>
        public async Task<BaseResponse<bool>> GameCollect(string gameId)
        {
            var favorite = await Dao.DaoUser.Context.T_User_GameFavorite.Where(it => it.UserId == _UserId && it.GameId == gameId).OrderByDescending(it => it.FavoriteTime).FirstOrDefaultAsync();
            if (favorite != null)
            {
                Dao.DaoUser.Context.T_User_GameFavorite.Remove(favorite);
                await Dao.DaoUser.Context.SaveChangesAsync();
                var degameIds = await UserInfo.GetUserGameCollect(Dao, RedisCache);
                degameIds.Remove(gameId);
                await this.SaveUserInfoCacheChangesAsync();
                return new BaseResponse<bool>(ResponseCode.Success, "取消收藏成功", false);
            }
            var game = Cache.GameEntityCache[gameId];
            if (game == null)
            {
                throw MessageBox.ErrorShow("收藏的游戏不存在");
            }
            favorite = new T_User_GameFavorite()
            {
                FavoriteTime = DateTime.Now,
                GameId = gameId,
                UserId = _UserId,
                Desc = ""
            };

            await Dao.DaoUser.Context.T_User_GameFavorite.AddAsync(favorite);
            await Dao.DaoUser.Context.SaveChangesAsync();
            var gameIds = await UserInfo.GetUserGameCollect(Dao, RedisCache);
            gameIds.Add(gameId);
            await this.SaveUserInfoCacheChangesAsync();
            return new BaseResponse<bool>(ResponseCode.Success, "收藏成功", true);
        }

        /// <summary>
        /// 游玩历史
        /// </summary>
        /// <returns></returns>
        public async Task<List<GameHistoryListDto>> GetGameHistory()
        {
            if (_UserId == 0)
            {
                return new List<GameHistoryListDto>();
            }
            List<GameHistoryListDto> gameHistoryListDtos = new List<GameHistoryListDto>();
            var list = await Dao.DaoPhone.Context.T_User_PlayGameTime.Where(it => it.UserId == _UserId).OrderByDescending(it => it.UpdateTime).ToListAsync();
            var gameList = Cache.GameEntityCache;
            list?.ForEach(it =>
            {
                if (string.IsNullOrEmpty(it.GameId))
                {
                    return;
                }
                var gameinfo = gameList[it.GameId];
                if (gameinfo != null)
                {
                    gameHistoryListDtos.Add(new GameHistoryListDto(gameinfo, it.PlayTime));
                }
            });
            return gameHistoryListDtos;
        }

        /// <summary>
        /// 游戏时长排行榜
        /// </summary>
        /// <param name="gameId"></param>
        /// <returns></returns>
        public async Task<GamePlayTimeInfoDto> GamePlayTimeList(string gameId)
        {
            GamePlayTimeInfoDto gamePlayTimeInfoDto = new GamePlayTimeInfoDto();
            List<GamePlayTimeDto> gamePlayTimeDtos = new List<GamePlayTimeDto>();
            //游玩记录
            var list = await Dao.DaoPhone.Context.T_User_PlayGameTime.Where(it => it.GameId == gameId).OrderByDescending(it => it.PlayTime).Take(50).ToListAsync();
            #region 排行榜数据
            var topList = list.Take(10).ToList();
            var userIds = topList.Select(it => it.UserId).ToList();
            var userInfo = await Dao.DaoUser.Context.T_User.Where(it => userIds.Contains(it.Id)).Select(it => new { it.NickName, it.Id, it.UserIconUrl }).ToListAsync();
            var index = 1;
            topList.ForEach(it =>
            {
                var user = userInfo.FirstOrDefault(item => item.Id == it.UserId);
                GamePlayTimeDto gamePlayTimeDto = new GamePlayTimeDto()
                {
                    PlayTime = $"{(it.PlayTime / 60.0).ToString("0.##")}小时",
                    UserIcon = user?.UserIconUrl ?? AppConfig.UserConfig.UserIconUrl,
                    UserName = user?.NickName ?? AppConfig.UserConfig.NickName,
                    UserId = it.UserId,
                    Ranking = index,
                };
                gamePlayTimeDtos.Add(gamePlayTimeDto);
                index++;
            });
            #endregion
            #region 用户数据
            GamePlayTimeDto userGamePlayTimeDto = new GamePlayTimeDto()
            {
                PlayTime = $"0小时",
                Ranking = 0,
                UserIcon = AppConfig.UserConfig.UserIconUrl,
                UserId = 0,
                UserName = ""
            };
            if (_UserId > 0)
            {
                //查找当前用户游玩记录
                var userGame = await Dao.DaoPhone.Context.T_User_PlayGameTime.Where(it => it.GameId == gameId && it.UserId == _UserId).FirstOrDefaultAsync();
                if (userGame != null)
                {
                    //计算用户排名，看看是否进入前50名
                    var userIndex = list.FindIndex(it => it.UserId == _UserId);
                    userGamePlayTimeDto.PlayTime = $"{(userGame.PlayTime / 60.0).ToString("0.##")}小时";
                    if (userIndex > -1)
                    {
                        userGamePlayTimeDto.Ranking = userIndex + 1;
                    }
                }
                userGamePlayTimeDto.UserName = UserInfo.NickName;
                userGamePlayTimeDto.UserId = _UserId;

            }
            #endregion
            gamePlayTimeInfoDto.UserGamePlayTime = userGamePlayTimeDto;
            gamePlayTimeInfoDto.GamePlayTimes = gamePlayTimeDtos;
            return gamePlayTimeInfoDto;
        }

        /// <summary>
        /// 获取首页排行榜
        /// </summary>
        /// <returns></returns>
        public async Task<List<GameHistoryListDto>> GetGameRankingList()
        {
            //后期需要把这个做出一个服务，每隔几分钟去查询一次
            var now = DateTime.Now;
            //从凌晨4点开始统计数据,如果当前时间小于凌晨4点，则将时间改成上一天
            if (now < new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 4, 0, 0))
            {
                now = now.AddDays(-1);
            }
            var startDate = new DateTime(now.Year, now.Month, now.Day, 4, 0, 0);
            //如果开始游玩时间大于凌晨4点，则直接计算时间
            var list = await Dao.DaoPhone.Context.T_User_GameList.Where(it => it.CreateTime > startDate)
                .GroupBy(it => it.GameId).Select(it => new { it.Key, PlayTime = it.Sum(it => it.PlayTime) }).OrderByDescending(it => it.PlayTime).Take(20).ToDictionaryAsync(it => it.Key, it => it.PlayTime);
            //如果开始时间小于凌晨4点，并且结束时间大于凌晨4点，则用结束时间减去凌晨4点，计算得到的游玩总时间
            var list1 = await Dao.DaoPhone.Context.T_User_GameList.Where(it => it.CreateTime < startDate && it.UpdateTime > startDate).Select(it => new { it.GameId, it.UpdateTime }).ToListAsync();
            var list2 = list1.Select(it =>
              new
              {
                  it.GameId,
                  PlayTime = it.UpdateTime.Subtract(startDate).TotalMinutes
              }).GroupBy(it => it.GameId).Select(it => new { it.Key, PlayTime = it.Sum(it => it.PlayTime) }).OrderByDescending(it => it.PlayTime).Take(20).ToList();
            //将结果二查出来合并到结果1中
            list2.ForEach(item =>
            {
                if (list.ContainsKey(item.Key))
                {
                    list[item.Key] += (int)item.PlayTime;
                }
                else
                {
                    list.TryAdd(item.Key, (int)item.PlayTime);
                }
            });
            var gameCache = Cache.GameEntityCache;
            List<GameHistoryListDto> gameListDtos = new List<GameHistoryListDto>();
            list = list.OrderByDescending(it => it.Value).Take(20).ToDictionary();

            foreach (var gameId in list.Keys)
            {
                var gameInfo = gameCache[gameId];
                if (gameInfo != null)
                {
                    gameListDtos.Add(new GameHistoryListDto(gameInfo, list[gameId], ImageResStyle.小LOGO));
                }
            }
            if (gameListDtos.Count < 20)
            {
                //gameListDtos.Add
                var gamelist = gameCache.DataList.Where(it => !gameListDtos.Any(game => game.GameId == it.GameId));
                var l = gamelist.OrderBy(it => new Random().Next(0, 999)).ToList();
                foreach (var g in l)
                {
                    gameListDtos.Add(new GameHistoryListDto(g, 0, ImageResStyle.小LOGO));
                    if (gameListDtos.Count >= 20)
                    {
                        break;
                    }
                }
            }
            return gameListDtos;
        }
    }
}
