public async Task<ActionResult> Review(ListingReview listingReview)
        {
            var currentUserId = User.Identity.GetUserId();

            var orderQuery = await _orderService.Query(x => x.ID == listingReview.OrderID)
                .Include(x => x.Listing)
                .SelectAsync();

            var order = orderQuery.FirstOrDefault();

            var userTo = order.UserProvider == currentUserId ? order.UserReceiver : order.UserProvider;

            // User cannot comment himself
            if (currentUserId == userTo)
            {
                TempData[TempDataKeys.UserMessageAlertState] = "bg-danger";
                TempData[TempDataKeys.UserMessage] = "[[[You cannot review yourself!]]]";
                return RedirectToAction("Orders", "Payment");
            }

            // check if user has right to review the order
            if (order == null || (order.UserProvider != currentUserId && order.UserReceiver != currentUserId))
            {
                TempData[TempDataKeys.UserMessageAlertState] = "bg-danger";
                TempData[TempDataKeys.UserMessage] = "[[[You cannot review the order!]]]";
                return RedirectToAction("Orders", "Payment");
            }

            // update review id on the order
            var review = new ListingReview()
            {
                UserFrom = currentUserId,
                UserTo = userTo,
                OrderID = listingReview.OrderID,
                Description = listingReview.Description,
                Rating = listingReview.Rating,
                Spam = false,
                Active = true,
                Enabled = true,
                ObjectState = Repository.Pattern.Infrastructure.ObjectState.Added,
                Created = DateTime.Now
            };

            // Set listing id if it's service receiver
            if (order.UserReceiver == currentUserId)
                review.ListingID = order.ListingID;

            _listingReviewService.Insert(review);

            await _unitOfWorkAsync.SaveChangesAsync();

            // update rating on the user            
            var listingReviewQuery = await _listingReviewService.Query(x => x.UserTo == userTo).SelectAsync();
            var rating = listingReviewQuery.Average(x => x.Rating);

            var user = await UserManager.FindByIdAsync(userTo);
            user.Rating = rating;
            await UserManager.UpdateAsync(user);

            // Notify the user with the rating and comment
            var message = new MessageSendModel()
            {
                UserFrom = review.UserFrom,
                UserTo = review.UserTo,
                Subject = review.Title,
                Body = string.Format("{0} <span class=\"score s{1} text-xs\"></span>", review.Description, review.RatingClass),
                ListingID = order.ListingID
            };

            await MessageHelper.SendMessage(message);

            TempData[TempDataKeys.UserMessage] = "[[[Thanks for your feedback!]]]";
            return RedirectToAction("Orders", "Payment");
        }
        public async Task<ActionResult> ReviewListing(ListingReview listingReview)
        {
            var currentUserId = User.Identity.GetUserId();

            // Check if listing review is enabled
            if (!CacheHelper.Settings.ListingReviewEnabled)
            {
                TempData[TempDataKeys.UserMessageAlertState] = "bg-danger";
                TempData[TempDataKeys.UserMessage] = "[[[Listing review is not allowed!]]]";
                return RedirectToAction("Listing", "Listing", new { id = listingReview.ID });
            }

            // Check if users reach max review limit       
            var today = DateTime.Today.Date;
            var reviewQuery = await _listingReviewService.Query(x => x.UserFrom == currentUserId
            && System.Data.Entity.DbFunctions.TruncateTime(x.Created) == today).SelectAsync();
            var reviewCount = reviewQuery.Count();

            if (reviewCount >= CacheHelper.Settings.ListingReviewMaxPerDay)
            {
                TempData[TempDataKeys.UserMessageAlertState] = "bg-danger";
                TempData[TempDataKeys.UserMessage] = "[[[You have reach the review limits today!]]]";
                return RedirectToAction("Listing", "Listing", new { id = listingReview.ID });
            }

            var listingQuery = await _listingService.Query(x => x.ID == listingReview.ID)
                .Include(x => x.AspNetUser)
                .SelectAsync();

            var listing = listingQuery.FirstOrDefault();

            // User cannot comment himself
            if (currentUserId == listing.UserID)
            {
                TempData[TempDataKeys.UserMessageAlertState] = "bg-danger";
                TempData[TempDataKeys.UserMessage] = "[[[You cannot review yourself!]]]";
                return RedirectToAction("Listing", "Listing", new { id = listingReview.ID });
            }

            // update review id on the order
            var review = new ListingReview()
            {
                UserFrom = currentUserId,
                UserTo = listing.UserID,
                Description = listingReview.Description,
                Rating = listingReview.Rating,
                Spam = false,
                Active = true,
                Enabled = true,
                ObjectState = Repository.Pattern.Infrastructure.ObjectState.Added,
                Created = DateTime.Now
            };

            review.ListingID = listingReview.ID;

            _listingReviewService.Insert(review);

            await _unitOfWorkAsync.SaveChangesAsync();

            // update rating on the user            
            var listingReviewQuery = await _listingReviewService.Query(x => x.UserTo == listing.UserID).SelectAsync();
            var rating = listingReviewQuery.Average(x => x.Rating);

            var user = await UserManager.FindByIdAsync(listing.UserID);
            user.Rating = rating;
            await UserManager.UpdateAsync(user);

            // Notify the user with the rating and comment
            var message = new MessageSendModel()
            {
                UserFrom = review.UserFrom,
                UserTo = review.UserTo,
                Subject = review.Title,
                Body = string.Format("{0} <span class=\"score s{1} text-xs\"></span>", review.Description, review.RatingClass),
                ListingID = listingReview.ID
            };

            await MessageHelper.SendMessage(message);

            TempData[TempDataKeys.UserMessage] = "[[[Thanks for your feedback!]]]";
            return RedirectToAction("Listing", "Listing", new { id = listingReview.ID });
        }
        /// <summary>
        /// review for an order on a listing
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ActionResult> Review(int id)
        {
            var currentUserId = User.Identity.GetUserId();

            // check if user has right to review the order            
            var reviewModel = new ListingReview();

            var orderQuery = await _orderService
                .Query(x => x.ID == id)
                .Include(x => x.Listing)
                .Include(x => x.Listing.AspNetUser)
                .Include(x => x.Listing.ListingType)
                .Include(x => x.Listing.ListingReviews)
                .Include(x => x.AspNetUserProvider)
                .Include(x => x.AspNetUserReceiver)
                .SelectAsync();

            var order = orderQuery.FirstOrDefault();

            reviewModel.Listing = order.Listing;
            reviewModel.OrderID = order.ID;
            reviewModel.ListingID = order.ListingID;

            // set user for review
            reviewModel.AspNetUserTo = currentUserId == order.UserProvider ? order.AspNetUserReceiver : order.AspNetUserProvider;

            return View(reviewModel);
        }