public async Task <IActionResult> UpdateManufacturerAsync(int id, [FromBody] Manufacturer updateModel,
                                                                  CancellationToken cancellationToken)
        {
            var item = await _catalogContext.Manufacturers
                       .SingleOrDefaultAsync(i => i.Id == id, cancellationToken);

            if (item == null)
            {
                return(NotFound(new { Message = $"Item with id {updateModel.Id} not found." }));
            }
            if (string.IsNullOrEmpty(updateModel.ImageName) || string.IsNullOrEmpty(updateModel.ImageUrl))
            {
                return(BadRequest(new { Message = $"Image is empty." }));
            }
            var oldImageName = item.ImageName;

            #region Mapping

            item.ImageName   = updateModel.ImageName;
            item.Description = updateModel.Description;
            item.Name        = updateModel.Name;

            #endregion

            // Update current product
            _catalogContext.Manufacturers.Update(item);

            await _catalogContext.SaveChangesAsync(cancellationToken);

            _fileUtility.DeleteFile("Manufacturer/" + updateModel.Id, oldImageName);
            await InsertManufacturerImageAsync(updateModel, cancellationToken, id);

            return(CreatedAtAction(nameof(UpdateManufacturerAsync), new { id = item.Id }, null));
        }
        public async Task <IActionResult> UpdateProductAsync(string id, [FromBody] ProductViewModel updateModel,
                                                             CancellationToken cancellationToken)
        {
            try
            {
                var item = await _catalogContext.Products
                           .Include(x => x.ProductImages)
                           .Include(x => x.ProductColors)
                           .SingleOrDefaultAsync(i => i.Id == id, cancellationToken);

                if (item == null)
                {
                    return(NotFound(new { Message = $"Item with id {updateModel.Id} not found." }));
                }

                if (updateModel.CategoryId <= 0 || updateModel.ManufacturerId <= 0)
                {
                    return(BadRequest(new
                    {
                        Message = $"Cant update Product when category and manufacturer is not assign."
                    }));
                }
                if (updateModel.ProductImages == null || updateModel.ProductImages.Length <= 0)
                {
                    return(BadRequest(new { Message = "Cant update product with 0 image" }));
                }

                var oldPrice = item.Price;
                var raiseProductPriceChangedEvent = oldPrice != updateModel.Price;

                updateModel.Id = id;

                #region Clean all Images and colors

                _catalogContext.ProductImages.RemoveRange(item.ProductImages);
                _catalogContext.ProductColors.RemoveRange(item.ProductColors);

                // Delete Previous Images
                foreach (var image in item.ProductImages)
                {
                    _fileUtility.DeleteFile("ProductImage/" + id, image.ImageName);
                }

                // Insert new images
                foreach (var image in updateModel.ProductImages)
                {
                    await InsertProductImageAsync(updateModel, cancellationToken, image);
                }

                await _catalogContext.SaveChangesAsync(cancellationToken);

                #endregion

                #region Mapping
                // Update current product
                item.Description    = updateModel.Description;
                item.LastUpdatedBy  = updateModel.ActorId;
                item.LastUpdated    = DateTime.Now;
                item.Name           = updateModel.Name;
                item.CategoryId     = updateModel.CategoryId;
                item.ManufacturerId = updateModel.ManufacturerId;
                item.Price          = updateModel.Price;
                item.ProductImages  = updateModel.ProductImages.Select(x =>
                                                                       new ProductImage {
                    ImageName = x.ImageName, ImageUrl = x.ImageUrl, ProductId = x.ProductId
                })
                                      .ToList();
                item.ProductColors = updateModel.ProductColors
                                     .Select(x => new ProductColor {
                    Name = x.Name, ProductId = x.ProductId
                }).ToList();

                #endregion

                // Update current product
                _catalogContext.Products.Update(item);


                if (raiseProductPriceChangedEvent) // Save product's data and publish integration event through the Event Bus if price has changed
                {
                    //Create Integration Event to be published through the Event Bus
                    var priceChangedEvent = new ProductPriceChangedIntegrationEvent(item.Id, updateModel.Price, oldPrice);

                    // Achieving atomicity between original Catalog database operation and the IntegrationEventLog thanks to a local transaction
                    await _catalogIntegrationEventService.SaveEventAndCatalogContextChangesAsync(0, "PriceChanged", priceChangedEvent);

                    // Publish through the Event Bus and mark the saved event as published
                    await _catalogIntegrationEventService.PublishThroughEventBusAsync(priceChangedEvent);
                }
                else // Just save the updated product because the Product's Price hasn't changed.
                {
                    await _catalogContext.SaveChangesAsync(cancellationToken);
                }

                return(CreatedAtAction(nameof(UpdateProductAsync), new
                {
                    id = item.Id
                }, null));
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }