using System.Text.Json;

namespace ZB.MOM.WW.OtOpcUa.Commons.Types;

/// <summary>
///     SINGLE SOURCE OF TRUTH for extracting + normalizing a <c>Device</c>'s connection host from its
///     schemaless <c>DeviceConfig</c> JSON. Shared by the live-compose seam (<c>AddressSpaceComposer</c>),
///     the artifact-decode seam (<c>DeploymentArtifact</c>), and the FixedTree-partition path
///     (<c>DriverHostActor</c>) so an <c>EquipmentNode.DeviceHost</c> and a driver-discovered device-host
///     folder segment for the same device compare byte-equal. Ported verbatim from the historical
///     <c>AddressSpaceComposer.TryExtractDeviceHost</c> / <c>NormalizeDeviceHost</c>.
/// </summary>
public static class DeviceConfigIntent
{
    /// <summary>
    ///     Extract a <c>Device</c>'s connection host from its schemaless <c>DeviceConfig</c> JSON: the
    ///     top-level <c>"HostAddress"</c> string (e.g. <c>"10.201.31.5:8193"</c>). Returns
    ///     <see langword="null"/> when the config is blank, not a JSON object, has no string
    ///     <c>HostAddress</c>, or the value is blank/whitespace. Never throws. The returned host is
    ///     deterministically normalized via <see cref="NormalizeHost"/> (trim + lower-case).
    /// </summary>
    /// <param name="deviceConfigJson">The device's schemaless <c>DeviceConfig</c> JSON blob.</param>
    /// <returns>The normalized device host, or <see langword="null"/> when absent/blank/unparseable.</returns>
    public static string? TryExtractHost(string? deviceConfigJson)
    {
        if (string.IsNullOrWhiteSpace(deviceConfigJson)) return null;
        try
        {
            using var doc = JsonDocument.Parse(deviceConfigJson);
            if (doc.RootElement.ValueKind != JsonValueKind.Object) return null;
            if (!doc.RootElement.TryGetProperty("HostAddress", out var hostEl)
                || hostEl.ValueKind != JsonValueKind.String) return null;
            var raw = hostEl.GetString();
            if (string.IsNullOrWhiteSpace(raw)) return null;
            return NormalizeHost(raw);
        }
        catch (JsonException) { return null; }
    }

    /// <summary>
    ///     The single normalization authority for a device host: trims surrounding whitespace and
    ///     lower-cases (invariant). Idempotent (an already-normalized value is unchanged).
    /// </summary>
    /// <param name="host">The raw host string (non-null; a non-empty <c>HostAddress</c> or folder segment).</param>
    /// <returns>The normalized host (trimmed + lower-cased).</returns>
    public static string NormalizeHost(string host) => host.Trim().ToLowerInvariant();
}
