// TODO: Create abstraction
        private void DetectGreyZones(CalculatorConfiguration configuration, Order order)
        {
            var boundaries = new List <Tuple <Price, CalculationRange> >();

            foreach (var range in configuration.CalculationRanges.Where(x => x.DeminimisThreshold.Value != 0))
            {
                boundaries.Add(new Tuple <Price, CalculationRange>(new Price(order.Currency, range.DeminimisThreshold.Value - .01m), range));
                boundaries.Add(new Tuple <Price, CalculationRange>(new Price(order.Currency, range.DeminimisThreshold.Value), range));
            }

            var greyZonePrices = new List <Tuple <Price, CalculationRange> >();

            foreach (var boundary in boundaries)
            {
                // Create forward calc
                var range             = configuration.GetRangeForBasePrice(boundary.Item1);
                var forwardCalculator = ForwardCalculatorFactory.Create(range);

                var orderItems = order.OrderItems.Select(oi => new OrderItem(oi.Quantity, oi.Weight, oi.VatRate, oi.DutyRate, new Price(order.Currency, order.RelativeOrderItemValue(oi) * boundary.Item1.Value))).ToList();
                orderItems.ForEach(oi => { var c = oi.GetChargeAmount(ChargeNames.InputItem, order.Currency); oi.AddCharge(new OrderCharge(ChargeNames.Item, c, ChargeNames.Item)); });
                var detectionOrder = new Order(order.Country, order.Currency, orderItems, new Price(order.Currency, 0));

                forwardCalculator?.Invoke(detectionOrder);

                var greyZonePrice = detectionOrder.Charges
                                    .Where(x => !x.InputCharge)
                                    .Where(x => x.ChargeName.Value.EndsWith(ChargeNames.Item))
                                    .Select(x => x.ChargeAmount.Value)
                                    .Sum();

                greyZonePrices.Add(new Tuple <Price, CalculationRange>(new Price(order.Currency, greyZonePrice), boundary.Item2));
            }

            if (greyZonePrices.Count % 2 != 0)
            {
                throw new ArgumentException("Invalid grey zones, should be in pairs!");
            }

            for (int x = 0; x < greyZonePrices.Count; x++)
            {
                configuration.AddGreyZone(new GreyZone(greyZonePrices[x].Item1, greyZonePrices[x + 1].Item1, greyZonePrices[x].Item2));
                x++;
            }
        }
        public void GetCalculationRange_MultipleRanges_ShouldReturnCorrectRegions(string price, string expectedThreshold)
        {
            // Arrange
            var deminimisBaseCharges = new List <ChargeName> {
                "Item"
            };
            var chargeConfigurations = new List <ChargeConfiguration>
            {
                new FixedRateChargeConfiguration("Duty", "EUR0", "EUR10"),
                new FixedRateChargeConfiguration("Duty", "EUR100", "EUR20"),
                new FixedRateChargeConfiguration("Duty", "EUR200", "EUR30")
            };

            var calculationRanges = new CalculatorConfiguration(chargeConfigurations, deminimisBaseCharges);

            // Act
            var range = calculationRanges.GetRangeForBasePrice(new Price(price));

            // Assert
            range.DeminimisThreshold.Should().Be(new Price(expectedThreshold));
        }