using CloudGaming.Code.Account;
using CloudGaming.Code.AppExtend;
using CloudGaming.Code.Contract;
using CloudGaming.DtoModel.Account.User;
using CloudGaming.DtoModel.Game;
using CloudGaming.DtoModel.JY;
using CloudGaming.DtoModel.PlayGame;

using Newtonsoft.Json;

using Org.BouncyCastle.Asn1.Ocsp;


namespace CloudGaming.Code.Game;

/// <summary>
/// 
/// </summary>
public class PlayGameBLL : CloudGamingBase
{
    private IJYApi JYApi { get; set; }
    public PlayGameBLL(IServiceProvider serviceProvider, IJYApi jYApi) : base(serviceProvider)
    {
        JYApi = jYApi;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="requestBaseModel"></param>
    /// <returns></returns>
    public async Task<BaseResponse<GetTokenModel>> GetTokenAsync(RequestBaseModel requestBaseModel)
    {
        if (_UserId == 0)
        {
            throw MessageBox.ErrorShow("请先登录");
        }
        if (string.IsNullOrEmpty(requestBaseModel.Sn))
        {
            throw MessageBox.ErrorShow("设备号不能为空");
        }
        //requestBaseModel.Sn = Guid.NewGuid().ToString();
        JYRequestParameter requestParameter = new JYRequestParameter(requestBaseModel.Sn, _UserId);
        var data = await JYApi.GetToken(requestParameter);
        //Console.WriteLine(jyResponseData.TotalMilliseconds);
        if (data.IsSuccess)
        {
            return new BaseResponse<GetTokenModel>(ResponseCode.Success, "", data?.Data ?? new GetTokenModel());
        }
        throw data.ToMessageBox();
    }

    /// <summary>
    /// 启动游戏方法
    /// </summary>
    /// <param name="playGameRequest">启动游戏的请求参数</param>
    /// <returns>包含操作结果的响应对象</returns>
    public async Task<BaseResponse<dynamic>> PlayGameAsync(PlayGameRequest playGameRequest)
    {
        // 检查用户是否已登录
        if (_UserId == 0)
        {
            throw MessageBox.ErrorShow("请先登录");
        }

        // 检查游戏是否存在
        var gameCache = Cache.GameEntityCache;
        var gameInfo = gameCache[playGameRequest.GameId];
        if (gameInfo == null)
        {
            throw MessageBox.ErrorShow("游戏不存在");
        }

        // 检查用户钻石是否足够
        if (UserInfo.Diamond <= 0)
        {
            throw MessageBox.Show(ResponseCode.NotMoney, "钻石不足");
        }

        // 获取用户和游戏信息
        var userInfo = UserInfo;
        PlayGameUserInfo gameInfoCache = await PlayGameExtend.GetPlayGameUserInfoCacheAsync(this, userInfo, gameInfo);

        // 检查游戏状态
        if (gameInfoCache != null)
        {
            switch (gameInfoCache.GameStatus)
            {
                case PlayGameStatus.游戏中:
                case PlayGameStatus.开始游戏:
                    throw MessageBox.Show(ResponseCode.Error, "已在游戏中");

                case PlayGameStatus.排队中:
                    throw MessageBox.Show(ResponseCode.Error, "用户正在排队中");
            }
        }

        // 配置启动游戏设置
        var playGameSettings = new PlayGameSettings(playGameRequest.Sn, _UserId)
        {
            GameKey = gameInfo.GameCloudId ?? playGameRequest.GameId,
            QueueGrade = UserInfo.IsPay ? 5 : 1,
            DisplayGrade = 1,
            HangUpTimer = 300, // 挂机时间 5 分钟
            ModelName = playGameRequest.ModelName,
            StartResolution = "1080P",

        };
        if (!string.IsNullOrEmpty(playGameRequest.Cpu))
        {
            playGameSettings.Cpu = playGameRequest.Cpu;
        }
        //设置开始游戏数据
        gameInfoCache.InitStartPlayGame(playGameSettings);
        // 调用鲸云游戏启动接口     
        var jyResponseData = await JYApi.PlayGame(playGameSettings);

        var response = new BaseResponse<dynamic>();
        // 用户进入排队
        if (jyResponseData.IsLineUp)
        {
            var gameResponse = JsonConvert.DeserializeObject<JYResponseCode<PlayQueueInfoModel>>(jyResponseData.ResponseContent);

            gameInfoCache?.PlayQueueStart(gameResponse?.Data?.PlayQueueId ?? 0, gameResponse?.Data?.QueuePos ?? 0, playGameSettings.QueueGrade, jyResponseData);
            response = new BaseResponse<object>(ResponseCode.StartQueue, "开始排队", jyResponseData.Data);
        }
        else if (jyResponseData.IsSuccess)
        {

            // 游戏启动成功
            var gameResponse = JsonConvert.DeserializeObject<JYResponseCode<JYPlayGameModel>>(jyResponseData.ResponseContent);
            // 创建游戏记录和日志
            var userGameList = new T_User_GameList
            {
                Channel = AppRequestInfo.Channel,
                CreateTime = DateTime.Now,
                GameId = playGameRequest.GameId,
                Status = (int)PlayGameStatus.开始游戏,
                UpdateTime = DateTime.Now,
                UserId = _UserId,
                SessionId = gameInfoCache?.SessionId
            };
            await Dao.DaoPhone.Context.T_User_GameList.AddAsync(userGameList);
            await Dao.DaoPhone.Context.SaveChangesAsync();
            //启动游戏
            gameInfoCache?.PlayGameStart(gameResponse?.Data?.ScId ?? 0, userGameList.Id, playGameSettings.DisplayGrade, jyResponseData);
            gameInfoCache.Ip = HttpContextAccessor.HttpContext.GetClientIpAddress();
            gameInfoCache.Channel = AppRequestInfo.Channel;
            var diamondNumHour = gameInfo.ConsumeDiamondNumHour / 60.0;
            if (diamondNumHour > 0)
            {
                var startDiamond = (int)diamondNumHour < 1 ? 1 : (int)diamondNumHour;
                await BalanceDeductionFee(userInfo, gameInfoCache, diamondNumHour, 0, startDiamond);
                gameInfoCache.GameUserOperation.Add(new PlayGameUserOperation()
                {
                    ActionId = (int)PlayGameStatus.开始游戏扣费,
                    Content = $"启动游戏扣除钻石*{startDiamond},游戏每分钟消耗*{diamondNumHour}",
                    OperationDateTime = DateTime.Now,
                });
            }
            var gameResponse1 = JsonConvert.DeserializeObject<Dictionary<string, object>>(jyResponseData.ResponseContent);
            if (gameResponse1 != null && gameResponse1.TryGetValue("data", out var xxx))
            {
                response = new BaseResponse<object>(ResponseCode.Success, "", JsonConvert.SerializeObject(xxx));
            }
            else
            {
                response = new BaseResponse<object>(ResponseCode.Success, "", jyResponseData.Data);
            }

        }
        else // 游戏启动失败
        {
            gameInfoCache?.PlayGameError(jyResponseData);
            response = new BaseResponse<object>(ResponseCode.Error, jyResponseData.Msg, jyResponseData.Data);
        }
        await Dao.DaoPhone.Context.SaveChangesAsync();

        // 保存游戏缓存状态
        await gameInfoCache.SaveChangesAsync(this);
        return response;
    }

    /// <summary>
    /// 游戏心跳
    /// </summary>
    /// <param name="gameId"></param>
    /// <returns></returns>
    public async Task<PlayGameHeartbeatResponse> PlayGameHeartbeat(string gameId)
    {

        // 检查用户是否已登录
        if (_UserId == 0)
        {
            throw MessageBox.ErrorShow("请先登录");
        }

        // 检查游戏是否存在
        var gameCache = Cache.GameEntityCache;
        var gameInfo = gameCache[gameId];
        if (gameInfo == null)
        {
            throw MessageBox.ErrorShow("游戏不存在");
        }
        var userInfo = UserInfo;
        PlayGameUserInfo gameInfoCache = await PlayGameExtend.GetPlayGameUserInfoOrNull(this, userInfo, gameInfo);
        if (gameInfoCache == null)
        {
            throw MessageBox.ErrorShow("未找到游戏信息");
        }

        PlayGameHeartbeatResponse playGameHeartbeatResponse = new PlayGameHeartbeatResponse()
        {
            Diamond = userInfo.Diamond,
            UserPlayGameTime = 999
        };
        //LastChargingAt
        if (gameInfo.ConsumeDiamondNumHour > 0)
        {
            //每分钟扣费
            var diamondNumHour = gameInfo.ConsumeDiamondNumHour / 60.0;
            playGameHeartbeatResponse.GameConsumeDiamond = diamondNumHour.ToString("0.##");
            var chargingAt = DateTime.Now;
            var minutes = (int)chargingAt.Subtract(gameInfoCache.LastChargingAt ?? DateTime.Now).TotalMinutes;
            if (minutes >= 1)
            {
                // 检查用户钻石是否足够
                if (userInfo.Diamond == 0 && gameInfo.ConsumeDiamondNumHour > 0)
                {
                    PlayGameCommonSetting playGameCommonSetting = new PlayGameCommonSetting()
                    {
                        ScId = gameInfoCache.ScId,
                        Sn = gameInfoCache.Sn,
                    };
                    var jyResponse = await JYApi.StopGame(playGameCommonSetting);
                    gameInfoCache.PlayGameUserNotDiamond(jyResponse);
                    await gameInfoCache.SaveChangesAsync(this);
                    throw MessageBox.Show(ResponseCode.NotMoney, "钻石不足");
                }
            }
            //判断扣费时间
            if (minutes >= 1)
            {
                var gameDiamondNumHour = (int)(diamondNumHour * minutes);
                //当前游玩的扣费金额,如果扣费金额不足1钻石，则等待下一次扣费
                if (gameDiamondNumHour >= 1)
                {
                    //如果游玩余额大于用户可扣款的余额
                    if (gameDiamondNumHour >= userInfo.Diamond)
                    {
                        //去数据库中在验证一下
                        //(int)userCurrency.GetUserCurrency(UserCurrencyType.钻石);
                        var currency = await Dao.DaoUser.Context.T_User_Currency.Where(it => it.UserId == userInfo.UserId && it.CurrencyType == (int)UserCurrencyType.钻石).FirstOrDefaultAsync();
                        if (currency == null)
                        {
                            throw MessageBox.ErrorShow("用户数据错误");
                        }
                        if ((int)(currency.CurrencyMoney) != userInfo.Diamond)
                        {
                            userInfo.Diamond = (int)currency.CurrencyMoney;
                        }
                        if (gameDiamondNumHour > userInfo.Diamond)
                        {
                            //用户余额不足
                            gameDiamondNumHour = userInfo.Diamond;
                            playGameHeartbeatResponse.UserPlayGameTime = 0;
                        }

                    }
                    await BalanceDeductionFee(userInfo, gameInfoCache, diamondNumHour, minutes, gameDiamondNumHour);
                }
            }
            //用户剩余游玩时间
            if (userInfo.Diamond > 0)
            {
                var userPlayGameTime = (int)(userInfo.Diamond / diamondNumHour);
                playGameHeartbeatResponse.UserPlayGameTime = userPlayGameTime;
            }
            else
            {
                playGameHeartbeatResponse.UserPlayGameTime = 0;
            }

            //重置一下用户钻石
            playGameHeartbeatResponse.Diamond = userInfo.Diamond;
            gameInfoCache.PlayGameHeartbeat($"；累计扣除钻石*{gameInfoCache.SpendingDiamonds}；用户剩余钻石*{userInfo.Diamond}；当前游戏每分钟消耗钻石*{diamondNumHour.ToString("0.##")}；上一次扣费时间：{gameInfoCache.LastChargingAt?.ToString("yyyy-MM-dd HH:mm:ss")}");
            await gameInfoCache.SaveChangesAsync(this);
        }
        else
        {
            gameInfoCache.PlayGameHeartbeat($"，游戏免费游玩");
            await gameInfoCache.SaveChangesAsync(this);
        }

        return playGameHeartbeatResponse;


    }

    private async Task BalanceDeductionFee(UserInfoCache userInfo, PlayGameUserInfo gameInfoCache, double diamondNumHour, int minutes, decimal gameDiamondNumHour)
    {
        var (issuccess, currlogId, diamId) = await this.UserPlayGameDiamondConsumeMoney(-gameDiamondNumHour, gameInfoCache.GameName, gameInfoCache.CurrencyLogId, gameInfoCache.DiamondListId, $"{diamondNumHour}/分钟");
        if (!issuccess)
        {
            var Content = $"扣除费用{gameDiamondNumHour}，用户剩余金额{userInfo.Diamond}；";
            if (minutes == 0)
            {
                Content = $"启动扣除费用{gameDiamondNumHour}，用户剩余金额{userInfo.Diamond}；";
            }
            gameInfoCache.GameUserOperation.Add(new PlayGameUserOperation()
            {
                ActionId = (int)PlayGameStatus.用户扣款错误,
                Content = Content
            });
            await gameInfoCache.SaveChangesAsync(this);
            throw MessageBox.ErrorShow("扣款出现错误");
        }
        gameInfoCache.SpendingDiamonds += gameDiamondNumHour;
        userInfo.UserPlayGameTime += minutes;
        await this.SaveUserInfoCacheChangesAsync();
        gameInfoCache.CurrencyLogId = currlogId;
        gameInfoCache.DiamondListId = diamId;
        //修改最后扣费时间
        gameInfoCache.LastChargingAt = (gameInfoCache.LastChargingAt ?? gameInfoCache.CreateDateTime).AddMinutes(minutes);
        await Dao.DaoUser.Context.SaveChangesAsync();
    }


    /// <summary>
    /// 用户主动结束游戏
    /// </summary>
    /// <param name="gameId"></param>
    /// <returns></returns>
    public async Task<BaseResponse<bool>> ExitPlayGame(ExitPlayGameRequest gameRequest)
    {
        // 检查用户是否已登录
        if (_UserId == 0)
        {
            throw MessageBox.ErrorShow("请先登录");
        }
        var gameId = gameRequest.GameId;
        // 检查游戏是否存在
        var gameCache = Cache.GameEntityCache;
        var gameInfo = gameCache[gameId];
        if (gameInfo == null)
        {
            throw MessageBox.ErrorShow("游戏不存在");
        }
        var userInfo = UserInfo;
        PlayGameUserInfo gameInfoCache = await PlayGameExtend.GetPlayGameUserInfoOrNull(this, userInfo, gameInfo);
        if (gameInfoCache == null)
        {
            return new BaseResponse<bool>(ResponseCode.Success, "游戏已结束", true);
        }
        if (gameInfoCache.GameStatus != PlayGameStatus.用户主动结束游戏)
        {
            PlayGameCommonSetting playGameQueue = new PlayGameCommonSetting()
            {
                ScId = gameInfoCache.ScId,
                Sn = gameInfoCache.Sn
            };
            var obj = await JYApi.StopGame(playGameQueue);
            gameInfoCache.ExitPlayGame(obj, gameRequest);
            await gameInfoCache.SaveChangesAsync(this);
        }
        return new BaseResponse<bool>(ResponseCode.Success, "", true);
    }



    /// <summary>
    /// 游戏排队
    /// </summary>
    /// <param name="gameRequest"></param>
    /// <returns></returns>
    public async Task<BaseResponse<PlayQueueInfoModel>> PlayGameQueueAsync(GameRequest gameRequest)
    {
        if (_UserId == 0)
        {
            throw MessageBox.ErrorShow("请先登录");
        }
        var gameId = gameRequest.GameId;
        // 检查游戏是否存在
        var gameCache = Cache.GameEntityCache;
        var gameInfo = gameCache[gameId];
        if (gameInfo == null)
        {
            throw MessageBox.ErrorShow("游戏不存在");
        }

        // 获取用户和游戏信息
        var userInfo = UserInfo;
        PlayGameUserInfo gameInfoCache = await PlayGameExtend.GetPlayGameUserInfoOrNull(this, userInfo, gameInfo);
        if (gameInfoCache == null)
        {
            throw MessageBox.ErrorShow("未找到游戏信息");
        }
        if (gameInfoCache.PlayQueueId == 0)
        {
            throw MessageBox.ErrorShow("排队出错");
        }
        PlayGameQueue playGameQueue = new PlayGameQueue(gameInfoCache.Sn, _UserId)
        {
            GameKey = gameInfoCache.JyGameId,
            PlayQueueId = gameInfoCache.PlayQueueId,
            QueueGrade = gameInfoCache.QueueGrade,
        };
        var paidui = await JYApi.PlayQueue(playGameQueue);
        BaseResponse<PlayQueueInfoModel> back = new BaseResponse<PlayQueueInfoModel>();
        if (paidui.IsSuccess)
        {
            gameInfoCache.PlayQueueSuccess(paidui);

            back = new BaseResponse<PlayQueueInfoModel>(0, "排队成功");
        }
        else if (paidui.IsLineUp)
        {
            gameInfoCache.PlayQueueStart(paidui?.Data?.PlayQueueId ?? 0, paidui?.Data?.QueuePos ?? 0, jYApiRespnse: paidui);
            back = new BaseResponse<PlayQueueInfoModel>(ResponseCode.StartQueue, "", paidui.Data);
        }
        else
        {
            gameInfoCache.PlayGameQueueError(paidui);
            back = new BaseResponse<PlayQueueInfoModel>(ResponseCode.Error, "排队出现错误", paidui.Data);
        }

        await gameInfoCache.SaveChangesAsync(this);
        return back;
    }

    /// <summary>
    /// 取消排队
    /// </summary>
    /// <param name="gameRequest"></param>
    /// <returns></returns>
    public async Task<BaseResponse<bool>> CancelQueueAsync(GameRequest gameRequest)
    {
        if (_UserId == 0)
        {
            throw MessageBox.ErrorShow("请先登录");
        }
        var gameId = gameRequest.GameId;
        // 检查游戏是否存在
        var gameCache = Cache.GameEntityCache;
        var gameInfo = gameCache[gameId];
        if (gameInfo == null)
        {
            throw MessageBox.ErrorShow("游戏不存在");
        }

        // 获取用户和游戏信息
        var userInfo = UserInfo;
        PlayGameUserInfo gameInfoCache = await PlayGameExtend.GetPlayGameUserInfoOrNull(this, userInfo, gameInfo);
        if (gameInfoCache == null)
        {
            throw MessageBox.ErrorShow("未找到游戏信息");
        }
        //CancelQueueAsync
        //PlayGameCancelQueue playGameQueue
        PlayGameQueue playGameQueue = new PlayGameQueue(gameInfoCache.Sn, _UserId)
        {
            PlayQueueId = gameInfoCache.PlayQueueId,
        };
        var paidui = await JYApi.CancelQueue(playGameQueue);
        if (paidui.IsSuccess)
        {
            gameInfoCache.PlayQueueCancel(paidui);
        }
        await gameInfoCache.SaveChangesAsync(this);
        return new BaseResponse<bool>(ResponseCode.Success, "取消排队成功");
    }

    /// <summary>
    /// 切换视频等级
    /// </summary>
    /// <param name="displayGrade"></param>
    /// <param name="gameId"></param>
    /// <returns></returns>
    public async Task<BaseResponse<object>> DisplayGrade(int displayGrade, string gameId)
    {

        if (_UserId == 0)
        {
            throw MessageBox.ErrorShow("请先登录");
        }

        // 检查游戏是否存在
        var gameCache = Cache.GameEntityCache;
        var gameInfo = gameCache[gameId];
        if (gameInfo == null)
        {
            throw MessageBox.ErrorShow("游戏不存在");
        }

        // 获取用户和游戏信息
        var userInfo = UserInfo;
        PlayGameUserInfo gameInfoCache = await PlayGameExtend.GetPlayGameUserInfoOrNull(this, userInfo, gameInfo);
        if (gameInfoCache == null)
        {
            throw MessageBox.ErrorShow("未找到游戏信息");
        }
        if (gameInfoCache.GameStatus != PlayGameStatus.开始游戏 && gameInfoCache.GameStatus != PlayGameStatus.游戏中)
        {
            throw MessageBox.ErrorShow("不在游戏中");
        }
        DisplayGradeSettings displayGradeSettings = new DisplayGradeSettings()
        {
            DisplayGrade = displayGrade,
            ScId = gameInfoCache.ScId,
            Sn = gameInfoCache.Sn,
        };
        //切换视频等级
        var response = await JYApi.DisplayGrade(displayGradeSettings);
        if (response.IsSuccess)
        {
            gameInfoCache.DisplayGrade = displayGrade;
            gameInfoCache.UserSwitchDisplayGrade(displayGrade, response);
            await gameInfoCache.SaveChangesAsync(this);
        }
        else
        {
            gameInfoCache.UserSwitchDisplayGradeError(displayGrade, response);
            await gameInfoCache.SaveChangesAsync(this);
            throw MessageBox.ErrorShow("切换失败");
        }
        return new BaseResponse<object>(ResponseCode.Success, "", response.Data);
    }


    /// <summary>
    /// 获取可重连的会话列表
    /// </summary>
    /// <param name="sn"></param>
    /// <returns></returns>
    public async Task<PlayGameInfoDto> GetMyScList(string sn)
    {
        var requestParmat = new JYRequestParameter(sn, _UserId);
        var response = await JYApi.MyScList(requestParmat);
        if (response.IsSuccess)
        {
            if (response.Data?.List?.Count > 0)
            {
                var sess = response.Data?.List[0];
                if (sess != null)
                {
                    //sess.RestTime
                    var gameInfo = await PlayGameExtend.PlayGameRecon(this, _UserId, sess.ScId, response);
                    if (gameInfo != null)
                    {
                        await gameInfo.SaveChangesAsync(this);
                        var game = Cache.GameEntityCache[gameInfo.GameId];
                        if (game != null)
                        {
                            return new PlayGameInfoDto(game, DtoModel.Epg.EpgEnum.ImageResStyle.小LOGO, sess.RestTime);
                        }

                    }
                }
            }
            return null;
        }
        return null;
    }

    /// <summary>
    /// 重连会话
    /// </summary>
    /// <param name="reconPlayGameRequest"></param>
    /// <returns></returns>
    public async Task<BaseResponse<string>> ReconPlayGame(GameRequest gameRequest)
    {
        var gameId = gameRequest.GameId;
        // 检查游戏是否存在
        var gameCache = Cache.GameEntityCache;
        var gameInfo = gameCache[gameId];
        if (gameInfo == null)
        {
            throw MessageBox.ErrorShow("游戏不存在");
        }

        // 获取用户和游戏信息
        var userInfo = UserInfo;
        PlayGameUserInfo gameInfoCache = await PlayGameExtend.GetPlayGameUserInfoOrNull(this, userInfo, gameInfo);
        if (gameInfoCache == null)
        {
            throw MessageBox.ErrorShow("未找到游戏信息");
        }
        var setting = new ReconPlayGameSettings(gameInfoCache.Sn, _UserId)
        {
            ScId = gameInfoCache.ScId,
            DisplayGrade = gameInfoCache.DisplayGrade,
            Cpu = gameInfoCache.Cpu,
            ModelName = gameInfoCache.ModelName,
        };
        var jyResponseData = await JYApi.ReconPlayGame(setting);
        if (jyResponseData.IsSuccess)
        {
            var gameResponse1 = JsonConvert.DeserializeObject<Dictionary<string, object>>(jyResponseData.ResponseContent);
            if (gameResponse1 != null && gameResponse1.TryGetValue("data", out var xxx))
            {
                if (gameInfo != null)
                {
                    gameInfoCache.PlayGameRecon(jyResponseData);
                    await gameInfoCache.SaveChangesAsync(this);
                }
                return new BaseResponse<string>(ResponseCode.Success, "", JsonConvert.SerializeObject(xxx));
            }

        }
        throw jyResponseData.ToMessageBox();
    }
}
