using Elwig.Helpers;
using Elwig.Helpers.Billing;
using Elwig.Models.Entities;
using System.Text.Json;

namespace Tests.HelperTests {
    [TestFixture]
    public class BillingDataTest {

        private static readonly JsonSerializerOptions JsonOpts = new() { WriteIndented = true };
        private static readonly RawVaribute[] Vaributes = [
            new("GV/-"), new("GV/D-"), new("GV/K-"), new("GV/S-"), new("GV/Z-"),
            new("WR/-"), new("WR/S-"), new("ZW/-"), new("ZW/S-"), new("ZW/Z-"),
            new("GV/-B"), new("WR/-B"), new("ZW/-B"), new("ZW/S-B"), new("GV/S-B"), new("GV/K-B")];

        private static (string, string?, string?) GetSortIdAttrId(string bucket) {
            var v = bucket.Split('-');
            return (v[0][..2], v[0].Length > 2 ? v[0][2..] : null, v.Length > 1 ? v[1] : null);
        }

        private static string GetQualId(double kmw) {
            return kmw switch {
                >= 17.0 => "KAB",
                >= 15.0 => "QUW",
                >= 14.0 => "LDW",
                >= 10.6 => "RSW",
                _ => "WEI",
            };
        }

        private static void TestCalcOe(PaymentBillingData data, string bucket, double oe, decimal expected, string? qualid = null, bool geb = false) {
            var (sortid, attrid, cultid) = GetSortIdAttrId(bucket);
            var kmw = Utils.OeToKmw(oe);
            var v = data.CalculatePrice(sortid, attrid, cultid, qualid ?? GetQualId(kmw), geb, oe, kmw);
            Assert.That(Math.Round(v, 6), Is.EqualTo(expected));
        }

        private static void TestCalcKmw(PaymentBillingData data, string bucket, double kmw, decimal expected, string? qualid = null, bool geb = false) {
            var (sortid, attrid, cultid) = GetSortIdAttrId(bucket);
            var oe = Utils.KmwToOe(kmw);
            var v = data.CalculatePrice(sortid, attrid, cultid, qualid ?? GetQualId(kmw), geb, oe, kmw);
            Assert.That(Math.Round(v, 6), Is.EqualTo(expected));
        }

        [Test]
        public void TestRead_01_Flatrate() {
            var data = PaymentBillingData.FromJson("""
                {
                  "mode": "elwig",
                  "version": 1,
                  "payment": 0.5,
                  "curves": []
                }
                """, Vaributes);
            Assert.Multiple(() => {
                TestCalcOe(data, "GV",  73, 0.5m);
                TestCalcOe(data, "WRS", 74, 0.5m);
            });
        }

        [Test]
        public void TestRead_02_Simple() {
            var data = PaymentBillingData.FromJson("""
                {
                  "mode": "elwig",
                  "version": 1,
                  "payment": "curve:1",
                  "curves": [{
                    "id": 1,
                    "mode": "oe",
                    "data": {
                      "72.0oe": 0.25,
                      "15.0kmw": 0.5,
                      "83oe": 1
                    },
                    "geb": 0.10
                  }]
                }
                """, Vaributes);
            Assert.Multiple(() => {
                TestCalcOe(data, "GV", 70, 0.25m);
                TestCalcOe(data, "GV", 72, 0.25m);
                TestCalcOe(data, "GV", 73, 0.50m);
                TestCalcOe(data, "GV", 74, 0.55m);
                TestCalcOe(data, "GV", 80, 0.85m);
                TestCalcOe(data, "GV", 83, 1.00m);
                TestCalcOe(data, "GV", 90, 1.00m);
                TestCalcOe(data, "GV", 73, 0.60m, geb: true);
                TestCalcOe(data, "GV", 74, 0.65m, geb: true);
                TestCalcOe(data, "GV", 80, 0.95m, geb: true);
                TestCalcOe(data, "GV", 83, 1.10m, geb: true);
                TestCalcOe(data, "GV", 90, 1.10m, geb: true);
            });
        }

