public async Task <IActionResult> Edit(int id, [Bind("ID,SurgeryStartingTime,SurgeryEndingTime,SurgeryRoomId,PatientFullName,PatientDateOfBirth,PatientGender,PatientMRNnumber,SurgeryName,SurgerySite,SurgicalDepartmentId,SurgeonID,BloodRequested,RequestedPostOperativeCare,SurgeryPosition,FrozenSection,SpecialThingsLikeSutures,SpecialThingsLikeSuturesText,Consumables,AnesthesiaTechniqueId,SpecialDevices,Turniquet,CArm,Harmonic,Ligasure,Microscope,Others,AppointmentStatus,PatientStatus,BookedItemsList,BloodRequestedText,ConsumablesText,SpecialDevicesText,SurgeryPositionText,AnestheticsId")] CreateBookingViewModel booking)
        {
            if (id != booking.ID)
            {
                return(NotFound());
            }

            if (ModelState.IsValid)
            {
                try
                {
                    var itemsBooked = booking.BookedItemsList?.Split(',').Where(x => int.TryParse(x, out _))
                                      .Select(int.Parse)
                                      .ToList();


                    booking.ItemsBooked = _context.ItemsBooked.Where(x => x.BookingId == booking.ID).Include(x => x.Item).ToList();

                    //delete extra items in itemsbooked
                    List <ItemsBooked> collection = new List <ItemsBooked>();
                    if (booking.ItemsBooked.Any())
                    {
                        if (itemsBooked != null)
                        {
                            collection = booking.ItemsBooked
                                         .Where(x => itemsBooked.All(c => c != x.ItemId)).ToList();
                        }
                        else
                        {
                            collection = booking.ItemsBooked;
                        }
                        if (collection.Any())
                        {
                            _context.ItemsBooked.RemoveRange(collection);
                        }
                    }

                    //add new items
                    if (itemsBooked != null)
                    {
                        foreach (var i in itemsBooked)
                        {
                            var booked = new ItemsBooked()
                            {
                                Booking  = booking,
                                Item     = _context.Item.FirstOrDefault(x => x.Id == i),
                                Quantity = 1
                            };
                            if (booking.ItemsBooked.All(x => x.ItemId != booked.Item.Id))
                            {
                                booking.ItemsBooked.Add(booked);
                            }
                        }
                    }

                    var bookingId       = booking.ID;
                    var overlapBookings = _bookingRepository.GetAllBookings().Where(x =>
                                                                                    x.SurgeryStartingTime <booking.SurgeryEndingTime &&
                                                                                                           x.SurgeryEndingTime> booking.SurgeryStartingTime && x.ID != bookingId).ToList();

                    if (User.IsInRole("StatusUpdate") && booking.AnestheticsId == null)
                    {
                        ModelState.AddModelError("AnestheticsId", $"Anesthetics is required.");
                    }

                    var overLapRoom = overlapBookings.FirstOrDefault(x => x.SurgeryRoomId == booking.SurgeryRoomId);
                    if (overLapRoom != null)
                    {
                        ModelState.AddModelError("SurgeryRoomId", $"Room {overLapRoom.SurgeryRoom.SurgeryRoomDescription} booked in this hour since someone booked it just now. Please select other time or room.");
                    }

                    var totalItems = _context.Item.AsNoTracking().ToList();

                    foreach (var i in totalItems.Where(i => overlapBookings.Any(x => x.ItemsBooked.Any(c => c.Item.Id == i.Id))))
                    {
                        i.Quantity--;
                    }

                    foreach (var i in totalItems.Where(x => booking.ItemsBooked.Any(c => c.Item.Id == x.Id && x.Quantity < 1)))
                    {
                        ModelState.AddModelError("", $"'{i.Description}' is not available in this time since someone booked it just now. Please select other time.");
                    }

                    if (ModelState.ErrorCount == 0)
                    {
                        _bookingRepository.Update(booking);
                    }
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!BookingExists(booking.ID))
                    {
                        return(NotFound());
                    }
                    else
                    {
                        throw;
                    }
                }
                if (ModelState.ErrorCount == 0)
                {
                    return(RedirectToAction(nameof(Index)));
                }
            }
            ViewData["Rooms"] = JsonConvert.SerializeObject(_context.SurgeryRoom.OrderBy(x => x.SurgeryRoomDescription).Select(x => new
            {
                id          = x.Id,
                description = x.SurgeryRoomDescription.Trim()
            }));
            var items     = _context.Item.ToArray();
            var listItems = items.Select(i => new { id = i.Id, description = i.Description }).Distinct().OrderBy(x => x.description);

            ViewData["Item"] = JsonConvert.SerializeObject(listItems);

            ViewData["AnesthesiaTechniqueId"] = new SelectList(_context.AnesthesiaTechnique, "Id", "Text", booking.AnesthesiaTechniqueId);
            ViewData["SurgeryRoomId"]         = new SelectList(_context.SurgeryRoom, "Id", "SurgeryRoomDescription", booking.SurgeryRoomId);
            ViewData["SurgicalDepartmentId"]  = new SelectList(_context.Set <SurgicalDepartment>(), "Id", "SurgicalDepartmentDescription", booking.SurgicalDepartmentId);
            ViewData["Anesthetics"]           = new SelectList(_context.Anesthetics, "Id", "Name", booking.AnestheticsId);
            var allBookings = _bookingRepository.GetAllBookings();

            ViewData["Appointments"] = JsonConvert.SerializeObject(allBookings.Where(x => x.ID != id).Select(x => new
            {
                startTime   = x.SurgeryStartingTime,
                endTime     = x.SurgeryEndingTime,
                roomId      = x.SurgeryRoomId,
                itemsBooked = x.ItemsBooked?.Where(p => p.Quantity > 0)
                              .SelectMany(p => Enumerable.Range(0, p.Quantity)
                                          .Select(i => new
                {
                    itemId   = p.ItemId,
                    quantity = p.Quantity
                }))
            }));


            ViewData["bookedItems"] = JsonConvert.SerializeObject(booking.ItemsBooked.Select(x => x.Item.Id).ToArray());
            var userModel = new List <UserRoleViewModel>();

            foreach (var user in _userManager.Users)
            {
                if (await _userManager.IsInRoleAsync(user, "Surgeon"))
                {
                    var userRoleViewModel = new UserRoleViewModel
                    {
                        UserID   = user.Id,
                        UserName = user.UserName,
                    };
                    userModel.Add(userRoleViewModel);
                }
            }

            ViewData["SurgeonId"] = new SelectList(userModel, "UserID", "UserName", booking.SurgeonID);

            var originalBooking = _bookingRepository.GetBooking((int)id);

            booking.CreatedBy  = originalBooking.CreatedBy;
            booking.ModifiedBy = originalBooking.ModifiedBy;


            return(View(booking));
        }
        public async Task <IActionResult> Create([Bind("ID,SurgeryStartingTime,SurgeryEndingTime,SurgeryRoomId,PatientFullName,PatientDateOfBirth,PatientGender,PatientMRNnumber,SurgeryName,SurgerySite,SurgicalDepartmentId,SurgeonID,BloodRequested,RequestedPostOperativeCare,SurgeryPosition,FrozenSection,SpecialThingsLikeSutures,SpecialThingsLikeSuturesText,Consumables,AnesthesiaTechniqueId,SpecialDevices,Turniquet,CArm,Harmonic,Ligasure,Microscope,Others,BookedItemsList,AppointmentStatus,BloodRequestedText,ConsumablesText,SpecialDevicesText,SurgeryPositionText")] CreateBookingViewModel booking)
        {
            if (ModelState.IsValid)
            {
                var itemsBooked = booking.BookedItemsList?.Split(',');
                booking.ItemsBooked = new List <ItemsBooked>();

                if (itemsBooked != null)
                {
                    foreach (var i in itemsBooked)
                    {
                        var booked = new ItemsBooked()
                        {
                            Booking  = booking,
                            Item     = _context.Item.FirstOrDefault(x => x.Id == int.Parse(i)),
                            Quantity = 1
                        };
                        booking.ItemsBooked.Add(booked);
                    }
                }

                var overlapBookings = _bookingRepository.GetAllBookings().Where(x =>
                                                                                x.SurgeryStartingTime <booking.SurgeryEndingTime &&
                                                                                                       x.SurgeryEndingTime> booking.SurgeryStartingTime).ToList();

                var overLapRoom = overlapBookings.FirstOrDefault(x => x.SurgeryRoomId == booking.SurgeryRoomId);
                if (overLapRoom != null)
                {
                    ModelState.AddModelError("SurgeryRoomId", $"Room {overLapRoom.SurgeryRoom.SurgeryRoomDescription} booked in this hour since someone booked it just now. Please select other time or room.");
                }

                var totalItems = _context.Item.AsNoTracking().ToList();

                foreach (var i in totalItems.Where(i => overlapBookings.Any(x => x.ItemsBooked.Any(c => c.Item.Id == i.Id))))
                {
                    i.Quantity--;
                }

                foreach (var i in totalItems.Where(x => booking.ItemsBooked.Any(c => c.Item.Id == x.Id && x.Quantity < 1)))
                {
                    ModelState.AddModelError("", $"'{i.Description}' is not available in this time since someone booked it just now. Please select other time.");
                }

                if (ModelState.ErrorCount == 0)
                {
                    _bookingRepository.Add(booking);
                    await _context.SaveChangesAsync();

                    return(RedirectToAction(nameof(Index)));
                }
            }

            ViewData["AnesthesiaTechniqueId"] = new SelectList(_context.AnesthesiaTechnique, "Id", "Text", booking.AnesthesiaTechniqueId);
            ViewData["Rooms"] = JsonConvert.SerializeObject(_context.SurgeryRoom.OrderBy(x => x.SurgeryRoomDescription).Select(x => new
            {
                id          = x.Id,
                description = x.SurgeryRoomDescription.Trim()
            }));
            ViewData["Appointments"] = JsonConvert.SerializeObject(_bookingRepository.GetAllBookings().Select(x => new
            {
                startTime   = x.SurgeryStartingTime,
                endTime     = x.SurgeryEndingTime,
                roomId      = x.SurgeryRoomId,
                itemsBooked = x.ItemsBooked?.Where(p => p.Quantity > 0)
                              .SelectMany(p => Enumerable.Range(0, p.Quantity)
                                          .Select(i => new
                {
                    itemId   = p.ItemId,
                    quantity = p.Quantity
                }))
            }));


            ViewData["SurgicalDepartmentId"] = new SelectList(_context.SurgicalDepartment, "Id", "SurgicalDepartmentDescription", booking.SurgicalDepartmentId);

            var items     = _context.Item.AsNoTracking().ToArray();
            var listItems = items.Select(i => new { id = i.Id, description = i.Description }).Distinct().OrderBy(x => x.description);

            ViewData["Item"] = JsonConvert.SerializeObject(listItems);

            var userModel = new List <UserRoleViewModel>();

            foreach (var user in _userManager.Users)
            {
                if (await _userManager.IsInRoleAsync(user, "Surgeon"))
                {
                    var userRoleViewModel = new UserRoleViewModel
                    {
                        UserID   = user.Id,
                        UserName = user.DisplayName,
                    };
                    userModel.Add(userRoleViewModel);
                }
            }

            ViewData["CurrentUserName"] = (await _userManager.FindByIdAsync(_userManager.GetUserId(User)).ConfigureAwait(false)).DisplayName;
            ViewData["SurgeonId"]       = new SelectList(userModel, "UserID", "UserName", booking.SurgeonID);


            return(View(booking));
        }