/// <inheritdoc />
        public void Deposit(string accountId, decimal amount)
        {
            accountId = accountId ?? throw new ArgumentNullException($"{nameof(accountId)} cannot be null.");
            amount    = amount >= 0
                    ? amount
                    : throw new ArgumentOutOfRangeException($"{nameof(amount)} cannot be less than zero.");

            BankAccountDto bankAccountDto = repository.GetAccountById(accountId) ??
                                            throw new ArgumentException($"Such account doesn't exist.");

            BankAccount account = bankAccountDto.ToAccount();

            DepositToAccount(account, amount);

            repository.Update(account.ToAccountDto(AccountResolver.GetBankAccountTypeName(account.GetType())));
            unitOfWork.Commit();
        }
        /// <inheritdoc />
        public string OpenAccount(string firstName, string lastName, AccountType accountType)
        {
            firstName = firstName ?? throw new ArgumentNullException($"{nameof(firstName)} cannot be null.");
            lastName  = lastName ?? throw new ArgumentNullException($"{nameof(lastName)} cannot be null.");

            string accountId = accountIdGeneratorService.GenerateId(firstName, lastName, accountType.ToString());

            if (repository.GetAccountById(accountId) != null)
            {
                throw new ArgumentException("Such account already exists.");
            }

            BankAccount account = AccountResolver.CreateAccount(accountType.ToString(), accountId, firstName, lastName);

            repository.Add(account.ToAccountDto(accountType.ToString()));
            unitOfWork.Commit();

            return(accountId);
        }
        /// <inheritdoc />
        public void CloseAccount(string accountId)
        {
            accountId = accountId ?? throw new ArgumentNullException($"{nameof(accountId)} cannot be null.");

            BankAccountDto accountDto = repository.GetAccountById(accountId) ??
                                        throw new ArgumentException($"Such account doesn't exist.");

            if (accountDto.IsClosed)
            {
                throw new InvalidOperationException($"Specified account is already closed.");
            }

            BankAccount account = accountDto.ToAccount();

            account.Close();

            repository.Update(account.ToAccountDto(AccountResolver.GetBankAccountTypeName(account.GetType())));
            unitOfWork.Commit();
        }
        /// <inheritdoc />
        public void Transfer(string destinationAccountId, string sourceAccountId, decimal amount)
        {
            destinationAccountId = destinationAccountId
                                   ?? throw new ArgumentNullException($"{nameof(destinationAccountId)} cannot be null.");

            sourceAccountId = sourceAccountId
                              ?? throw new ArgumentNullException($"{nameof(sourceAccountId)} cannot be null.");

            amount = amount <= 0
                ? throw new ArgumentOutOfRangeException($"{nameof(amount)} cannot be less than zero")
                : amount;

            var destinationAccount = repository.GetAccountById(destinationAccountId)?.ToAccount()
                                     ?? throw new ArgumentException($"Account with {destinationAccountId} doesn't exist");

            var sourceAccount = repository.GetAccountById(sourceAccountId)?.ToAccount()
                                ?? throw new ArgumentException($"Account with {sourceAccountId} doesn't exist");

            try
            {
                WithdrawFromAccount(sourceAccount, amount);
                DepositToAccount(destinationAccount, amount);

                repository.Update(sourceAccount.ToAccountDto(
                                      AccountResolver.GetBankAccountTypeName(sourceAccount.GetType())));
                repository.Update(destinationAccount.ToAccountDto(
                                      AccountResolver.GetBankAccountTypeName(destinationAccount.GetType())));

                unitOfWork.Commit();
            }
            catch (InvalidOperationException)
            {
                // How to restore?
                throw;
            }
        }