"""
Contains the code that deals with money.

*Classes*
---------
  Money
    Deals with money.
"""
import interactions  # Used for typehints
import discord  # Used for typehints


class Money():
  """
  Deals with money.

  *Methods*
  ---------
    checkBalance(user: str)
    sendBalance(ctx: interactions.SlashContext)
    addMoney(user: str, amount: int)
    giveMoney(ctx: interactions.SlashContext, user: discord.User,
          amount: int)

  *Attributes*
  ------------
    bot: Gwendolyn
      The instance of Gwendolyn
    database: pymongo.Client
      The mongo database
  """

  def __init__(self, bot):
    """Initialize the class."""
    self.bot = bot
    self.database = bot.database

  def checkBalance(self, user: str):
    """
    Get the account balance of a user.

    *Parameters*
    ------------
      user: str
        The user to get the balance of.

    *Returns*
    ---------
      balance: int
        The balance of the user's account.
    """
    self.bot.log("checking "+user+"'s account balance")

    user_data = self.database["users"].find_one({"_id": user})

    if user_data is not None:
      return user_data["money"]
    else:
      return 0

  async def sendBalance(self, ctx: interactions.SlashContext):
    """
    Get your own account balance.

    *Parameters*
    ------------
      ctx: interactions.SlashContext
        The context of the command.
    """
    await self.bot.defer(ctx)
    response = self.checkBalance("#"+str(ctx.author.id))
    user_name = ctx.author.display_name
    if response == 1:
      new_message = f"{user_name} has {response} GwendoBuck"
    else:
      new_message = f"{user_name} has {response} GwendoBucks"
    await ctx.send(new_message)

  # Adds money to the account of a user
  def addMoney(self, user: str, amount: int):
    """
    Add money to a user account.

    *Parameters*
    ------------
      user: str
        The id of the user to give money.
      amount: int
        The amount to add to the user's account.
    """
    self.bot.log("adding "+str(amount)+" to "+user+"'s account")

    user_data = self.database["users"].find_one({"_id": user})

    if user_data is not None:
      updater = {"$inc": {"money": amount}}
      self.database["users"].update_one({"_id": user}, updater)
    else:
      new_user = {
        "_id": user,
        "user name": self.bot.database_funcs.get_name(user),
        "money": amount
      }
      self.database["users"].insert_one(new_user)

  # Transfers money from one user to another
  async def giveMoney(self, ctx: interactions.SlashContext,
            user: discord.User, amount: int):
    """
    Give someone else money from your account.

    *Parameters*
    ------------
      ctx: interactions.SlashContext
        The context of the command.
      user: discord.User
        The user to give money.
      amount: int
        The amount to transfer.
    """
    await self.bot.defer(ctx)
    username = user.display_name
    if self.bot.database_funcs.get_id(username) is None:
      async for member in ctx.guild.fetch_members(limit=None):
        if member.display_name.lower() == username.lower():
          username = member.display_name
          user_id = f"#{member.id}"
          new_user = {
            "_id": user_id,
            "user name": username,
            "money": 0
          }
          self.bot.database["users"].insert_one(new_user)

    userid = f"#{ctx.author.id}"
    user_data = self.database["users"].find_one({"_id": userid})
    targetUser = self.bot.database_funcs.get_id(username)

    if amount <= 0:
      self.bot.log("They tried to steal")
      await ctx.send("Yeah, no. You can't do that")
    elif targetUser is None:
      self.bot.log("They weren't in the system")
      await ctx.send("The target doesn't exist")
    elif user_data is None or user_data["money"] < amount:
      self.bot.log("They didn't have enough GwendoBucks")
      await ctx.send("You don't have that many GwendoBuck")
    else:
      self.addMoney(f"#{ctx.author.id}", -1 * amount)
      self.addMoney(targetUser, amount)
      await ctx.send(f"Transferred {amount} GwendoBucks to {username}")
