using System.Text.Json;
using System.Text.Json.Serialization;

namespace ZB.MOM.WW.OtOpcUa.Driver.Mqtt;

/// <summary>
///     The <b>single</b> <see cref="JsonSerializerOptions"/> instance every MQTT driver-config seam
///     parses <see cref="MqttDriverOptions"/> through — the runtime factory
///     (<c>MqttDriverFactoryExtensions</c>), the Test-connect probe (<c>MqttDriverProbe</c>), the
///     driver's own <c>ReinitializeAsync</c> re-parse, and the address-picker browser
///     (<c>MqttDriverBrowser</c>).
/// </summary>
/// <remarks>
///     <para>
///         <b>Why one instance, and why here.</b> Divergent per-seam options are this repo's
///         documented systemic enum bug: an AdminUI-authored config with an enum-valued field is
///         accepted by the seam that carries a <see cref="JsonStringEnumConverter"/> and faults the
///         one that does not, so "Test connect" goes green and the deployed driver dies. Two other
///         drivers already carry a copy per seam. Rather than repeat that, this driver keeps exactly
///         one instance.
///     </para>
///     <para>
///         It lives in <c>.Contracts</c> — the assembly that owns <see cref="MqttDriverOptions"/> and
///         the three enums the converter exists for — rather than in the factory or the probe,
///         because <c>.Contracts</c> is the <i>only</i> assembly all four consumers already reference.
///         In particular the browser lives in its own assembly and reaches the runtime <c>.Driver</c>
///         project only through a deliberate, documented layering exception that is scheduled to be
///         removed (see the <c>ProjectReference</c> comment in the browser's csproj); anchoring the
///         options in <c>.Driver</c> would resurrect the duplicate the day that reference goes away.
///     </para>
///     <para>
///         <b>Not a general-purpose JSON policy.</b> <c>UnmappedMemberHandling.Skip</c> means an
///         unknown key is ignored rather than rejected — deliberate, so a config blob authored
///         against a newer driver still binds — and <c>PropertyNameCaseInsensitive</c> accepts both
///         the camelCase the AdminUI emits and the PascalCase a hand-edited blob may carry. A
///         <see cref="JsonSerializerOptions"/> becomes read-only on first use, so this instance is
///         safe to share across threads and must never be mutated after startup.
///     </para>
/// </remarks>
public static class MqttJson
{
    /// <summary>
    ///     The shared options. Enum-valued knobs (<see cref="MqttMode"/>,
    ///     <see cref="MqttProtocolVersion"/>, <see cref="MqttPayloadFormat"/>) round-trip by
    ///     <b>name</b>; numeric ordinals still bind, so an older blob is not broken by this.
    /// </summary>
    public static readonly JsonSerializerOptions Options = new()
    {
        PropertyNameCaseInsensitive = true,
        UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip,
        Converters = { new JsonStringEnumConverter() },
    };
}
