public async Task <IActionResult> RepeatAppointment(
            [Bind]
            RepeatAppViewModel model)
        {
            if (model.PeriodType == RepeatTime.Unselect || model.PeriodType == RepeatTime.Never)
            {
                ModelState.AddModelError("", "Select the repetition type");
            }
            if (model.RepeatNumber == 0)
            {
                ModelState.AddModelError("", "You must repeat the appointment at least once");
            }
            if (model.PeriodType == RepeatTime.Once && model.TargetDay == null ||
                model.PeriodType == RepeatTime.Once && model.TargetDay < DateTime.Today)
            {
                ModelState.AddModelError("", "Date is not valid");
            }

            if (ModelState.IsValid)
            {
                Appointment app = await appointmentRopository.Appointments.FirstOrDefaultAsync(a => a.Id == model.Id);

                app.RoomCode = model.Code;

                var toCompareTime = await appointmentRopository.Appointments
                                    .Where(a =>
                                           a.Start.Date > app.Start.Date &&
                                           a.RoomId == app.RoomId ||
                                           a.Id == app.Id)
                                    .ToDictionaryAsync(a => a.Id);

                var appointments = await RepeatAppointment(app, model, toCompareTime);

                if (appointments.Any(a => a.ErrorHappened))
                {
                    ModelState.Clear();
                    ModelState.AddModelError("", $"An error occurred while processing the request, " +
                                             $"it is possible that the appointments were not created, " +
                                             $"please make sure and then try again");
                    return(View(model));
                }

                HttpContext.Session.SetJson("repeatResult", appointments);

                return(RedirectToAction("ReportAppointments", nameof(Appointment), new { date = model.Date }));
            }

            return(View(model));
        }
        public async Task <Appointment> AddDuplicate(Appointment newAppointment, RepeatAppViewModel model, int amount, Dictionary <int, Appointment> compareTo)
        {
            switch (model.PeriodType)
            {
            case RepeatTime.Once:

                //var appointmentDuration = newAppointment.End - newAppointment.Start;
                newAppointment.Start = model.TargetDay.Value.Date + model.Start.Value;
                newAppointment.End   = model.TargetDay.Value.Date + model.End.Value;
                break;

            case RepeatTime.Daily:
                newAppointment.Start += amount.Days();
                newAppointment.End   += amount.Days();
                break;

            case RepeatTime.Weekly:
                newAppointment.Start += amount.Weeks();
                newAppointment.End   += amount.Weeks();
                break;

            case RepeatTime.Monthly:
                newAppointment.Start += amount.Months();
                newAppointment.End   += amount.Months();
                break;

            case RepeatTime.Never:
                break;

            default:
                break;
            }

            newAppointment.IsValid = await ValidateAppointmentAsync(newAppointment, compareTo);

            return(newAppointment);
        }
        public async Task <IEnumerable <Appointment> > RepeatAppointment(Appointment original, RepeatAppViewModel model, Dictionary <int, Appointment> compareTo)
        {
            var tasks = new List <Task <Appointment> >();
            int count = 1;

            while (tasks.Count < model.RepeatNumber)
            {
                if (!model.IncludeWeekends)
                {
                    var tempDate = original.Start + count.Days();

                    if (tempDate.DayOfWeek == DayOfWeek.Saturday)
                    {
                        count += 2;
                        continue;
                    }
                    else if (tempDate.DayOfWeek == DayOfWeek.Sunday)
                    {
                        count++;
                        continue;
                    }
                }

                tasks.Add(AddDuplicate(original.Clone(), model, count++, compareTo));
            }

            var appointments = await Task.WhenAll(tasks);


            try
            {
                await appointmentRopository.SaveRangeAsync(appointments.Where(a => a.IsValid == true));
            }
            catch (DbUpdateException ex)
            {
                Parallel.ForEach(appointments.Where(a => a.IsValid && a.Id == 0), a => a.ErrorHappened = true);
            }

            return(appointments);
        }