using System.Text.Json;
using System.Text.Json.Nodes;

namespace ZB.MOM.WW.OtOpcUa.AdminUI.Uns.TagEditors;

/// <summary>
/// Helpers for per-driver tag-config editors: parse a TagConfig JSON string into a mutable
/// <see cref="JsonObject"/> (preserving every key, so fields the editor doesn't expose survive a
/// load→save), read typed scalars, and serialise back.
/// </summary>
public static class TagConfigJson
{
    /// <summary>Parses <paramref name="json"/> into a mutable object; returns a fresh empty object on null/blank/malformed/non-object input.</summary>
    public static JsonObject ParseOrNew(string? json)
    {
        if (string.IsNullOrWhiteSpace(json)) { return new JsonObject(); }
        try { return JsonNode.Parse(json) as JsonObject ?? new JsonObject(); }
        catch (JsonException) { return new JsonObject(); }
    }

    /// <summary>Serialises the object to compact JSON (JsonNode.ToJsonString() defaults to non-indented).</summary>
    public static string Serialize(JsonObject obj) => obj.ToJsonString();

    /// <summary>Reads a string value, or null if absent/null/non-string.</summary>
    public static string? GetString(JsonObject o, string name)
        => o.TryGetPropertyValue(name, out var n) && n is JsonValue v && v.TryGetValue<string>(out var s) ? s : null;

    /// <summary>Reads an int value, or <paramref name="fallback"/> if absent/null/non-numeric (incl. object/array nodes).</summary>
    public static int GetInt(JsonObject o, string name, int fallback = 0)
        => o.TryGetPropertyValue(name, out var n) && n is JsonValue v && v.TryGetValue<int>(out var i) ? i : fallback;

    /// <summary>Reads an enum by its serialised name, or <paramref name="fallback"/> if absent/unparseable.</summary>
    public static TEnum GetEnum<TEnum>(JsonObject o, string name, TEnum fallback) where TEnum : struct, Enum
        => GetString(o, name) is { } s && Enum.TryParse<TEnum>(s, ignoreCase: true, out var v) ? v : fallback;

    /// <summary>Sets a string/number/enum-name value (enums via ToString()). A null value REMOVES the key, so it is omitted from the serialised JSON.</summary>
    public static void Set(JsonObject o, string name, object? value)
    {
        if (value is null) { o.Remove(name); return; }
        o[name] = JsonValue.Create(value is Enum e ? e.ToString() : value);
    }
}