        [Test]
        public void TestRead_03_GreaterThanAndLessThan() {
            var data = PaymentBillingData.FromJson("""
                {
                  "mode": "elwig",
                  "version": 1,
                  "payment": "curve:1",
                  "curves": [{
                    "id": 1,
                    "mode": "kmw",
                    "data": {
                      "<14kmw": 0.1,
                      "14kmw": 0.2,
                      "<15kmw": 0.25,
                      "15kmw": 0.5,
                      "17kmw": 1,
                      ">17kmw": 1.25
                    }
                  }]
                }
                """, Vaributes);
            Assert.Multiple(() => {
                TestCalcKmw(data, "GV", 13.00, 0.10m);
                TestCalcKmw(data, "GV", 13.50, 0.10m);
                TestCalcKmw(data, "GV", 13.99, 0.10m);
                TestCalcKmw(data, "GV", 14.00, 0.20m);
                TestCalcKmw(data, "GV", 14.50, 0.225m);
                TestCalcKmw(data, "GV", 15.00, 0.50m);
                TestCalcKmw(data, "GV", 15.50, 0.625m);
                TestCalcKmw(data, "GV", 16.00, 0.75m);
                TestCalcKmw(data, "GV", 16.50, 0.875m);
                TestCalcKmw(data, "GV", 17.00, 1.00m);
                TestCalcKmw(data, "GV", 17.01, 1.25m);
                TestCalcKmw(data, "GV", 17.50, 1.25m);
                TestCalcKmw(data, "GV", 18.00, 1.25m);
                TestCalcKmw(data, "GV", 18.50, 1.25m);
            });
        }

        [Test]
        public void TestRead_04_VariantsAndAttributes() {
            var data = PaymentBillingData.FromJson("""
                {
                  "mode": "elwig",
                  "version": 1,
                  "payment": {
                    "default": 0.10,
                    "GV/": 0.20,
                    "ZW": 0.25,
                    "/S": 0.15,
                    "GV/K": 0.30
                  },
                  "curves": []
                }
                """, Vaributes);
            Assert.Multiple(() => {
                TestCalcOe(data, "WR",  73, 0.10m);
                TestCalcOe(data, "WRS", 73, 0.15m);
                TestCalcOe(data, "GV",  73, 0.20m);
                TestCalcOe(data, "GVD", 73, 0.10m);
                TestCalcOe(data, "GVK", 73, 0.30m);
                TestCalcOe(data, "GVS", 73, 0.15m);
                TestCalcOe(data, "GVZ", 73, 0.10m);
                TestCalcOe(data, "ZW",  73, 0.25m);
                TestCalcOe(data, "ZWS", 73, 0.15m);
                TestCalcOe(data, "ZWZ", 73, 0.25m);
            });
        }

        [Test]
        public void TestRead_05_Cultivations() {
            var data = PaymentBillingData.FromJson("""
                {
                  "mode": "elwig",
                  "version": 1,
                  "payment": {
                    "default": 0.10,
                    "-B": 0.20,
                    "/S": 0.30
                  },
                  "curves": []
                }
                """, Vaributes);
            Assert.Multiple(() => {
                TestCalcOe(data, "WR",    73, 0.10m);
                TestCalcOe(data, "WR-B",  73, 0.20m);
                TestCalcOe(data, "WRS",   73, 0.30m);
                TestCalcOe(data, "GV",    73, 0.10m);
                TestCalcOe(data, "GV-B",  73, 0.20m);
                TestCalcOe(data, "GVD",   73, 0.10m);
                TestCalcOe(data, "GVK",   73, 0.10m);
                TestCalcOe(data, "GVK-B", 73, 0.20m);
                TestCalcOe(data, "GVS",   73, 0.30m);
                TestCalcOe(data, "GVS-B", 73, 0.30m);
                TestCalcOe(data, "GVZ",   73, 0.10m);
                TestCalcOe(data, "ZW",    73, 0.10m);
                TestCalcOe(data, "ZW-B",  73, 0.20m);
                TestCalcOe(data, "ZWS",   73, 0.30m);
                TestCalcOe(data, "ZWZ",   73, 0.10m);
            });
        }

