void SetCryptoCurrencies(CheckoutAppearanceViewModel vm, Data.StoreData storeData)
        {
            var enabled          = storeData.GetEnabledPaymentIds(_NetworkProvider);
            var defaultPaymentId = storeData.GetDefaultPaymentId();
            var defaultChoice    = defaultPaymentId is not null?defaultPaymentId.FindNearest(enabled) : null;

            if (defaultChoice is null)
            {
                defaultChoice = enabled.FirstOrDefault(e => e.CryptoCode == "BTC" && e.PaymentType == PaymentTypes.BTCLike) ??
                                enabled.FirstOrDefault(e => e.CryptoCode == "BTC" && e.PaymentType == PaymentTypes.LightningLike) ??
                                enabled.FirstOrDefault();
            }
            var choices = enabled
                          .Select(o =>
                                  new CheckoutAppearanceViewModel.Format()
            {
                Name      = o.ToPrettyString(),
                Value     = o.ToString(),
                PaymentId = o
            }).ToArray();
            var chosen = defaultChoice is null ? null : choices.FirstOrDefault(c => defaultChoice.ToString().Equals(c.Value, StringComparison.OrdinalIgnoreCase));

            vm.PaymentMethods       = new SelectList(choices, nameof(chosen.Value), nameof(chosen.Name), chosen?.Value);
            vm.DefaultPaymentMethod = chosen?.Value;
        }
        void SetCryptoCurrencies(CheckoutAppearanceViewModel vm, Data.StoreData storeData)
        {
            var choices = GetEnabledPaymentMethodChoices(storeData);
            var chosen  = GetDefaultPaymentMethodChoice(storeData);

            vm.PaymentMethods       = new SelectList(choices, nameof(chosen.Value), nameof(chosen.Name), chosen?.Value);
            vm.DefaultPaymentMethod = chosen?.Value;
        }
        public IActionResult CheckoutAppearance()
        {
            var storeBlob = CurrentStore.GetStoreBlob();
            var vm        = new CheckoutAppearanceViewModel();

            SetCryptoCurrencies(vm, CurrentStore);
            vm.PaymentMethodCriteria = CurrentStore.GetSupportedPaymentMethods(_NetworkProvider)
                                       .Where(s => !storeBlob.GetExcludedPaymentMethods().Match(s.PaymentId))
                                       .Where(s => _NetworkProvider.GetNetwork(s.PaymentId.CryptoCode) != null)
                                       .Where(s => s.PaymentId.PaymentType != PaymentTypes.LNURLPay)
                                       .Select(method =>
            {
                var existing =
                    storeBlob.PaymentMethodCriteria.SingleOrDefault(criteria =>
                                                                    criteria.PaymentMethod == method.PaymentId);
                if (existing is null)
                {
                    return(new PaymentMethodCriteriaViewModel()
                    {
                        PaymentMethod = method.PaymentId.ToString(),
                        Value = ""
                    });
                }
                else
                {
                    return(new PaymentMethodCriteriaViewModel()
                    {
                        PaymentMethod = existing.PaymentMethod.ToString(),
                        Type = existing.Above
                            ? PaymentMethodCriteriaViewModel.CriteriaType.GreaterThan
                            : PaymentMethodCriteriaViewModel.CriteriaType.LessThan,
                        Value = existing.Value?.ToString() ?? ""
                    });
                }
            }).ToList();

            vm.RequiresRefundEmail   = storeBlob.RequiresRefundEmail;
            vm.LazyPaymentMethods    = storeBlob.LazyPaymentMethods;
            vm.RedirectAutomatically = storeBlob.RedirectAutomatically;
            vm.CustomCSS             = storeBlob.CustomCSS;
            vm.CustomLogo            = storeBlob.CustomLogo;
            vm.HtmlTitle             = storeBlob.HtmlTitle;
            vm.ReceiptOptions        = CheckoutAppearanceViewModel.ReceiptOptionsViewModel.Create(storeBlob.ReceiptOptions);
            vm.AutoDetectLanguage    = storeBlob.AutoDetectLanguage;
            vm.SetLanguages(_LangService, storeBlob.DefaultLang);

            return(View(vm));
        }
        public async Task <IActionResult> CheckoutAppearance(CheckoutAppearanceViewModel model)
        {
            bool needUpdate             = false;
            var  blob                   = CurrentStore.GetStoreBlob();
            var  defaultPaymentMethodId = model.DefaultPaymentMethod == null ? null : PaymentMethodId.Parse(model.DefaultPaymentMethod);

            if (CurrentStore.GetDefaultPaymentId() != defaultPaymentMethodId)
            {
                needUpdate = true;
                CurrentStore.SetDefaultPaymentId(defaultPaymentMethodId);
            }
            SetCryptoCurrencies(model, CurrentStore);
            model.SetLanguages(_LangService, model.DefaultLang);
            model.PaymentMethodCriteria ??= new List <PaymentMethodCriteriaViewModel>();
            for (var index = 0; index < model.PaymentMethodCriteria.Count; index++)
            {
                var methodCriterion = model.PaymentMethodCriteria[index];
                if (!string.IsNullOrWhiteSpace(methodCriterion.Value))
                {
                    if (!CurrencyValue.TryParse(methodCriterion.Value, out var value))
                    {
                        model.AddModelError(viewModel => viewModel.PaymentMethodCriteria[index].Value,
                                            $"{methodCriterion.PaymentMethod}: Invalid format. Make sure to enter a valid amount and currency code. Examples: '5 USD', '0.001 BTC'", this);
                    }
                }
            }

            if (!ModelState.IsValid)
            {
                return(View(model));
            }

            // Payment criteria for Off-Chain should also affect LNUrl
            foreach (var newCriteria in model.PaymentMethodCriteria.ToList())
            {
                var paymentMethodId = PaymentMethodId.Parse(newCriteria.PaymentMethod);
                if (paymentMethodId.PaymentType == PaymentTypes.LightningLike)
                {
                    model.PaymentMethodCriteria.Add(new PaymentMethodCriteriaViewModel()
                    {
                        PaymentMethod = new PaymentMethodId(paymentMethodId.CryptoCode, PaymentTypes.LNURLPay).ToString(),
                        Type          = newCriteria.Type,
                        Value         = newCriteria.Value
                    });
                }
                // Should not be able to set LNUrlPay criteria directly in UI
                if (paymentMethodId.PaymentType == PaymentTypes.LNURLPay)
                {
                    model.PaymentMethodCriteria.Remove(newCriteria);
                }
            }
            blob.PaymentMethodCriteria ??= new List <PaymentMethodCriteria>();
            foreach (var newCriteria in model.PaymentMethodCriteria)
            {
                var paymentMethodId  = PaymentMethodId.Parse(newCriteria.PaymentMethod);
                var existingCriteria = blob.PaymentMethodCriteria.FirstOrDefault(c => c.PaymentMethod == paymentMethodId);
                if (existingCriteria != null)
                {
                    blob.PaymentMethodCriteria.Remove(existingCriteria);
                }
                CurrencyValue.TryParse(newCriteria.Value, out var cv);
                blob.PaymentMethodCriteria.Add(new PaymentMethodCriteria()
                {
                    Above         = newCriteria.Type == PaymentMethodCriteriaViewModel.CriteriaType.GreaterThan,
                    Value         = cv,
                    PaymentMethod = paymentMethodId
                });
            }
            blob.RequiresRefundEmail   = model.RequiresRefundEmail;
            blob.LazyPaymentMethods    = model.LazyPaymentMethods;
            blob.RedirectAutomatically = model.RedirectAutomatically;
            blob.CustomLogo            = model.CustomLogo;
            blob.CustomCSS             = model.CustomCSS;
            blob.HtmlTitle             = string.IsNullOrWhiteSpace(model.HtmlTitle) ? null : model.HtmlTitle;
            blob.AutoDetectLanguage    = model.AutoDetectLanguage;
            blob.DefaultLang           = model.DefaultLang;

            if (CurrentStore.SetStoreBlob(blob))
            {
                needUpdate = true;
            }
            if (needUpdate)
            {
                await _Repo.UpdateStore(CurrentStore);

                TempData[WellKnownTempData.SuccessMessage] = "Store successfully updated";
            }

            return(RedirectToAction(nameof(CheckoutAppearance), new
            {
                storeId = CurrentStore.Id
            }));
        }