public async Task ProcessUpdateItemEventAsync(EventGridEvent eventToProcess, string userId)
        {
            // process the item type
            var(updatedItem, _, operationType) = ConvertEventGridEventToCategoryItem(eventToProcess);
            if (operationType != OperationType.Update)
            {
                return;
            }

            // find the category document
            var categoryDocument = await CategoriesRepository.FindCategoryWithItemAsync(updatedItem.Id, updatedItem.Type, userId);

            if (categoryDocument == null)
            {
                return;
            }

            // find the item in the document
            var existingItem = categoryDocument.Items.SingleOrDefault(i => i.Id == updatedItem.Id);

            if (existingItem == null)
            {
                return;
            }

            // update the item with the latest changes
            // (the only field that can change is Preview)
            existingItem.Preview = updatedItem.Preview;
            await CategoriesRepository.UpdateCategoryAsync(categoryDocument);

            // post a CategoryItemsUpdated event to Event Grid
            var eventData = new CategoryItemsUpdatedEventData();
            var subject   = $"{userId}/{categoryDocument.Id}";
            await EventGridPublisher.PostEventGridEventAsync(EventTypes.Categories.CategoryItemsUpdated, subject, eventData);
        }
        public async Task ProcessDeleteItemEventAsync(EventGridEvent eventToProcess, string userId)
        {
            // process the item type
            var(updatedItem, _, operationType) = ConvertEventGridEventToCategoryItem(eventToProcess);
            if (operationType != OperationType.Delete)
            {
                return;
            }

            // find the category document
            var categoryDocument = await CategoriesRepository.FindCategoryWithItemAsync(updatedItem.Id, updatedItem.Type, userId);

            if (categoryDocument == null)
            {
                return;
            }

            // find the item in the document
            var itemToRemove = categoryDocument.Items.SingleOrDefault(i => i.Id == updatedItem.Id);

            if (itemToRemove == null)
            {
                return;
            }

            // remove the item from the document
            categoryDocument.Items.Remove(itemToRemove);
            await CategoriesRepository.UpdateCategoryAsync(categoryDocument);

            // post a CategoryItemsUpdated event to Event Grid
            var eventData = new CategoryItemsUpdatedEventData();
            var subject   = $"{userId}/{categoryDocument.Id}";
            await EventGridPublisher.PostEventGridEventAsync(EventTypes.Categories.CategoryItemsUpdated, subject, eventData);
        }
        public async Task ProcessAddItemEventAsync(EventGridEvent eventToProcess, string userId)
        {
            // process the item type
            var(item, categoryId, operationType) = ConvertEventGridEventToCategoryItem(eventToProcess);
            if (operationType != OperationType.Add)
            {
                return;
            }

            // find the category document
            var categoryDocument = await CategoriesRepository.GetCategoryAsync(categoryId, userId);

            if (categoryDocument == null)
            {
                return;
            }

            // update the document with the new item
            // and if the item already exists in this category, replace it
            var existingItem = categoryDocument.Items.SingleOrDefault(i => i.Id == item.Id);

            if (existingItem != null)
            {
                categoryDocument.Items.Remove(existingItem);
            }
            categoryDocument.Items.Add(item);
            await CategoriesRepository.UpdateCategoryAsync(categoryDocument);

            // post a CategoryItemsUpdated event to Event Grid
            var eventData = new CategoryItemsUpdatedEventData();
            var subject   = $"{userId}/{categoryDocument.Id}";
            await EventGridPublisher.PostEventGridEventAsync(EventTypes.Categories.CategoryItemsUpdated, subject, eventData);
        }