from typing import *

from person import Person

class BankAccount:
    """ 
    Represents a bank account with a number, an owner, a balance, and a transaction history.
    """
    def __init__(self, account_number: int, owner: Person):
        """ 
        Initializes a new instance of the BankAccount class. Adds the account to the owner's list of accounts.
        
        Parameters:
        -----------
        account_number: int
            The account number.
        owner: Person
            The owner of the account.
        Raises:
        -------
        ValueError: If the owner is None.
        """
        if owner is None:
            raise ValueError("Owner must be specified")
        self.__account_number = account_number
        self.__owner = owner
        self.__balance = 0
        self.__history = []
        owner.add_account(self)

    def deposit(self, amount: float):
        """ 
        Deposits the specified amount to the balance of the bank account.
        
        Parameters:
        -----------
        amount: float
            The amount to deposit.
        Raises:
        -------
        ValueError: If the amount is not positive.
        """
        if amount < 0:
            raise ValueError("Amount must be positive")
        self.__balance += amount
        self.__history.append(amount)

    def withdraw(self, amount: float):
        """ 
        Withdraws the specified amount from the balance of the bank account.
        
        Parameters:
        -----------
        amount: float
            The amount to withdraw.
        Raises:
        -------
        ValueError: If the amount is not positive or greater than the balance.
        """
        if 0 < amount <= self.__balance:
          self.__balance -= amount
          self.__history.append(-amount)
        else:
          raise ValueError("Amount must be positive and less than the balance")

    def get_account_number(self) -> int:
        """ 
        Returns the account number of the bank account.
        """
        return self.__account_number

    def get_balance(self) -> float:
        """ 
        Returns the balance of the bank account.

        Returns:
        --------
        The balance of the bank account.
        """
        return self.__balance

    def get_transaction_history(self) -> List[float]:
        """ 
        Returns the transaction history of the bank account.

        Returns:
        --------
        The transaction history of the bank account.
        """
        return self.__history

    def get_owner(self) -> Person:
        """ 
        Returns the owner of the bank account.

        Returns:
        --------
        The owner of the bank account.
        """
        return self.__owner

    def __str__(self) -> str:
        return f"Account number {self.__account_number} from {self.__owner.fullname()} has {self.__balance} € and has done {len(self.__history)} transactions"

    def __repr__(self) -> str:
        return f"Account number {self.__account_number}: {self.__owner.fullname()} has {self.__balance} € and has done {len(self.__history)} transactions"