using System;
using System.Linq;
using System.Threading.Tasks;
using Knoks.Core.Data.Interfaces;
using Knoks.Core.Entities;
using Knoks.Core.Entities.Args.AccountTransactions;
using Knoks.Framework.DataAccess;
using Microsoft.Extensions.Logging;
using AccountTransactionType = Knoks.Core.Entities.Args.AccountTransactions.AccountTransactionType;

namespace Knoks.Core.Data.Dao
{
    public class AccountTransactionDao : IAccountTransactionDao
    {
        private readonly IProcExecutor _executor;
        private readonly ILogger<AccountTransactionDao> _logger;

        public AccountTransactionDao(ILogger<AccountTransactionDao> logger, IProcExecutor executor)
        {
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _executor = executor ?? throw new ArgumentNullException(nameof(executor));
        }

        public async Task<long> SetBalance(AccountSetBalanceArgs args)
        {
            var transId = (await _executor.Go("TRN_Account_SetBalance", args)).OutputParams.First().Value;
            return Convert.ToInt64(transId);
        }

        public async Task TransferMoney(AccountSetBalanceArgs fromArgs, AccountSetBalanceArgs toArgs, long? knokId)
        {
            if(fromArgs.Amount != toArgs.Amount || fromArgs.AmountUSD != toArgs.AmountUSD)
                throw new ArgumentException($"Different amounts. Amount: {fromArgs.Amount} vs {toArgs.Amount}; AmountUSD: {fromArgs.AmountUSD} vs {toArgs.AmountUSD}");

            await _executor.Go("TRN_Account_TransferMoney", new 
            {
                FromUserId = fromArgs.UserId,
                FromAccountId = fromArgs.AccountId,
                FromExternalReferenceId = fromArgs.ExternalReferenceId,
                FromWalletAddress = fromArgs.WalletAddress,
                FromAccountTransactionTypeId = fromArgs.AccountTransactionTypeId,


                ToUserId = toArgs.UserId,
                ToAccountId = toArgs.AccountId,
                ToExternalReferenceId = toArgs.ExternalReferenceId,
                ToWalletAddress = toArgs.WalletAddress,
                ToAccountTransactionTypeId = toArgs.AccountTransactionTypeId,

                Amount = fromArgs.Amount,
                AmountUSD = fromArgs.AmountUSD,

                OperatorId = fromArgs.OperatorId,
                Comment = fromArgs.Comment,
                PendingId = fromArgs.PendingId,

                KnokId = knokId
            });
        }

        public async Task<AccountTransaction> GetLatestEvent(AccountTransactionType eventType)
        {
            var result = await _executor.Go("TRN_GetLatestAccountTransaction", new { AcountTransactionTypeId = (short)eventType });
            return result.Тables[0].Rows.Any() ? result.Тables[0][0].To<AccountTransaction>() : null;
        }
    }
}