using System.Text.Json; namespace HrynCo.NotificationService.DAL.Abstract.Templates; public static class PushTemplateActionValidation { private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web) { PropertyNameCaseInsensitive = false }; public static PushTemplateActions Parse(string json) { if (string.IsNullOrWhiteSpace(json)) throw new EmailTemplateWriteException("Actions JSON is required. Use {} for no actions.", false); try { var actions = JsonSerializer.Deserialize(json, JsonOptions) ?? throw new JsonException(); Validate(actions); return actions; } catch (JsonException) { throw new EmailTemplateWriteException("Invalid actions JSON. Use defaultAction and buttons with action and label.", false); } } public static void Validate(PushTemplateActions actions) { if (actions.DefaultAction is not null) ValidateKey(actions.DefaultAction); if (actions.Buttons is null || actions.Buttons.Count > 3) throw new EmailTemplateWriteException("Configure up to three push buttons.", false); var keys = new HashSet(StringComparer.Ordinal); foreach (var button in actions.Buttons) { if (button is null) throw new EmailTemplateWriteException("A button needs an action and label.", false); ValidateKey(button.Action); if (!keys.Add(button.Action) || string.IsNullOrWhiteSpace(button.Label) || button.Label.Length > 100) throw new EmailTemplateWriteException("Button actions must be unique and labels must contain 1–100 characters.", false); } } private static void ValidateKey(string key) { if (string.IsNullOrWhiteSpace(key) || key.Length > 100 || key.Any(c => !char.IsAsciiLetterOrDigit(c) && c is not '_' and not '-' and not '.')) throw new EmailTemplateWriteException("Action keys need 1–100 letters, digits, dots, underscores or hyphens.", false); } }