context: using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Web.Mvc;
  using System.Web.WebPages;
  using CmsData;
  using CmsData.Codes;
  using CmsData.Finance;
  using CMSShared.SharedUtil;
  using CmsWeb.Areas.Manage.Models;
  using CmsWeb.Areas.OnlineReg.Models;
  using CmsWeb.Code;
  using CmsWeb.Membership;
  using CmsWeb.Models;
  using Elmah;
  using UtilityExtensions;
  
  namespace CmsWeb.Areas.OnlineReg.Controllers
  {
      public partial class OnlineRegController
      {
          [HttpGet]
          [Route("~/OnePageGiving/{id:int}")]
          public ActionResult OnePageGiving(int id, bool? testing, string source)
          {
              Response.NoCache();
              try
              {
                  var m = new OnlineRegModel(Request, CurrentDatabase, id, testing, null, null, source);
  
                  string redirectLink = m.org?.RedirectUrl ?? m.masterorg?.RedirectUrl;
                  if (redirectLink.IsEmpty() && CurrentDatabase.Setting("UseGivingPages"))
                  {
                      if (CurrentDatabase.CurrentUserPerson?.CampusId.HasValue == true)
                      {
                          var givingPage = (from g in CurrentDatabase.GivingPages where g.CampusId == CurrentDatabase.CurrentUserPerson.CampusId && g.MainCampusPageFlag == true select g).FirstOrDefault();
                          if (givingPage.IsNull())
                          {
                              var defaultGivingPage = (from g in CurrentDatabase.GivingPages where g.DefaultPage == true select g).FirstOrDefault();
                              redirectLink = "/Give/" + defaultGivingPage.PageUrl;
                              redirectLink += SharedUtil.GivingTypeRedirectLink(oneTimeGiving: true);
                              return Redirect(redirectLink);
                          }
                          else
                          {
                              redirectLink = "/Give/" + givingPage.PageUrl;
                              redirectLink += SharedUtil.GivingTypeRedirectLink(oneTimeGiving: true);
                              return Redirect(redirectLink);
                          }
                      }
                      else
                      {
                          var givingPage = (from g in CurrentDatabase.GivingPages where g.DefaultPage == true select g).FirstOrDefault();
                          redirectLink = "/Give/" + givingPage.PageUrl;
                          redirectLink += SharedUtil.GivingTypeRedirectLink(oneTimeGiving: true);
                      }
                  }
  
                  if (redirectLink.HasValue())
                  {
                      return Redirect(redirectLink);
                  }
  
                  if (!m.org.IsOnePageOnlineGiving(CurrentDatabase))
                  {
                      return Redirect($"/OnlineReg/{id}{Request.Url.Query}");
                  }
  
                  var pid = CurrentDatabase.UserPeopleId;
                  if (pid.HasValue)
                      PrePopulate(m, pid.Value);
  
                  SetHeaders(m);
                  m.CheckRegisterLink(null);
  
                  if (m.NotActive())
                  {
                      return View("OnePageGiving/NotActive", m);
                  }
  
                  if ((m.org.IsMissionTrip.IsNotNull() && m.org.IsMissionTrip == true) ? true : false)
                  {
                      m.ProcessType = PaymentProcessTypes.OneTimeGiving;
                  }
                  else
                  {
                      m.ProcessType = (m.org.RegistrationTypeId.IsNull() || m.org.RegistrationTypeId == RegistrationTypeCode.OnlineGiving)
                          ? PaymentProcessTypes.OneTimeGiving
                          : PaymentProcessTypes.OnlineRegistration;
                  }
  
                  int? GatewayId = MultipleGatewayUtils.GatewayId(CurrentDatabase, m.ProcessType);
  
                  if (GatewayId == (int)GatewayTypes.Pushpay && m.OnlineGiving())
                  {
                      ViewBag.Header = "One Page Giving";                    
                      if (string.IsNullOrEmpty(MultipleGatewayUtils.Setting(CurrentDatabase, "PushpayMerchant", "", (int)m.ProcessType)))
                          return View("OnePageGiving/NotConfigured");
  
                      return Redirect($"/Pushpay/OnePage/{id}");
                  }
  
                  var pf = PaymentForm.CreatePaymentForm(m);
                  pf.AmtToPay = null;
  
                  if (string.IsNullOrWhiteSpace(pf.Type))
                  {
                      pf.Type = pf.AcceptCredit ? PaymentType.CreditCard : PaymentType.Ach;
                  }
  
                  var p = m.List[0];
                  if (pf.ShowCampusOnePageGiving)
                      pf.Campuses = p.Campuses().ToList();
  
                  var designatedFund = p.DesignatedDonationFund().FirstOrDefault();
                  pf.Description = designatedFund != null ? designatedFund.Text : m.DescriptionForPayment;
  
                  SetInstructions(m);
  
                  return View("OnePageGiving/Index", new OnePageGivingModel() { OnlineRegPersonModel = m.List[0], PaymentForm = pf });
              }
              catch (Exception ex)
              {
                  if (ex is BadRegistrationException)
                      return Message(ex.Message);
                  throw;
              }
          }
  
          private void PrePopulate(OnlineRegModel m, int pid)
          {
              m.UserPeopleId = pid;
              var p = m.LoadExistingPerson(pid, 0);
              m.List[0] = p;
          }
  
          private void SetInstructions(OnlineRegModel m)
          {
              var s = m.SubmitInstructions();
              ViewBag.Instructions = s.HasValue() ? s : $"<h4>{m.Header}</h4>";
          }
  
  
          [HttpPost, Route("~/OnePageGiving")]
          public ActionResult OnePageGiving(PaymentForm pf, Dictionary<int, decimal?> fundItem)
          {
              // need save off the original amt to pay if there is an error later on.
              var amtToPay = pf.AmtToPay;
  
              var id = pf.OrgId;
              if (id == null)
                  return Message("Missing OrgId");
  
              if (!Util.ValidEmail(pf.Email))
                  ModelState.AddModelError("Email", "Need a valid email address");
              if (pf.IsUs && !pf.Zip.HasValue())
                  ModelState.AddModelError("Zip", "Zip is Required for US");
              if (pf.ShowCampusOnePageGiving)
                  if ((pf.CampusId ?? 0) == 0)
                      ModelState.AddModelError("CampusId", "Campus is Required");
  
              var m = new OnlineRegModel(Request, CurrentDatabase, pf.OrgId, pf.testing, null, null, pf.source)
              {
                  URL = $"/OnePageGiving/{pf.OrgId}"
              };
  
              m.ProcessType = pf.ProcessType;
  
              var pid = CurrentDatabase.UserPeopleId;
              if (pid.HasValue)
                  PrePopulate(m, pid.Value);
  
              // we need to always retrieve the entire list of funds for one page giving calculations.
              m.List[0].RetrieveEntireFundList = true;
  
              // first re-build list of fund items with only ones that contain a value (amt).
              var fundItems = fundItem.Where(f => f.Value.GetValueOrDefault() > 0).ToDictionary(f => f.Key, f => f.Value);
  
              var designatedFund = m.settings[id.Value].DonationFundId ?? 0;
              if (designatedFund != 0)
                  fundItems.Add(designatedFund, pf.AmtToPay);
  
              // set the fund items on online reg person if there are any.
              if (fundItems.Any())
              {
                  m.List[0].FundItem = fundItems;
                  pf.AmtToPay = m.List[0].FundItemsChosen().Sum(f => f.Amt);
              }
  
              if (pf.AmtToPay.GetValueOrDefault() == 0)
                  ModelState.AddModelError("AmtToPay", "Invalid Amount");
  
              SetHeaders(m);
              SetInstructions(m);
  
              var p = m.List[0];
              if (pf.ShowCampusOnePageGiving)
                  pf.Campuses = p.Campuses().ToList();
  
              if (!ModelState.IsValid)
              {
                  m.List[0].FundItem = fundItem;
                  pf.AmtToPay = amtToPay;
                  return View("OnePageGiving/Index", new OnePageGivingModel() { OnlineRegPersonModel = m.List[0], PaymentForm = pf });
              }
  
              if (CheckAddress(pf) == false)
              {
                  m.List[0].FundItem = fundItem;
                  pf.AmtToPay = amtToPay;
                  return View("OnePageGiving/Index", new OnePageGivingModel() { OnlineRegPersonModel = m.List[0], PaymentForm = pf });
              }
  
  
              if (!ModelState.IsValid)
              {
                  m.List[0].FundItem = fundItem;
                  pf.AmtToPay = amtToPay;
                  return View("OnePageGiving/Index", new OnePageGivingModel() { OnlineRegPersonModel = m.List[0], PaymentForm = pf });
              }
  
              p.orgid = m.Orgid;
              p.FirstName = pf.First;
              p.LastName = pf.Last;
              p.EmailAddress = pf.Email;
              p.Phone = pf.Phone;
              p.AddressLineOne = pf.Address;
              p.City = pf.City;
              p.State = pf.State;
              p.ZipCode = pf.Zip;
              p.Country = pf.Country;
              p.ProcessType = pf.ProcessType;
              if (pf.ShowCampusOnePageGiving)
                  p.Campus = pf.CampusId.ToString();
  
              p.IsNew = p.person == null;
  
              if (pf.testing)
                  pf.CheckTesting();
  
              if (pf.Country.HasValue() && !pf.Zip.HasValue())
                  pf.Zip = "NA";
  
              pf.ValidatePaymentForm(ModelState, false);
              if (!ModelState.IsValid)
              {
                  m.List[0].FundItem = fundItem;
                  pf.AmtToPay = amtToPay;
                  return View("OnePageGiving/Index", new OnePageGivingModel() { OnlineRegPersonModel = m.List[0], PaymentForm = pf });
              }
  
  
              if (m?.UserPeopleId != null && m.UserPeopleId > 0)
                  try
                  {
                      pf.CheckStoreInVault(ModelState, m.UserPeopleId.Value, visitorIpAddress: VisitorIpAddress);
                  }
                  catch(Exception ex)
                  {
                      if (ex.Message == "InvalidVaultId")
                      {
                          ClearPaymentInfo(ModelState, pf);
                      }
                  }
              if (!ModelState.IsValid)
              {
                  m.List[0].FundItem = fundItem;
                  pf.AmtToPay = amtToPay;
                  return View("OnePageGiving/Index", new OnePageGivingModel() { OnlineRegPersonModel = m.List[0], PaymentForm = pf });
              }
              
              if (CurrentDatabase.Setting("UseRecaptcha"))
              {
                  if (!GoogleRecaptcha.IsValidResponse(HttpContext, CurrentDatabase))
                  {
                      m.List[0].FundItem = fundItem;
                      pf.AmtToPay = amtToPay;
                      ModelState.AddModelError("TranId", "ReCaptcha validation failed.");
                      return View("OnePageGiving/Index", new OnePageGivingModel {
                          OnlineRegPersonModel = m.List[0],
                          PaymentForm = pf
                      });
                  }
              }
  
  
gt:             var ti = pf.ProcessPaymentTransaction(m, VisitorIpAddress);