        [Test]
        public void TestRead_06_QualityLevel() {
            var data = PaymentBillingData.FromJson("""
                {
                  "mode": "elwig",
                  "version": 1,
                  "payment": 0.5,
                  "quality": {
                    "WEI": {
                      "default": 0.25,
                      "GV": 0.3,
                      "/S": 0.2
                    }
                  },
                  "curves": []
                }
                """, Vaributes);
            Assert.Multiple(() => {
                TestCalcOe(data, "GV",  75, 0.30m, qualid: "WEI");
                TestCalcOe(data, "ZW",  76, 0.25m, qualid: "WEI");
                TestCalcOe(data, "GVS", 75, 0.20m, qualid: "WEI");
                TestCalcOe(data, "GVK", 74, 0.30m, qualid: "WEI");
                TestCalcOe(data, "ZWS", 73, 0.20m, qualid: "WEI");
                TestCalcOe(data, "GV",  70, 0.5m);
                TestCalcOe(data, "GV",  72, 0.5m);
                TestCalcOe(data, "GV",  73, 0.5m);
                TestCalcOe(data, "ZWS", 74, 0.5m);
                TestCalcOe(data, "GVK", 80, 0.5m);
            });
        }

        [Test]
        public void TestRead_07_ModeOeAndKmw() {
            var data = PaymentBillingData.FromJson("""
                {
                  "mode": "elwig",
                  "version": 1,
                  "payment": {
                    "default": 1.0,
                    "GV": "curve:1",
                    "ZW": "curve:2"
                  },
                  "curves": [{
                    "id": 1,
                    "mode": "oe",
                    "data": {
                      "73oe": 2.0,
                      "17kmw": 3.0
                    }
                  }, {
                    "id": 2,
                    "mode": "kmw",
                    "data": {
                      "73oe": 2.0,
                      "17kmw": 3.0
                    }
                  }]
                }
                """, Vaributes);
            Assert.Multiple(() => {
                TestCalcKmw(data, "GV", 15.0, 2.0m);
                TestCalcKmw(data, "GV", 15.5, 2.272727m);
                TestCalcKmw(data, "GV", 16.0, 2.454545m);
                TestCalcKmw(data, "GV", 16.5, 2.727273m);
                TestCalcKmw(data, "GV", 17.0, 3.0m);
                TestCalcKmw(data, "ZW", 15.0, 2.0m);
                TestCalcKmw(data, "ZW", 15.5, 2.25m);
                TestCalcKmw(data, "ZW", 16.0, 2.50m);
                TestCalcKmw(data, "ZW", 16.5, 2.75m);
                TestCalcKmw(data, "ZW", 17.0, 3.0m);
            });
        }

        [Test]
        public void TestRead_08_MultipleCurves() {
            var data = PaymentBillingData.FromJson("""
                {
                  "mode": "elwig",
                  "version": 1,
                  "payment": {
                    "default": 0.25,
                    "/S": "curve:1",
                    "GV/": 0.75,
                    "GV/K": "curve:2",
                    "WR/S": "curve:3"
                  },
                  "curves": [{
                    "id": 3,
                    "mode": "kmw",
                    "data": {
                      "73oe": 0.7,
                      "17kmw": 0.8
                    },
                    "geb": {
                      "15kmw": 0.8,
                      "17kmw": 0.95
                    }
                  }, {
                    "id": 1,
                    "mode": "kmw",
                    "data": {
                      "73oe": 0.5,
                      "17kmw": 0.6
                    },
                    "geb": 0.1
                  }, {
                    "id": 2,
                    "mode": "kmw",
                    "data": {
                      "15kmw": 0.6,
                      "17kmw": 0.7
                    },
                    "geb": {
                      "73oe": 0.65,
                      "17kmw": 0.80
                    }
                  }]
                }
                """, Vaributes);
            Assert.Multiple(() => {
                TestCalcKmw(data, "GV",  15.0, 0.75m);
                TestCalcKmw(data, "GVS", 15.0, 0.50m);
                TestCalcKmw(data, "GVS", 16.0, 0.55m);
                TestCalcKmw(data, "GVS", 17.0, 0.60m);
                TestCalcKmw(data, "GVS", 15.0, 0.60m, geb: true);
                TestCalcKmw(data, "GVS", 16.0, 0.65m, geb: true);
                TestCalcKmw(data, "GVS", 17.0, 0.70m, geb: true);
                TestCalcKmw(data, "GVK", 15.0, 0.60m);
                TestCalcKmw(data, "GVK", 16.0, 0.65m);
                TestCalcKmw(data, "GVK", 17.0, 0.70m);
                TestCalcKmw(data, "GVK", 15.0, 0.65m, geb: true);
                TestCalcKmw(data, "GVK", 16.0, 0.725m, geb: true);
                TestCalcKmw(data, "GVK", 17.0, 0.80m, geb: true);
                TestCalcKmw(data, "WRS", 15.0, 0.70m);
                TestCalcKmw(data, "WRS", 16.0, 0.75m);
                TestCalcKmw(data, "WRS", 17.0, 0.80m);
                TestCalcKmw(data, "WRS", 15.0, 0.80m, geb: true);
                TestCalcKmw(data, "WRS", 16.0, 0.875m, geb: true);
                TestCalcKmw(data, "WRS", 17.0, 0.95m, geb: true);
            });
        }

