using Marco.Pms.Model.AppMenu; using Marco.Pms.Model.Dtos.AppMenu; using Marco.Pms.Model.ViewModels.AppMenu; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using MongoDB.Bson; using MongoDB.Driver; using System; using System.Collections.Generic; using System.Threading.Tasks; using static System.Collections.Specialized.BitVector32; namespace Marco.Pms.CacheHelper { public class SideBarMenu { private readonly IMongoCollection _collection; private readonly ILogger _logger; public SideBarMenu(IConfiguration configuration, ILogger logger) { _logger = logger; var connectionString = configuration["MongoDB:ConnectionMenu"]; var mongoUrl = new MongoUrl(connectionString); var client = new MongoClient(mongoUrl); var database = client.GetDatabase(mongoUrl.DatabaseName); _collection = database.GetCollection("Menus"); } public async Task CreateMenuSectionAsync(MenuSection section) { try { await _collection.InsertOneAsync(section); return section; } catch (Exception ex) { _logger.LogError(ex, "Error occurred while adding MenuSection."); return null; } } public async Task UpdateMenuSectionAsync(Guid sectionId, MenuSection updatedSection) { try { var filter = Builders.Filter.Eq(s => s.Id, sectionId); var update = Builders.Update .Set(s => s.Header, updatedSection.Header) .Set(s => s.Title, updatedSection.Title) .Set(s => s.Items, updatedSection.Items); var result = await _collection.UpdateOneAsync(filter, update); if (result.ModifiedCount > 0) { return await _collection.Find(s => s.Id == sectionId).FirstOrDefaultAsync(); } return null; } catch (Exception ex) { _logger.LogError(ex, "Error updating MenuSection."); return null; } } public async Task AddMenuItemAsync(Guid sectionId, MenuItem newItem) { try { newItem.Id = Guid.NewGuid(); var filter = Builders.Filter.Eq(s => s.Id, sectionId); var update = Builders.Update.Push(s => s.Items, newItem); var result = await _collection.UpdateOneAsync(filter, update); if (result.ModifiedCount > 0) { return await _collection.Find(s => s.Id == sectionId).FirstOrDefaultAsync(); } return null; } catch (Exception ex) { _logger.LogError(ex, "Error adding menu item."); return null; } } public async Task UpdateMenuItemAsync(Guid sectionId, Guid itemId, MenuItem updatedItem) { try { var filter = Builders.Filter.And( Builders.Filter.Eq(s => s.Id, sectionId), Builders.Filter.ElemMatch(s => s.Items, i => i.Id == itemId) ); var update = Builders.Update .Set("Items.$.Text", updatedItem.Text) .Set("Items.$.Icon", updatedItem.Icon) .Set("Items.$.Available", updatedItem.Available) .Set("Items.$.Link", updatedItem.Link) .Set("Items.$.PermissionKeys", updatedItem.PermissionKeys); // <-- updated var result = await _collection.UpdateOneAsync(filter, update); if (result.ModifiedCount > 0) { // Re-fetch section and return the updated item var section = await _collection.Find(s => s.Id == sectionId).FirstOrDefaultAsync(); return section?.Items.FirstOrDefault(i => i.Id == itemId); } return null; } catch (Exception ex) { _logger.LogError(ex, "Error updating MenuItem."); return null; } } public async Task AddSubMenuItemAsync(Guid sectionId, Guid itemId, SubMenuItem newSubItem) { try { newSubItem.Id = Guid.NewGuid(); // Match the MenuSection and the specific MenuItem inside it var filter = Builders.Filter.And( Builders.Filter.Eq(s => s.Id, sectionId), Builders.Filter.ElemMatch(s => s.Items, i => i.Id == itemId) ); // Use positional operator `$` to target matched MenuItem and push into its Submenu var update = Builders.Update.Push("Items.$.Submenu", newSubItem); var result = await _collection.UpdateOneAsync(filter, update); if (result.ModifiedCount > 0) { return await _collection.Find(s => s.Id == sectionId).FirstOrDefaultAsync(); } return null; } catch (Exception ex) { _logger.LogError(ex, "Error adding submenu item."); return null; } } public async Task UpdateSubmenuItemAsync(Guid sectionId, Guid itemId, Guid subItemId, SubMenuItem updatedSub) { try { var filter = Builders.Filter.Eq(s => s.Id, sectionId); var arrayFilters = new List { new BsonDocumentArrayFilterDefinition( new BsonDocument("item._id", itemId.ToString())), new BsonDocumentArrayFilterDefinition( new BsonDocument("sub._id", subItemId.ToString())) }; var update = Builders.Update .Set("Items.$[item].Submenu.$[sub].Text", updatedSub.Text) .Set("Items.$[item].Submenu.$[sub].Available", updatedSub.Available) .Set("Items.$[item].Submenu.$[sub].Link", updatedSub.Link) .Set("Items.$[item].Submenu.$[sub].PermissionKeys", updatedSub.PermissionKeys); // <-- updated var options = new UpdateOptions { ArrayFilters = arrayFilters }; var result = await _collection.UpdateOneAsync(filter, update, options); if (result.ModifiedCount == 0) return null; var updatedSection = await _collection.Find(x => x.Id == sectionId).FirstOrDefaultAsync(); var subItem = updatedSection?.Items .FirstOrDefault(i => i.Id == itemId)? .Submenu .FirstOrDefault(s => s.Id == subItemId); return subItem; } catch (Exception ex) { _logger.LogError(ex, "Error updating SubMenuItem."); return null; } } public async Task> GetAllMenuSectionsAsync() { return await _collection.Find(_ => true).ToListAsync(); } } }