using System; using System.Collections.Generic; using System.Linq; using System.Text.Json.Nodes; namespace Elwig.Helpers.Billing { public class PaymentBillingData : BillingData { protected readonly Dictionary Curves; protected readonly Dictionary PaymentData; protected readonly Dictionary QualityData; protected readonly IEnumerable AttributeVariants; public PaymentBillingData(JsonObject data, IEnumerable attributeVariants) : base(data) { if (attributeVariants.Any(e => e.Any(c => c < 'A' || c > 'Z'))) throw new ArgumentException("Invalid attributeVariants"); AttributeVariants = attributeVariants; Curves = GetCurves(); PaymentData = GetPaymentData(); QualityData = GetQualityData(); } public static PaymentBillingData FromJson(string json, IEnumerable attributeVariants) { return new(ParseJson(json), attributeVariants); } private Dictionary GetData(JsonNode data) { return GetSelection(data, AttributeVariants).ToDictionary(e => e.Key, e => LookupCurve(e.Value)); } protected Dictionary GetPaymentData() { return GetData(GetPaymentEntry()); } protected Dictionary GetQualityData() { Dictionary dict = []; var q = GetQualityEntry(); if (q == null) return dict; foreach (var (qualid, data) in q) { foreach (var (idx, d) in GetData(data ?? throw new InvalidOperationException())) { dict[$"{qualid}/{idx}"] = d; } } return dict; } public decimal CalculatePrice(string sortid, string? attrid, string qualid, bool gebunden, double oe, double kmw) { var curve = GetQualityCurve(qualid, sortid, attrid) ?? GetCurve(sortid, attrid); var d = (gebunden ? curve.Gebunden : null) ?? curve.Normal; if (d.Count == 1) return d.First().Value; var r = curve.Mode == CurveMode.Oe ? oe : kmw; var lt = d.Keys.Where(v => v <= r); var gt = d.Keys.Where(v => v >= r); if (!lt.Any()) { return d[gt.Min()]; } else if (!gt.Any()) { return d[lt.Max()]; } var max = lt.Max(); var min = gt.Min(); if (max == min) return d[r]; var p1 = ((decimal)r - (decimal)min) / ((decimal)max - (decimal)min); var p2 = 1 - p1; return d[min] * p2 + d[max] * p1; } private Curve LookupCurve(JsonValue val) { if (val.TryGetValue(out string? curve)) { var curveId = int.Parse(curve.Split(":")[1]); return Curves[curveId]; } else if (val.TryGetValue(out decimal value)) { return new(CurveMode.Oe, new() { { 73, value } }, null); } throw new InvalidOperationException(); } protected Curve GetCurve(string sortid, string? attrid) { return PaymentData[$"{sortid}{attrid ?? ""}"]; } protected Curve? GetQualityCurve(string qualid, string sortid, string? attrid) { return QualityData.TryGetValue($"{qualid}/{sortid}{attrid ?? ""}", out var curve) ? curve : null; } } }