        [Test]
        public void TestRead_09_WgMaster() {
            var data = PaymentBillingData.FromJson("""
                {
                  "mode": "wgmaster",
                  "Grundbetrag": 0.033,
                  "GBZS": 0.0,
                  "Ausgabefaktor": 1.0,
                  "Rebelzuschlag": 0.0,
                  "AufschlagVolllieferanten": 0.0,
                  "AuszahlungSorten": {
                    "BL/": 0.097,
                    "BP/": 0.097,
                    "GV/K": "curve:1",
                    "SL/": 0.097,
                    "ZW/": 0.097,
                    "default": "curve:0"
                  },
                  "AuszahlungSortenQualitätsstufe": {
                    "WEI": 0.005
                  },
                  "Kurven": [{
                    "id": 0,
                    "mode": "oe",
                    "data": 0.033,
                    "geb": 0
                  }, {
                    "id": 1,
                    "mode": "oe",
                    "data": {
                      "88oe": 0.032,
                      "89oe": 0.065
                    }
                  }]
                }
                """, Vaributes);
            Assert.Multiple(() => {
                TestCalcOe(data, "GVK", 73, 0.032m);
                TestCalcOe(data, "ZWS", 74, 0.033m);
                TestCalcOe(data, "GV", 75, 0.005m, qualid: "WEI");
                TestCalcOe(data, "GVK", 115, 0.065m);
            });
        }

        [Test]
        public void TestRead_10_AttrubteAndCultivation() {
            var data = PaymentBillingData.FromJson("""
                {
                  "mode": "elwig",
                  "version": 1,
                  "payment": {
                    "default": 0.10,
                    "/S": 0.20,
                    "-B": 0.30,
                    "GV/S-B": 0.40
                  },
                  "curves": []
                }
                """, Vaributes);
            Assert.Multiple(() => {
                TestCalcOe(data, "GV", 73, 0.10m);
                TestCalcOe(data, "GVS", 73, 0.20m);
                TestCalcOe(data, "GV-B", 73, 0.30m);
                TestCalcOe(data, "GVS-B", 73, 0.40m);
                TestCalcOe(data, "ZWS-B", 73, 0.20m);
            });
        }

        private static List<Varibute> GetSelection(IEnumerable<string> attVars) {
            return attVars.Select(s => new Varibute(new RawVaribute(s))).ToList();
        }

        [Test]
        public void TestWrite_01_Empty() {
            List<GraphEntry> entries = [
                new GraphEntry(1, 4, BillingData.CurveMode.Oe, new() {
                    [73] = 0.5m
                }, null)
            ];
            var updated = BillingData.FromGraphEntries(entries);
            Assert.That(updated.ToJsonString(JsonOpts), Is.EqualTo("""
                {
                  "mode": "elwig",
                  "version": 1,
                  "payment": 0,
                  "curves": []
                }
                """));
        }

