private InvoiceEntity ToEntity(Data.InvoiceData invoice)
        {
            var entity = invoice.GetBlob(_Networks);
            PaymentMethodDictionary paymentMethods = null;

#pragma warning disable CS0618
            entity.Payments = invoice.Payments.Select(p =>
            {
                var paymentEntity = p.GetBlob(_Networks);
                if (paymentEntity is null)
                {
                    return(null);
                }
                // PaymentEntity on version 0 does not have their own fee, because it was assumed that the payment method have fixed fee.
                // We want to hide this legacy detail in InvoiceRepository, so we fetch the fee from the PaymentMethod and assign it to the PaymentEntity.
                if (paymentEntity.Version == 0)
                {
                    if (paymentMethods == null)
                    {
                        paymentMethods = entity.GetPaymentMethods();
                    }
                    var paymentMethodDetails = paymentMethods.TryGet(paymentEntity.GetPaymentMethodId())?.GetPaymentMethodDetails();
                    if (paymentMethodDetails != null) // == null should never happen, but we never know.
                    {
                        paymentEntity.NetworkFee = paymentMethodDetails.GetNextNetworkFee();
                    }
                }

                return(paymentEntity);
            })
                              .Where(p => p != null)
                              .OrderBy(a => a.ReceivedTime).ToList();
#pragma warning restore CS0618
            var state = invoice.GetInvoiceState();
            entity.ExceptionStatus = state.ExceptionStatus;
            entity.Status          = state.Status;
            entity.RefundMail      = invoice.CustomerEmail;
            entity.Refundable      = false;
            if (invoice.HistoricalAddressInvoices != null)
            {
                entity.HistoricalAddresses = invoice.HistoricalAddressInvoices.ToArray();
            }
            if (invoice.AddressInvoices != null)
            {
                entity.AvailableAddressHashes = invoice.AddressInvoices.Select(a => a.GetAddress() + a.GetpaymentMethodId().ToString()).ToHashSet();
            }
            if (invoice.Events != null)
            {
                entity.Events = invoice.Events.OrderBy(c => c.Timestamp).ToList();
            }
            if (!string.IsNullOrEmpty(entity.RefundMail) && string.IsNullOrEmpty(entity.Metadata.BuyerEmail))
            {
                entity.Metadata.BuyerEmail = entity.RefundMail;
            }
            entity.Archived = invoice.Archived;
            return(entity);
        }
        public async Task <InvoiceEntity> CreateInvoiceAsync(string storeId, InvoiceEntity invoice, string[] additionalSearchTerms = null)
        {
            var textSearch = new HashSet <string>();

            invoice          = Clone(invoice);
            invoice.Networks = _btcPayNetworkProvider;
            invoice.Id       = Encoders.Base58.EncodeData(RandomUtils.GetBytes(16));
#pragma warning disable CS0618
            invoice.Payments = new List <PaymentEntity>();
#pragma warning restore CS0618
            invoice.StoreId = storeId;
            using (var context = _applicationDbContextFactory.CreateContext())
            {
                var invoiceData = new Data.InvoiceData()
                {
                    StoreDataId = storeId,
                    Id          = invoice.Id,
                    Created     = invoice.InvoiceTime,
                    Blob        = ToBytes(invoice, null),
                    OrderId     = invoice.Metadata.OrderId,
#pragma warning disable CS0618 // Type or member is obsolete
                    Status = invoice.StatusString,
#pragma warning restore CS0618 // Type or member is obsolete
                    ItemCode      = invoice.Metadata.ItemCode,
                    CustomerEmail = invoice.RefundMail,
                    Archived      = false
                };
                await context.Invoices.AddAsync(invoiceData);


                foreach (var paymentMethod in invoice.GetPaymentMethods())
                {
                    if (paymentMethod.Network == null)
                    {
                        throw new InvalidOperationException("CryptoCode unsupported");
                    }
                    var details = paymentMethod.GetPaymentMethodDetails();
                    if (!details.Activated)
                    {
                        continue;
                    }
                    var    paymentDestination = details.GetPaymentDestination();
                    string address            = GetDestination(paymentMethod);
                    await context.AddressInvoices.AddAsync(new AddressInvoiceData()
                    {
                        InvoiceDataId = invoice.Id,
                        CreatedTime   = DateTimeOffset.UtcNow,
                    }.Set(address, paymentMethod.GetId()));

                    textSearch.Add(paymentDestination);
                    textSearch.Add(paymentMethod.Calculate().TotalDue.ToString());
                }
                await context.PendingInvoices.AddAsync(new PendingInvoiceData()
                {
                    Id = invoice.Id
                });

                textSearch.Add(invoice.Id);
                textSearch.Add(invoice.InvoiceTime.ToString(CultureInfo.InvariantCulture));
                if (!invoice.IsUnsetTopUp())
                {
                    textSearch.Add(invoice.Price.ToString(CultureInfo.InvariantCulture));
                }
                textSearch.Add(invoice.Metadata.OrderId);
                textSearch.Add(invoice.StoreId);
                textSearch.Add(invoice.Metadata.BuyerEmail);

                if (additionalSearchTerms != null)
                {
                    textSearch.AddRange(additionalSearchTerms);
                }
                AddToTextSearch(context, invoiceData, textSearch.ToArray());

                await context.SaveChangesAsync().ConfigureAwait(false);
            }


            return(invoice);
        }