/// <summary>
        /// Update team goal, personal goal and personal goal note details in storage if team goal cycle is ended.
        /// </summary>
        /// <param name="turnContext">Context object containing information cached for a single turn of conversation with a user.</param>
        /// <param name="teamGoalDetail">Holds team goal detail entity data sent from background service.</param>
        /// <param name="cancellationToken">Propagates notification that operations should be canceled.</param>
        /// <returns>A task that represents team goal, personal goal and personal goal note details data is saved or updated.</returns>
        private async Task UpdateGoalEntitiesAsync(ITurnContext turnContext, TeamGoalDetail teamGoalDetail, CancellationToken cancellationToken)
        {
            try
            {
                var teamGoalEntities = await this.teamGoalStorageProvider.GetTeamGoalDetailsByTeamIdAsync(teamGoalDetail.TeamId);

                // Update team goal details data when goal cycle is ended
                foreach (var teamGoalEntity in teamGoalEntities)
                {
                    teamGoalEntity.IsActive         = false;
                    teamGoalEntity.IsReminderActive = false;
                    teamGoalEntity.LastModifiedOn   = DateTime.UtcNow.ToString(CultureInfo.CurrentCulture);
                }

                await this.teamGoalStorageProvider.CreateOrUpdateTeamGoalDetailsAsync(teamGoalEntities);

                var teamMembers = await this.goalHelper.GetMembersInTeamAsync(turnContext, cancellationToken);

                foreach (var teamMember in teamMembers)
                {
                    var userAadObjectId    = teamMember.AadObjectId;
                    var alignedGoalDetails = await this.personalGoalStorageProvider.GetUserAlignedGoalDetailsByTeamIdAsync(teamGoalDetail.TeamId, userAadObjectId);

                    if (alignedGoalDetails.FirstOrDefault() != null)
                    {
                        // Update personal goal details data when goal cycle is ended for aligned goals
                        foreach (var personalGoalEntity in alignedGoalDetails)
                        {
                            personalGoalEntity.IsActive         = false;
                            personalGoalEntity.IsReminderActive = false;
                            personalGoalEntity.LastModifiedOn   = DateTime.UtcNow.ToString(CultureInfo.CurrentCulture);

                            var personalGoalNoteEntities = await this.personalGoalNoteStorageProvider.GetPersonalGoalNoteDetailsAsync(personalGoalEntity.PersonalGoalId, userAadObjectId);

                            // Update personal goal note details data when goal cycle is ended for aligned goals
                            foreach (var personalGoalNoteEntity in personalGoalNoteEntities)
                            {
                                personalGoalNoteEntity.IsActive       = false;
                                personalGoalNoteEntity.LastModifiedOn = DateTime.UtcNow.ToString(CultureInfo.CurrentCulture);
                            }

                            await this.personalGoalNoteStorageProvider.CreateOrUpdatePersonalGoalNoteDetailsAsync(personalGoalNoteEntities);
                        }

                        await this.personalGoalStorageProvider.CreateOrUpdatePersonalGoalDetailsAsync(alignedGoalDetails);
                    }
                }
            }
            catch (Exception ex)
            {
                this.logger.LogError(ex, $"Failed to save team goal detail data to table storage at {nameof(this.UpdateGoalEntitiesAsync)} for team id: {teamGoalDetail.TeamId}");
                throw;
            }
        }
        /// <summary>
        /// Method to update team goal, personal goal and note details in storage when team goal is ended.
        /// </summary>
        /// <param name="teamGoalDetail">Holds team goal detail entity data sent from background service.</param>
        /// <returns>A task that represents team goal, personal goal and personal goal note details data is saved or updated.</returns>
        public async Task UpdateGoalDetailsAsync(TeamGoalDetail teamGoalDetail)
        {
            teamGoalDetail = teamGoalDetail ?? throw new ArgumentNullException(nameof(teamGoalDetail));

            try
            {
                var    teamId     = teamGoalDetail.TeamId;
                string serviceUrl = teamGoalDetail.ServiceUrl;
                MicrosoftAppCredentials.TrustServiceUrl(serviceUrl);

                var conversationReference = new ConversationReference()
                {
                    ChannelId = Constants.TeamsBotFrameworkChannelId,
                    Bot       = new ChannelAccount()
                    {
                        Id = $"28:{this.microsoftAppCredentials.MicrosoftAppId}"
                    },
                    ServiceUrl   = serviceUrl,
                    Conversation = new ConversationAccount()
                    {
                        ConversationType = Constants.ChannelConversationType, IsGroup = true, Id = teamId, TenantId = this.options.Value.TenantId
                    },
                };

                await this.retryPolicy.ExecuteAsync(async() =>
                {
                    try
                    {
                        await((BotFrameworkAdapter)this.adapter).ContinueConversationAsync(
                            this.microsoftAppCredentials.MicrosoftAppId,
                            conversationReference,
                            async(turnContext, cancellationToken) =>
                        {
                            await this.UpdateGoalEntitiesAsync(turnContext, teamGoalDetail, cancellationToken);
                        },
                            CancellationToken.None);
                    }
                    catch (Exception ex)
                    {
                        this.logger.LogError(ex, $"Error while performing retry logic to send goal reminder card for : {teamGoalDetail.TeamGoalId}.");
                        throw;
                    }
                });
            }
            #pragma warning disable CA1031 // Catching general exceptions to log exception details in telemetry client.
            catch (Exception ex)
            #pragma warning restore CA1031 // Catching general exceptions to log exception details in telemetry client.
            {
                this.logger.LogError(ex, $"Error while updating personal goal, team goal and personal goal note detail from background service for : {teamGoalDetail.TeamGoalId} at {nameof(this.UpdateGoalDetailsAsync)}");
            }
        }
        /// <summary>
        /// Sends goal reminder card to each member of team if he/she has aligned goal with the team.
        /// </summary>
        /// <param name="turnContext">Context object containing information cached for a single turn of conversation with a user.</param>
        /// <param name="teamGoalDetail">Team goal details obtained from storage.</param>
        /// <param name="goalReminderActivity">Goal reminder activity to send.</param>
        /// <param name="cancellationToken">Propagates notification that operations should be canceled.</param>
        /// <returns>A Task represents goal reminder card is sent to team and team members.</returns>
        private async Task SendGoalReminderToTeamMembersAsync(ITurnContext turnContext, TeamGoalDetail teamGoalDetail, IMessageActivity goalReminderActivity, CancellationToken cancellationToken)
        {
            var teamMembers = await this.goalHelper.GetMembersInTeamAsync(turnContext, cancellationToken);

            ConversationReference conversationReference = null;

            foreach (var teamMember in teamMembers)
            {
                // Send goal reminder card to those team members who have aligned their personal goals with the team
                var alignedGoalDetails = await this.personalGoalStorageProvider.GetUserAlignedGoalDetailsByTeamIdAsync(teamGoalDetail.TeamId, teamMember.AadObjectId);

                if (alignedGoalDetails.Any())
                {
                    var conversationParameters = new ConversationParameters
                    {
                        Bot      = turnContext.Activity.Recipient,
                        Members  = new ChannelAccount[] { teamMember },
                        TenantId = turnContext.Activity.Conversation.TenantId,
                    };

                    try
                    {
                        await this.retryPolicy.ExecuteAsync(async() =>
                        {
                            await((BotFrameworkAdapter)turnContext.Adapter).CreateConversationAsync(
                                teamGoalDetail.TeamId,
                                teamGoalDetail.ServiceUrl,
                                new MicrosoftAppCredentials(this.microsoftAppCredentials.MicrosoftAppId, this.microsoftAppCredentials.MicrosoftAppPassword),
                                conversationParameters,
                                async(createConversationtTurnContext, cancellationToken1) =>
                            {
                                conversationReference = createConversationtTurnContext.Activity.GetConversationReference();
                                await((BotFrameworkAdapter)turnContext.Adapter).ContinueConversationAsync(
                                    this.microsoftAppCredentials.MicrosoftAppId,
                                    conversationReference,
                                    async(continueConversationTurnContext, continueConversationCancellationToken) =>
                                {
                                    this.logger.LogInformation($"Sending goal reminder card to: {teamMember.Name} from team: {teamGoalDetail.TeamId}");
                                    await continueConversationTurnContext.SendActivityAsync(goalReminderActivity, continueConversationCancellationToken);
                                },
                                    cancellationToken);
                            },
                                cancellationToken);
                        });
                    }
                    catch (Exception ex)
                    {
                        this.logger.LogError(ex, $"Error while sending goal reminder card to members of the team : {teamGoalDetail.TeamId} at {nameof(this.SendGoalReminderToTeamMembersAsync)}");
                        throw;
                    }
                }
            }
        }
        /// <summary>
        /// Method to send goal reminder card to team and team members or update team goal, personal goal and note details in storage.
        /// </summary>
        /// <param name="teamGoalDetail">Holds team goal detail entity data sent from background service.</param>
        /// <param name="isReminderBeforeThreeDays">Determines reminder to be sent prior 3 days to end date.</param>
        /// <returns>A Task represents goal reminder card is sent to team and team members.</returns>
        public async Task SendGoalReminderToTeamAndTeamMembersAsync(TeamGoalDetail teamGoalDetail, bool isReminderBeforeThreeDays = false)
        {
            teamGoalDetail = teamGoalDetail ?? throw new ArgumentNullException(nameof(teamGoalDetail));

            try
            {
                var    teamId     = teamGoalDetail.TeamId;
                string serviceUrl = teamGoalDetail.ServiceUrl;
                MicrosoftAppCredentials.TrustServiceUrl(serviceUrl);

                var conversationReference = new ConversationReference()
                {
                    ChannelId = Constants.TeamsBotFrameworkChannelId,
                    Bot       = new ChannelAccount()
                    {
                        Id = $"28:{this.microsoftAppCredentials.MicrosoftAppId}"
                    },
                    ServiceUrl   = serviceUrl,
                    Conversation = new ConversationAccount()
                    {
                        ConversationType = Constants.ChannelConversationType, IsGroup = true, Id = teamId, TenantId = this.options.Value.TenantId
                    },
                };

                await this.retryPolicy.ExecuteAsync(async() =>
                {
                    try
                    {
                        await((BotFrameworkAdapter)this.adapter).ContinueConversationAsync(
                            this.microsoftAppCredentials.MicrosoftAppId,
                            conversationReference,
                            async(turnContext, cancellationToken) =>
                        {
                            string reminderType = string.Empty;
                            AdaptiveTextColor reminderTypeColor = AdaptiveTextColor.Accent;
                            if (isReminderBeforeThreeDays)
                            {
                                reminderType      = this.localizer.GetString("TeamGoalEndingAfterThreeDays");
                                reminderTypeColor = AdaptiveTextColor.Warning;
                            }
                            else
                            {
                                reminderType = this.GetReminderTypeString(teamGoalDetail.ReminderFrequency);
                            }

                            var goalReminderAttachment = MessageFactory.Attachment(GoalReminderCard.GetGoalReminderCard(this.localizer, this.options.Value.ManifestId, this.options.Value.GoalsTabEntityId, reminderType, reminderTypeColor));
                            this.logger.LogInformation($"Sending goal reminder card to teamId: {teamId}");
                            await turnContext.SendActivityAsync(goalReminderAttachment, cancellationToken);
                            await this.SendGoalReminderToTeamMembersAsync(turnContext, teamGoalDetail, goalReminderAttachment, cancellationToken);
                        },
                            CancellationToken.None);
                    }
                    catch (Exception ex)
                    {
                        this.logger.LogError(ex, $"Error while performing retry logic to send goal reminder card for : {teamGoalDetail.TeamGoalId}.");
                        throw;
                    }
                });
            }
            #pragma warning disable CA1031 // Catching general exceptions to log exception details in telemetry client.
            catch (Exception ex)
            #pragma warning restore CA1031 // Catching general exceptions to log exception details in telemetry client.
            {
                this.logger.LogError(ex, $"Error while sending goal reminder in team from background service for : {teamGoalDetail.TeamGoalId} at {nameof(this.SendGoalReminderToTeamAndTeamMembersAsync)}");
            }
        }