        [Test]
        public void TestWrite_02_Flatrate() {
            List<GraphEntry> entries = [
                new GraphEntry(0, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() {
                    [73] = 0.5m
                }, null), GetSelection(["GV/-"]))
            ];
            var data = BillingData.FromGraphEntries(entries);
            Assert.That(data.ToJsonString(JsonOpts), Is.EqualTo("""
                {
                  "mode": "elwig",
                  "version": 1,
                  "payment": 0.5,
                  "curves": []
                }
                """));
        }

        [Test]
        public void TestWrite_03_SingleCurve() {
            List<GraphEntry> entries = [
               new GraphEntry(0, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() {
                   [73] = 0.5m,
                   [83] = 1.0m
               }, null), GetSelection(["GV/-"]))
           ];
            var data = BillingData.FromGraphEntries(entries);
            Assert.That(data.ToJsonString(JsonOpts), Is.EqualTo("""
                {
                  "mode": "elwig",
                  "version": 1,
                  "payment": "curve:1",
                  "curves": [
                    {
                      "id": 1,
                      "mode": "oe",
                      "data": {
                        "73oe": 0.5,
                        "83oe": 1
                      }
                    }
                  ]
                }
                """));
        }

        [Test]
        public void TestWrite_04_Simple() {
            List<GraphEntry> entries = [
               new GraphEntry(0, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() {
                   [73] = 0.5m,
                   [84] = 1.0m
               }, null), GetSelection(["GV/-", "ZW/-"])),
                new GraphEntry(10, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() {
                    [73] = 0.75m,
                }, null), GetSelection(["WR/-"]))
           ];
            var data = BillingData.FromGraphEntries(entries);
            Assert.That(data.ToJsonString(JsonOpts), Is.EqualTo("""
                {
                  "mode": "elwig",
                  "version": 1,
                  "payment": {
                    "default": "curve:1",
                    "WR": 0.75
                  },
                  "curves": [
                    {
                      "id": 1,
                      "mode": "oe",
                      "data": {
                        "73oe": 0.5,
                        "84oe": 1
                      }
                    }
                  ]
                }
                """));
        }

        [Test]
        public void TestWrite_05_Attribute() {
            List<GraphEntry> entries = [
               new GraphEntry(0, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() {
                   [73] = 0.5m,
                   [84] = 1.0m
               }, null), GetSelection(["GV/K-", "ZW/K-"])),
                new GraphEntry(2, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() {
                    [73] = 0.75m,
                }, null), GetSelection(["WR/-", "BL/-", "RR/-", "FV/-"])),
                new GraphEntry(4, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() {
                    [73] = 0.65m,
                    [84] = 1.2m
                }, null), GetSelection(["BP/-", "SA/-"]))
           ];
            var data = BillingData.FromGraphEntries(entries);
            Assert.That(data.ToJsonString(JsonOpts), Is.EqualTo("""
                {
                  "mode": "elwig",
                  "version": 1,
                  "payment": {
                    "default": 0.75,
                    "/K": "curve:1",
                    "BP": "curve:2",
                    "SA": "curve:2"
                  },
                  "curves": [
                    {
                      "id": 1,
                      "mode": "oe",
                      "data": {
                        "73oe": 0.5,
                        "84oe": 1
                      }
                    },
                    {
                      "id": 2,
                      "mode": "oe",
                      "data": {
                        "73oe": 0.65,
                        "84oe": 1.2
                      }
                    }
                  ]
                }
                """));
        }

        [Test]
        public void TestWrite_06_Cultivation_1() {
            List<GraphEntry> entries = [
                new GraphEntry(0, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() {
                    [73] = 0.5m,
                    [84] = 1.0m
                }, null), GetSelection(["GV/-B", "ZW/-B"])),
                new GraphEntry(2, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() {
                    [73] = 0.75m,
                }, null), GetSelection(["WR/-", "BL/-", "RR/-", "FV/-"])),
                new GraphEntry(4, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() {
                    [73] = 0.65m,
                    [84] = 1.2m
                }, null), GetSelection(["BP/-", "SA/-"]))
           ];
            var data = BillingData.FromGraphEntries(entries);
            Assert.That(data.ToJsonString(JsonOpts), Is.EqualTo("""
                {
                  "mode": "elwig",
                  "version": 1,
                  "payment": {
                    "default": 0.75,
                    "BP": "curve:2",
                    "SA": "curve:2",
                    "-B": "curve:1"
                  },
                  "curves": [
                    {
                      "id": 1,
                      "mode": "oe",
                      "data": {
                        "73oe": 0.5,
                        "84oe": 1
                      }
                    },
                    {
                      "id": 2,
                      "mode": "oe",
                      "data": {
                        "73oe": 0.65,
                        "84oe": 1.2
                      }
                    }
                  ]
                }
                """));
        }

        [Test]
        public void TestWrite_07_Cultivation_2() {
            List<GraphEntry> entries = [
                new GraphEntry(0, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() {
                    [73] = 0.6m,
                    [84] = 1.0m
                }, null), GetSelection(["GV/-", "GV/-B"])),
                new GraphEntry(2, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() {
                    [73] = 0.75m,
                }, null), GetSelection(["ZW/-", "ZW/-B"])),
                 new GraphEntry(2, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() {
                    [73] = 0.8m,
                }, null), GetSelection(["BP/-", "BP/-B"])),
           ];
            var data = BillingData.FromGraphEntries(entries);
            Assert.That(data.ToJsonString(JsonOpts), Is.EqualTo("""
                {
                  "mode": "elwig",
                  "version": 1,
                  "payment": {
                    "GV": "curve:1",
                    "ZW": 0.75,
                    "BP": 0.8
                  },
                  "curves": [
                    {
                      "id": 1,
                      "mode": "oe",
                      "data": {
                        "73oe": 0.6,
                        "84oe": 1
                      }
                    }
                  ]
                }
                """));
        }

        [Test]
        public void TestWrite_08_Cultivation_3() {
            List<GraphEntry> entries = [
                new GraphEntry(0, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() {
                    [73] = 0.6m,
                    [84] = 1.0m
                }, null), GetSelection(["GV/-", "GV/-B"])),
                new GraphEntry(2, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() {
                    [73] = 0.75m,
                }, null), GetSelection(["BP/-B", "ZW/-B", "FV/-B"])),
                 new GraphEntry(2, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() {
                    [73] = 0.8m,
                }, null), GetSelection(["BP/-", "ZW/-", "FV/-", "WR/-", "BL/-"])),
           ];
            var data = BillingData.FromGraphEntries(entries);
            Assert.That(data.ToJsonString(JsonOpts), Is.EqualTo("""
                {
                  "mode": "elwig",
                  "version": 1,
                  "payment": {
                    "default": 0.8,
                    "GV": "curve:1",
                    "GV-B": "curve:1",
                    "-B": 0.75
                  },
                  "curves": [
                    {
                      "id": 1,
                      "mode": "oe",
                      "data": {
                        "73oe": 0.6,
                        "84oe": 1
                      }
                    }
                  ]
                }
                """));
        }

        [Test]
        public void TestWrite_09_AttributeAndCultivation() {
            List<GraphEntry> entries = [
                new GraphEntry(0, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() {
                    [73] = 0.75m,
                }, null), GetSelection(["GV/-", "ZW/-", "WR/-", "RR/-", "BL/-", "BP/-", "FV/-"])),
                new GraphEntry(2, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() {
                    [73] = 0.3m,
                }, null), GetSelection(["GV/S-", "ZW/S-"])),
                new GraphEntry(4, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() {
                    [73] = 0.2m,
                }, null), GetSelection(["GV/-B", "ZW/-B"])),
                new GraphEntry(4, 4, new BillingData.Curve(BillingData.CurveMode.Oe, new() {
                    [73] = 0.4m,
                }, null), GetSelection(["GV/S-B", "ZW/S-B"]))
            ];
            var data = BillingData.FromGraphEntries(entries);
            Assert.That(data.ToJsonString(JsonOpts), Is.EqualTo("""
                {
                  "mode": "elwig",
                  "version": 1,
                  "payment": {
                    "default": 0.75,
                    "/S": 0.3,
                    "/S-B": 0.4,
                    "-B": 0.2
                  },
                  "curves": []
                }
                """));
        }
    }
}