public OperationResult SavePayment(PatientLoginInfo patientLoginInfo, PaymentCreationParameters paymentCreationParameters, int?managementUserId)
        {
            if (patientLoginInfo == null)
            {
                throw new ArgumentNullException(nameof(patientLoginInfo));
            }
            if (paymentCreationParameters == null)
            {
                throw new ArgumentNullException(nameof(paymentCreationParameters));
            }
            ValidatePaymentCreationParameters(paymentCreationParameters);

            try
            {
                //save payment data locally
                var paymentDb = PaymentRepository.Create();
                Mapper.ToPayment(paymentCreationParameters, paymentDb);
                paymentDb.Active           = true;
                paymentDb.LoginId          = patientLoginInfo.ID;
                paymentDb.ManagementUserId = managementUserId;
                PaymentRepository.Insert(paymentDb);

                //create the customer in stripe
                var r = PaymentGateway.Customer(patientLoginInfo.ID, patientLoginInfo.FirstName + " " + patientLoginInfo.LastName, patientLoginInfo.Email);
                if (r["error"] != null)
                {
                    throw new Exception(r.error.message.ToString());
                }

                //create the card in stripe
                var c = PaymentGateway.CreateCard(patientLoginInfo.ID, paymentCreationParameters.CardHolder, paymentCreationParameters.CardNumber, paymentCreationParameters.CardExpiryMonth, paymentCreationParameters.CardExpiryYear, paymentCreationParameters.CardSecurityCode);
                if (c["error"] != null)
                {
                    throw new Exception(r.error.message.ToString());
                }

                //save cc data locally
                var card = CreditCardRepository.Create();
                Mapper.ToCreditCard(paymentCreationParameters, card);
                card.LoginId       = patientLoginInfo.ID;
                card.GatewayType   = PaymentGateway.GetId();
                card.GatewayCardId = c["id"];
                card.CardType      = c["brand"];
                CreditCardRepository.Insert(card);

                //update payment with cc data
                paymentDb.CreditCardId = card.Id;
                PaymentRepository.Save(paymentDb);

                if (paymentCreationParameters.PaymentType == PaymentType.recurring)
                {
                    //create instance of a recurring payment
                    var start = paymentCreationParameters.RecurringDateStart.Value;
                    var end   = paymentCreationParameters.RecurringDateEnd.Value;
                    var dates = DatesGenerator.GetDates(start, end, paymentCreationParameters.RecurringFrequency.Value).Select((m, i) => new { date = m, index = i });
                    if (dates.Count() == 0)
                    {
                        throw new InvalidOperationException("No payments to schedule.");
                    }
                    var schedules = new List <PaymentSchedule>();
                    foreach (var d in dates)
                    {
                        var schedule = PaymentScheduleRepository.Create();
                        schedule.PaymentId      = paymentDb.Id;
                        schedule.ScheduledDate  = d.date;
                        schedule.ScheduleNumber = d.index + 1;
                        schedules.Add(schedule);
                    }
                    PaymentScheduleRepository.Insert(schedules);
                }
                else
                {
                    if (paymentCreationParameters.OneTimePaymentDate.Value.Date == DateTime.Today)
                    {
                        //charge to cc since this is a onetime payment scheduled for today
                        var chargeParameters = new PaymentChargeParameters
                        {
                            Description   = "One Time Charge -  Payment Id " + paymentDb.Id.ToString("D5"),
                            Amount        = paymentCreationParameters.Amount,
                            CustomerId    = patientLoginInfo.ID,
                            GatewayCardId = card.GatewayCardId,
                            PaymentId     = paymentDb.Id,
                            CardId        = card.Id,
                            ReferenceType = "Payment",
                            ReferenceId   = paymentDb.Id
                        };
                        return(Charge(chargeParameters));
                    }
                    else
                    {
                        var schedule = PaymentScheduleRepository.Create();
                        schedule.PaymentId      = paymentDb.Id;
                        schedule.ScheduledDate  = paymentCreationParameters.OneTimePaymentDate.Value.Date;
                        schedule.ScheduleNumber = 1;
                        PaymentScheduleRepository.Insert(schedule);
                    }
                }
            }
            catch (Exception e)
            {
                return(new OperationResult {
                    Success = false, Message = e.Message
                });
            }
            return(new OperationResult {
                Success = true
            });
        }