private async Task <ServiceObjectResult <ICollection <AccountAccessContext> > > ObtainValidAccountContexts(string userId)
        {
            //Refresh access on all users accounts where required
            var accessRefreshResult = await _authorizationService.AttemptRefreshAccountContexts(userId);

            if (!accessRefreshResult.Success)
            {
                return(ServiceObjectResult <ICollection <AccountAccessContext> > .Failed(null, accessRefreshResult.Errors));
            }

            //ObtainAccessContexts
            var accessContextResult = await _accessCachingService.RetrieveAccessContexts(userId, new List <Scope> {
                Scope.transactions, Scope.accounts
            });

            if (!accessContextResult.Success)
            {
                return(ServiceObjectResult <ICollection <AccountAccessContext> > .Failed(null, accessContextResult.Errors));
            }

            if (accessContextResult.Result == null)
            {
                return(ServiceObjectResult <ICollection <AccountAccessContext> > .Failed(null, new List <string> {
                    ErrorMessages.UserNotFound
                }));
            }

            return(ServiceObjectResult <ICollection <AccountAccessContext> > .Succeeded(accessContextResult.Result));
        }
        public async Task <ServiceResult> AttemptRefreshAccountContexts(string userId)
        {
            var accessContextsForUser = await _accessContextCachingService.RetrieveAccessContexts(userId);

            if (!accessContextsForUser.Success)
            {
                return(ServiceResult.Failed(accessContextsForUser.Errors));
            }

            if (!accessContextsForUser.Result.Any(x => x.IsExpiredOrClose))
            {
                return(ServiceResult.Succeeded());
            }

            foreach (var accessContext in accessContextsForUser.Result.Where(x => x.IsExpiredOrClose))
            {
                if (accessContext.RefreshToken == null)
                {
                    await _accessContextCachingService.RemoveAccessContext(accessContext);

                    continue;
                }

                var authResponseResult = await _trueLayerDataRequestExecutor.RefreshAccountAccess(accessContext);

                if (!authResponseResult.Success)
                {
                    return(ServiceResult.Failed(authResponseResult.Errors));
                }

                accessContext.AccessToken       = authResponseResult.Result.AccessToken;
                accessContext.RefreshToken      = authResponseResult.Result.RefreshToken;
                accessContext.AccessTokenExpiry =
                    DateTime.UtcNow.AddSeconds(authResponseResult.Result.ExpiresIn);

                var updateCacheResult = await _accessContextCachingService.PutAccessContext(accessContext);

                if (!updateCacheResult.Success)
                {
                    return(ServiceResult.Failed(updateCacheResult.Errors));
                }
            }

            return(ServiceResult.Succeeded());
        }