/// <summary>Method used to execute the query</summary>
        /// <param name="query">Query to execute.</param>
        /// <returns>Task which will contain the result once completed.</returns>
        public async Task <GetReportResult> ExecuteAsync(GetReport query)
        {
            var report = await _repository.GetAsync(query.ReportId);

            var collections = Enumerable.ToList((
                                                    from x in report.ContextCollections
                                                    where x.Properties.Count > 0
                                                    let properties = Enumerable.Select(x.Properties, y => new KeyValuePair(y.Key, y.Value))
                                                                     select new GetReportResultContextCollection(x.Name, Enumerable.ToArray(properties))
                                                    ));

            //TODO: Fix feedback
            //var feedbackQuery = new GetReportFeedback(query.ReportId, query.);//TODO: Fix customerId
            //var feedback = await _queryBus.QueryAsync(feedbackQuery);
            //if (feedback != null)
            //{
            //    collections.Add(new GetReportResultContextCollection("UserFeedback", new[]
            //    {
            //        new KeyValuePair("EmailAddress", feedback.EmailAddress),
            //        new KeyValuePair("Description", feedback.Description)
            //    })
            //        );
            //}

            return(new GetReportResult
            {
                ContextCollections = collections.ToArray(),
                CreatedAtUtc = report.CreatedAtUtc,
                ErrorId = report.ReportId,
                Exception = ConvertException(report.Exception),
                Id = report.Id.ToString(),
                IncidentId = report.IncidentId.ToString(),
                Message = report.Exception.Message,
                StackTrace = report.Exception.StackTrace
                             //UserFeedback = feedback != null ? feedback.Description : "",
                             //EmailAddress = feedback != null ? feedback.EmailAddress : ""
                             //                ReportHashCode = report.
            });
        }
        public async Task ExecuteAsync(SubmitFeedback command)
        {
            ReportDTO report;

            if (command.ReportId > 0)
            {
                report = await _reportsRepository.GetAsync(command.ReportId);
            }
            else
            {
                report = await _reportsRepository.FindByErrorIdAsync(command.ErrorId);
            }


            // storing it without connections as the report might not have been uploaded yet.
            if (report == null)
            {
                _logger.InfoFormat(
                    "Failed to find report. Let's enqueue it instead for report {0}/{1}. Email: {2}, Feedback: {3}",
                    command.ReportId, command.ErrorId, command.Email, command.Feedback);
                try
                {
                    using (var cmd = _unitOfWork.CreateCommand())
                    {
                        cmd.CommandText = "INSERT INTO IncidentFeedback (ErrorReportId, RemoteAddress, Description, EmailAddress, CreatedAtUtc, Conversation, ConversationLength) "
                                          +
                                          "VALUES (@ErrorReportId, @RemoteAddress, @Description, @EmailAddress, @CreatedAtUtc, '', 0)";
                        cmd.AddParameter("ErrorReportId", command.ErrorId);
                        cmd.AddParameter("RemoteAddress", command.RemoteAddress);
                        cmd.AddParameter("Description", command.Feedback);
                        cmd.AddParameter("EmailAddress", command.Email);
                        cmd.AddParameter("CreatedAtUtc", DateTime.UtcNow);
                        cmd.ExecuteNonQuery();
                    }
                }
                catch (Exception exception)
                {
                    _logger.Error(
                        string.Format("{0}: Failed to store '{1}' '{2}'", command.ErrorId, command.Email,
                                      command.Feedback), exception);
                    //hide errors.
                }

                return;
            }

            using (var cmd = (DbCommand)_unitOfWork.CreateCommand())
            {
                cmd.CommandText = "INSERT INTO IncidentFeedback (ErrorReportId, ApplicationId, ReportId, IncidentId, RemoteAddress, Description, EmailAddress, CreatedAtUtc, Conversation, ConversationLength) "
                                  +
                                  "VALUES (@ErrorReportId, @ApplicationId, @ReportId, @IncidentId, @RemoteAddress, @Description, @EmailAddress, @CreatedAtUtc, @Conversation, 0)";
                cmd.AddParameter("ErrorReportId", command.ErrorId);
                cmd.AddParameter("ApplicationId", report.ApplicationId);
                cmd.AddParameter("ReportId", report.Id);
                cmd.AddParameter("IncidentId", report.IncidentId);
                cmd.AddParameter("RemoteAddress", command.RemoteAddress);
                cmd.AddParameter("Description", command.Feedback);
                cmd.AddParameter("EmailAddress", command.Email);
                cmd.AddParameter("Conversation", "");
                cmd.AddParameter("CreatedAtUtc", DateTime.UtcNow);

                var evt = new FeedbackAttachedToIncident
                {
                    Message          = command.Feedback,
                    UserEmailAddress = command.Email,
                    IncidentId       = report.IncidentId
                };
                await _eventBus.PublishAsync(evt);

                await cmd.ExecuteNonQueryAsync();
            }
        }
        public async Task HandleAsync(IMessageContext context, SubmitFeedback command)
        {
            if (string.IsNullOrEmpty(command.Email))
            {
                if (string.IsNullOrEmpty(command.Feedback))
                {
                    return;
                }
                if (command.Feedback.Length < 3)
                {
                    return;
                }
            }

            ReportMapping report2;
            int?          reportId = null;

            if (command.ReportId > 0)
            {
                var report = await _reportsRepository.GetAsync(command.ReportId);

                report2 = new ReportMapping
                {
                    ApplicationId = report.ApplicationId,
                    ErrorId       = report.ClientReportId,
                    IncidentId    = report.IncidentId,
                    ReceivedAtUtc = report.CreatedAtUtc
                };
                reportId = report.Id;
            }
            else
            {
                report2 = await _reportsRepository.FindByErrorIdAsync(command.ErrorId);

                if (report2 == null)
                {
                    _logger.Warn("Failed to find report by error id: " + command.ErrorId);
                }
            }

            // storing it without connections as the report might not have been uploaded yet.
            if (report2 == null)
            {
                _logger.InfoFormat(
                    "Failed to find report. Let's enqueue it instead for report {0}/{1}. Email: {2}, Feedback: {3}",
                    command.ReportId, command.ErrorId, command.Email, command.Feedback);
                try
                {
                    using (var cmd = _unitOfWork.CreateCommand())
                    {
                        cmd.CommandText =
                            "INSERT INTO IncidentFeedback (ErrorReportId, RemoteAddress, Description, EmailAddress, CreatedAtUtc, Conversation, ConversationLength) "
                            +
                            "VALUES (@ErrorReportId, @RemoteAddress, @Description, @EmailAddress, @CreatedAtUtc, '', 0)";
                        cmd.AddParameter("ErrorReportId", command.ErrorId);
                        cmd.AddParameter("RemoteAddress", command.RemoteAddress);
                        cmd.AddParameter("Description", command.Feedback);
                        cmd.AddParameter("EmailAddress", command.Email);
                        cmd.AddParameter("CreatedAtUtc", DateTime.UtcNow);
                        cmd.ExecuteNonQuery();
                    }

                    _logger.Info("** STORING FEEDBACK");
                }
                catch (Exception exception)
                {
                    _logger.Error(
                        $"{command.ErrorId}: Failed to store '{command.Email}' '{command.Feedback}'", exception);
                    //hide errors.
                }

                return;
            }

            using (var cmd = (DbCommand)_unitOfWork.CreateCommand())
            {
                cmd.CommandText =
                    "INSERT INTO IncidentFeedback (ErrorReportId, ApplicationId, ReportId, IncidentId, RemoteAddress, Description, EmailAddress, CreatedAtUtc, Conversation, ConversationLength) "
                    +
                    "VALUES (@ErrorReportId, @ApplicationId, @ReportId, @IncidentId, @RemoteAddress, @Description, @EmailAddress, @CreatedAtUtc, @Conversation, 0)";
                cmd.AddParameter("ErrorReportId", command.ErrorId);
                cmd.AddParameter("ApplicationId", report2.ApplicationId);
                cmd.AddParameter("ReportId", reportId);
                cmd.AddParameter("IncidentId", report2.IncidentId);
                cmd.AddParameter("RemoteAddress", command.RemoteAddress);
                cmd.AddParameter("Description", command.Feedback);
                cmd.AddParameter("EmailAddress", command.Email);
                cmd.AddParameter("Conversation", "");
                cmd.AddParameter("CreatedAtUtc", DateTime.UtcNow);

                var app = await _applicationRepository.GetByIdAsync(report2.ApplicationId);

                var evt = new FeedbackAttachedToIncident
                {
                    ApplicationId    = report2.ApplicationId,
                    ApplicationName  = app.Name,
                    Message          = command.Feedback,
                    UserEmailAddress = command.Email,
                    IncidentId       = report2.IncidentId
                };
                await context.SendAsync(evt);

                await cmd.ExecuteNonQueryAsync();
            }
        }