public virtual async Task <IActionResult> ProductDetails(string productId, string updatecartitemid = "")
        {
            var product = await _productService.GetProductById(productId);

            if (product == null)
            {
                return(InvokeHttp404());
            }

            var customer = _workContext.CurrentCustomer;

            //published?
            if (!_catalogSettings.AllowViewUnpublishedProductPage)
            {
                //Check whether the current user has a "Manage catalog" permission
                //It allows him to preview a product before publishing
                if (!product.Published && !await _permissionService.Authorize(StandardPermissionProvider.ManageProducts, customer))
                {
                    return(InvokeHttp404());
                }
            }

            //ACL (access control list)
            if (!_aclService.Authorize(product, customer))
            {
                return(InvokeHttp404());
            }

            //Store mapping
            if (!_storeMappingService.Authorize(product))
            {
                return(InvokeHttp404());
            }

            //availability dates
            if (!product.IsAvailable() && !(product.ProductType == ProductType.Auction))
            {
                return(InvokeHttp404());
            }

            //visible individually?
            if (!product.VisibleIndividually)
            {
                //is this one an associated products?
                var parentGroupedProduct = await _productService.GetProductById(product.ParentGroupedProductId);

                if (parentGroupedProduct == null)
                {
                    return(RedirectToRoute("HomePage"));
                }

                return(RedirectToRoute("Product", new { SeName = parentGroupedProduct.GetSeName(_workContext.WorkingLanguage.Id) }));
            }
            //update existing shopping cart item?
            ShoppingCartItem updatecartitem = null;

            if (_shoppingCartSettings.AllowCartItemEditing && !String.IsNullOrEmpty(updatecartitemid))
            {
                var cart = _shoppingCartService.GetShoppingCart(_storeContext.CurrentStore.Id);

                updatecartitem = cart.FirstOrDefault(x => x.Id == updatecartitemid);
                //not found?
                if (updatecartitem == null)
                {
                    return(RedirectToRoute("Product", new { SeName = product.GetSeName(_workContext.WorkingLanguage.Id) }));
                }
                //is it this product?
                if (product.Id != updatecartitem.ProductId)
                {
                    return(RedirectToRoute("Product", new { SeName = product.GetSeName(_workContext.WorkingLanguage.Id) }));
                }
            }

            //prepare the model
            var model = await _productViewModelService.PrepareProductDetailsPage(product, updatecartitem, false);

            //product template
            var productTemplateViewPath = await _productViewModelService.PrepareProductTemplateViewPath(product.ProductTemplateId);

            //save as recently viewed
            await _recentlyViewedProductsService.AddProductToRecentlyViewedList(customer.Id, product.Id);

            //display "edit" (manage) link
            if (await _permissionService.Authorize(StandardPermissionProvider.AccessAdminPanel, customer) &&
                await _permissionService.Authorize(StandardPermissionProvider.ManageProducts, customer))
            {
                //a vendor should have access only to his products
                if (_workContext.CurrentVendor == null || _workContext.CurrentVendor.Id == product.VendorId)
                {
                    DisplayEditLink(Url.Action("Edit", "Product", new { id = product.Id, area = "Admin" }));
                }
            }

            //activity log
            await _customerActivityService.InsertActivity("PublicStore.ViewProduct", product.Id, _localizationService.GetResource("ActivityLog.PublicStore.ViewProduct"), product.Name);

            await _customerActionEventService.Viewed(customer, this.HttpContext.Request.Path.ToString(), this.Request.Headers[HeaderNames.Referer].ToString() != null?Request.Headers[HeaderNames.Referer].ToString() : "");

            await _productService.UpdateMostView(productId, 1);

            return(View(productTemplateViewPath, model));
        }