using CloudGaming.Code.Account.Contract;
using CloudGaming.Code.Account.UserCurrency;
using CloudGaming.Code.DataAccess;
using CloudGaming.DtoModel.Account.User;

using Microsoft.EntityFrameworkCore.Storage;

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

namespace CloudGaming.Code.Account
{
    public static class UserCurrencyExtend
    {
        /// <summary>
        /// 获取用户货币余额,没有货币的时候添加
        /// </summary>
        /// <param name="user"></param>
        /// <param name="userCurrencyType"></param>
        /// <param name="dao"></param>
        /// <returns></returns>
        public static async Task<decimal> GetUserCurrencyMoney(this T_User user, UserCurrencyType userCurrencyType, DAO dao)
        {
            var userCurrency = await dao.DaoUser.Context.T_User_Currency.FirstOrDefaultAsync(it => it.UserId == user.Id && it.CurrencyType == (int)userCurrencyType);
            if (userCurrency == null)
            {
                userCurrency = new T_User_Currency()
                {
                    CurrencyMoney = 0,
                    CreateAt = DateTime.Now,
                    CurrencyName = userCurrencyType.ToString(),
                    CurrencyType = (int)userCurrencyType,
                    UpdateAt = DateTime.Now,
                    UserId = user.Id,
                };
                await dao.DaoUser.Context.AddAsync(userCurrency);
                await dao.DaoUser.Context.SaveChangesAsync();
            }
            return userCurrency?.CurrencyMoney ?? 0;
        }

        /// <summary>
        /// 获取用户货币余额
        /// </summary>
        /// <param name="user"></param>
        /// <param name="userCurrencyType"></param>
        /// <param name="dao"></param>
        /// <returns></returns>
        public static async Task<T_User_Currency> GetUserCurrency(this T_User user, UserCurrencyType userCurrencyType, DAO dao)
        {
            var userCurrency = await dao.DaoUser.Context.T_User_Currency.FirstOrDefaultAsync(it => it.UserId == user.Id && it.CurrencyType == (int)userCurrencyType);
            return userCurrency;
        }

        /// <summary>
        /// 获取用户所有货币信息
        /// </summary>
        /// <param name="user"></param>
        /// <param name="userCurrencyType"></param>
        /// <param name="dao"></param>
        /// <returns></returns>
        public static async Task<List<T_User_Currency>> GetUserCurrencys(this T_User user, DAO dao)
        {
            var userCurrency = await dao.DaoUser.Context.T_User_Currency.Where(it => it.UserId == user.Id).ToListAsync();
            return userCurrency;
        }

        /// <summary>
        /// 扣除或者充值货币
        /// </summary>
        /// <param name="user"></param>
        /// <param name="userCurrencyType">货币类型</param>
        /// <param name="money">扣除金额（负数扣除，正数添加）</param>
        /// <param name="dao">数据库</param>
        /// <param name="_currency"></param>
        /// <param name="orderId">订单号</param>
        /// <param name="title"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static async Task<bool> ConsumeMoneyNoWork(this T_User user, UserCurrencyType userCurrencyType, decimal money, DAO dao, T_User_Currency? _currency = null, string orderId = "", string title = "")
        {
            if (user == null || user.Id == 0)
            {
                throw new ArgumentNullException("用户不能为空");
            }
            int userId = user.Id;
            return await UserConsumeDiamondMoneyAsync(dao, userId, userCurrencyType, money, title, orderId, _currency);
        }


        /// <summary>
        /// 扣除当前用户钻石
        /// </summary>
        /// <param name="cloudGamingBase"></param>
        /// <param name="userCurrencyType"></param>
        /// <returns></returns>
        public static IUserConsumeMoney GetCurrentUserConsumeMoney(this CloudGamingBase cloudGamingBase, UserCurrencyType userCurrencyType, T_User_Currency currency = null)
        {
            if (UserCurrencyType.钻石 == userCurrencyType)
            {
                return new DiamondConsumeMoney(cloudGamingBase.Dao, cloudGamingBase._UserId, userCurrencyType, currency);
            }
            return new DiamondConsumeMoney(cloudGamingBase.Dao, cloudGamingBase._UserId, userCurrencyType, currency);
        }

        /// <summary>
        /// 扣除当前用户钻石
        /// </summary>
        /// <param name="cloudGamingBase"></param>
        /// <param name="userCurrencyType"></param>
        /// <returns></returns>
        public static IUserConsumeMoney CurrentUserConsumeMoney(this UserInfoCache userInfo, CloudGamingBase cloudGamingBase, UserCurrencyType userCurrencyType, T_User_Currency currency = null)
        {
            if (UserCurrencyType.钻石 == userCurrencyType)
            {
                return new DiamondConsumeMoney(cloudGamingBase.Dao, userInfo.UserId, userCurrencyType, currency);
            }
            return new DiamondConsumeMoney(cloudGamingBase.Dao, cloudGamingBase._UserId, userCurrencyType, currency);
        }

