using System.Linq;
using GTANetworkAPI;
using ReallifeGamemode.Database;
using ReallifeGamemode.Database.Entities;
using ReallifeGamemode.Database.Entities.Logs;
using ReallifeGamemode.Database.Models;
using ReallifeGamemode.Server.Util;

/**
* @overview Life of German Reallife - Managers BankManager (BankManager.cs)
* @author VegaZ
* @copyright (c) 2008 - 2018 Life of German
*/

namespace ReallifeGamemode.Server.Managers
{
  public class BankManager
  {
    public static TransactionResult SetMoney(Player admin, IBankAccountOwner owner, int amount, string reason = "Von Admin gesetzt")
    {
      using (var transferMoney = new DatabaseContext())
      {
        if (amount < 0) return TransactionResult.NEGATIVE_MONEY_SENT;

        IBankAccount account = owner.GetBankAccount(transferMoney);

        if (account == null) return TransactionResult.RECEIVER_NO_BANKACCOUNT;

        var transactionLog = new BankAccountTransactionHistory
        {
          Sender = "ADMIN: " + admin.Name,
          SenderBalance = 0,
          Receiver = owner.Name,
          ReceiverBalance = amount,
          NewReceiverBalance = amount,
          NewSenderBalance = 0,
          MoneySent = amount,
          Fee = 0,
          Origin = reason
        };

        // add log
        transferMoney.BankAccountTransactionLogs.Add(transactionLog);

        account.Balance = amount;

        transferMoney.SaveChanges();

        return TransactionResult.SUCCESS;
      }
    }

    public static TransactionResult TransferMoney<TSender, TReceiver>(
      BankAccountHolder<TSender> sender,
      BankAccountHolder<TReceiver> receiver,
      int amount,
      string origin,
      DatabaseContext dbContext) where TSender : class, IBankAccount, new() where TReceiver : class, IBankAccount, new()
    {
      if (amount < 0) return TransactionResult.NEGATIVE_MONEY_SENT;

      IBankAccount senderAccount;
      IBankAccount receiverAccount;

      if (sender is BankAccountHolder<BusinessBankAccount> businessSender)
      {
        senderAccount = dbContext.BusinessBankAccounts.Where(b => b.Id == businessSender.BankAccountId).First();
      }
      else
      {
        senderAccount = sender.BankAccount;
      }

      if (receiver is BankAccountHolder<BusinessBankAccount> businessReceiver)
      {
        receiverAccount = dbContext.BusinessBankAccounts.Where(b => b.Id == businessReceiver.BankAccountId).First();
      }
      else
      {
        receiverAccount = receiver.BankAccount;
      }

      if (senderAccount == null) return TransactionResult.SENDER_NO_BANKACCOUNT;
      if (receiverAccount == null) return TransactionResult.RECEIVER_NO_BANKACCOUNT;

      if (senderAccount.Balance < amount) return TransactionResult.SENDER_NOT_ENOUGH_MONEY;

      var transactionLog = new BankAccountTransactionHistory
      {
        Sender = sender.BankAccountName,
        SenderBalance = senderAccount.Balance,
        Receiver = receiver.BankAccountName,
        ReceiverBalance = receiverAccount.Balance,
        NewReceiverBalance = receiverAccount.Balance + amount,
        NewSenderBalance = senderAccount.Balance - amount,
        MoneySent = amount,
        Fee = 0,
        Origin = origin
      };

      // add log
      dbContext.BankAccountTransactionLogs.Add(transactionLog);

      senderAccount.Balance -= amount;
      receiverAccount.Balance += amount;

      dbContext.SaveChanges();

      return TransactionResult.SUCCESS;
    }
  }
}