        /// <summary>
        /// 扣除当前用户钻石
        /// </summary>
        /// <param name="cloudGamingBase"></param>
        /// <param name="money"></param>
        /// <param name="userDoamondAction"></param>
        /// <returns></returns>
        public static async Task<bool> UserConsumeDiamondMoneyAsync(this CloudGamingBase cloudGamingBase, decimal money, Action<T_User_DiamondList>? userDoamondAction = null)
        {
            T_User_Currency currency = new T_User_Currency();
            try
            {
                var isSuccess = await UserConsumeDiamondMoneyAsync(cloudGamingBase.Dao, cloudGamingBase.UserInfo.UserId, money, userDoamondAction, currency);// 
                if (!isSuccess)
                {
                    return false;
                }
                cloudGamingBase.UserInfo.Diamond = (int)currency.CurrencyMoney;
                await cloudGamingBase.SaveUserInfoCacheChangesAsync();
            }
            catch (Exception ex)
            {

                return false;
            }
            return true;
        }





        /// <summary>
        /// 扣除或者添加当前用户钻石
        /// </summary>
        /// <param name="dao"></param>
        /// <param name="userId"></param>
        /// <param name="money">负数扣除，正数添加</param>
        /// <param name="userDoamondAction"></param>
        /// <returns></returns>
        public static async Task<bool> UserConsumeDiamondMoneyAsync(DAO dao, int userId, decimal money, Action<T_User_DiamondList>? userDoamondAction = null, T_User_Currency userCurrency = null)
        {

            var userConsumeMoney = new DiamondConsumeMoney(dao, userId, UserCurrencyType.钻石, userCurrency);
            try
            {
                var isSuccess = await userConsumeMoney.ConsumeMoneyAsync(money);
                if (!isSuccess)
                {
                    return false;
                }
                UserCurrencyConsumeType consumeType = money >= 0 ? UserCurrencyConsumeType.收入 : UserCurrencyConsumeType.消耗;
                T_User_DiamondList userDiamondList = new T_User_DiamondList()
                {
                    CreateAt = DateTime.Now,
                    Consume = money,
                    ConsumeType = (int)consumeType,
                    CurrencyType = (int)UserCurrencyType.钻石,
                    OrderCode = "",
                    Title = "",
                    UpdateAt = DateTime.Now,
                    UserId = userId,
                };
                if (userDoamondAction != null)
                {
                    userDoamondAction(userDiamondList);
                }
                await dao.DaoUser.Context.AddAsync(userDiamondList);
                await dao.DaoUser.Context.SaveChangesAsync();
            }
            catch (Exception ex)
            {

                return false;
            }
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cloudGamingBase"></param>
        /// <param name="money">金额</param>
        /// <param name="title">资产支出标题</param>
        /// <param name="orderId">订单号</param>
        /// <returns></returns>

        public static async Task<bool> UserConsumeDiamondMoneyAsync(this CloudGamingBase cloudGamingBase, decimal money, string title = "", string orderId = "")
        {
            return await UserConsumeDiamondMoneyAsync(cloudGamingBase, money, it => { it.Title = title; it.OrderCode = orderId; });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cloudGamingBase"></param>
        /// <param name="money">金额</param>
        /// <param name="title">资产支出标题</param>
        /// <param name="orderId">订单号</param>
        /// <returns></returns>

        public static async Task<bool> UserConsumeDiamondMoneyAsync(this CloudGamingBase cloudGamingBase, UserCurrencyType userCurrencyType, decimal money, string title = "", string orderId = "")
        {
            if (userCurrencyType == UserCurrencyType.钻石)
            {
                return await UserConsumeDiamondMoneyAsync(cloudGamingBase, money, it => { it.Title = title; it.OrderCode = orderId; });
            }
            return await UserConsumeDiamondMoneyAsync(cloudGamingBase, money, it => { it.Title = title; it.OrderCode = orderId; });
        }
        /// <summary>
        /// 充值或者消耗用户货币
        /// </summary>
        /// <param name="dao"></param>
        /// <param name="userId"></param>
        /// <param name="userCurrencyType"></param>
        /// <param name="money"></param>
        /// <param name="title"></param>
        /// <param name="orderId"></param>
        /// <returns></returns>

        public static async Task<bool> UserConsumeDiamondMoneyAsync(DAO dao, int userId, UserCurrencyType userCurrencyType, decimal money, string title = "", string orderId = "", T_User_Currency currency = null)
        {
            if (userCurrencyType == UserCurrencyType.钻石)
            {
                return await UserConsumeDiamondMoneyAsync(dao, userId, money, it => { it.Title = title; it.OrderCode = orderId; }, currency);
            }
            return await UserConsumeDiamondMoneyAsync(dao, userId, money, it => { it.Title = title; it.OrderCode = orderId; }, currency);
        }

        /// <summary>
        /// 用户玩游戏消耗钻石
        /// </summary>
        /// <param name="cloudGamingBase"></param>
        /// <param name="money">金额</param>
        /// <param name="currencyLogId">资产记录日志id</param>
        /// <param name="gameName">游戏名称</param>
        /// <param name="diamondListId">资产收入支出记录id</param>
        /// <param name="gameXiaoHao">游戏每分钟消耗多少钻石</param>
        /// <returns></returns>
        public static async Task<(bool, int, int)> UserPlayGameDiamondConsumeMoney(this CloudGamingBase cloudGamingBase, decimal money, string gameName, int currencyLogId, int diamondListId, string gameXiaoHao)
        {
            bool issuccess = false;
            int _currencyLogId = currencyLogId;
            try
            {
                var currency = new T_User_Currency();
                GameDiamondConsumeMoney gameDiamondConsumeMoney = new GameDiamondConsumeMoney(cloudGamingBase.Dao, cloudGamingBase._UserId, UserCurrencyType.钻石, currency);
                (issuccess, _currencyLogId) = await gameDiamondConsumeMoney.ConsumeMoneyAsync(money, currencyLogId);
                if (issuccess)
                {
                    cloudGamingBase.UserInfo.Diamond = (int)currency.CurrencyMoney;
                    //await cloudGamingBase.SaveUserInfoCacheChangesAsync();
                    UserCurrencyConsumeType consumeType = money >= 0 ? UserCurrencyConsumeType.收入 : UserCurrencyConsumeType.消耗;
                    T_User_DiamondList userDiamondList = null;
                    if (diamondListId > 0)
                    {
                        userDiamondList = await cloudGamingBase.Dao.DaoUser.Context.T_User_DiamondList.FirstOrDefaultAsync(it => it.Id == diamondListId);
                    }
                    if (userDiamondList == null)
                    {
                        userDiamondList = new T_User_DiamondList()
                        {
                            CreateAt = DateTime.Now,
                            Consume = 0,
                            ConsumeType = (int)consumeType,
                            CurrencyType = (int)UserCurrencyType.钻石,
                            OrderCode = "",
                            Title = $"游玩《{gameName}》",
                            UpdateAt = DateTime.Now,
                            UserId = cloudGamingBase.UserInfo.UserId,
                            Extend = gameXiaoHao,
                        };
                        await cloudGamingBase.Dao.DaoUser.Context.AddAsync(userDiamondList);

                    }
                    userDiamondList.Consume += Math.Abs(money);
                    userDiamondList.UpdateAt = DateTime.Now;
                    await cloudGamingBase.Dao.DaoUser.Context.SaveChangesAsync();
                    diamondListId = userDiamondList.Id;
                }
            }
            catch (Exception ex)
            {

                return (false, _currencyLogId, diamondListId); ;
            }
            return (issuccess, _currencyLogId, diamondListId);

        }
        /// <summary>
        /// 扣除当前用户钻石
        /// </summary>
        /// <param name="cloudGamingBase"></param>
        /// <param name="userCurrencyType"></param>
        /// <returns></returns>
        public static async Task<bool> UserConsumeMoneyAsync(this CloudGamingBase cloudGamingBase, int userId, decimal money)
        {
            bool isSuccess = await UserConsumeDiamondMoneyAsync(userId, money, cloudGamingBase);
            if (isSuccess)
            {
                await cloudGamingBase.SaveUserInfoCacheChangesAsync();
            }
            return isSuccess;
        }


        /// <summary>
        /// 扣除当前用户钻石
        /// </summary>
        /// <param name="cloudGamingBase"></param>
        /// <param name="userCurrencyType"></param>
        /// <returns></returns>
        public static async Task<bool> UserConsumeDiamondMoneyAsync(int userId, decimal money, CloudGamingBase cloudGamingBase)
        {
            T_User_Currency currency = new T_User_Currency();
            var userConsumeMoney = new DiamondConsumeMoney(cloudGamingBase.Dao, userId, UserCurrencyType.钻石, currency);
            try
            {
                var isSuccess = await userConsumeMoney.ConsumeMoneyAsync(money);

                if (!isSuccess)
                {
                    return false;
                }
                //清除缓存
                string key = AccountExtend.GetUserInfoRedisKey(userId);
                var userInfo = await cloudGamingBase.RedisCache.StringGetAsync<UserInfoCache>(key);
                if (userInfo != null)
                {
                    userInfo.Diamond = (int)currency.CurrencyMoney;
                    await cloudGamingBase.RedisCache.StringSetAsync(key, userInfo, TimeSpan.FromMinutes(30));
                }
            }
            catch (Exception ex)
            {

                return false;
            }
            return true;
        }

    }
}
