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

/// <summary>
/// Pure, driver-agnostic merge helper for the two server-side HistoryRead intent keys at the ROOT of a
/// tag's <c>TagConfig</c> JSON: <c>isHistorized</c> (camelCase bool — omit/false default) and
/// <c>historianTagname</c> (camelCase string override — omit when blank). These map to what the server's
/// <c>AddressSpaceComposer.ExtractTagHistorize</c> reads (see <c>docs/Historian.md</c>).
///
/// <para>
/// This is the TagModal-merge seam: the TagModal owns the canonical TagConfig JSON; the driver's typed
/// editor reads/writes its driver-specific fields on that same JSON, and the modal's "Historize this tag"
/// checkbox + "Historian tagname (override)" textbox read/write these two keys through this helper. They
/// COMPOSE because both sides preserve every unrecognised key (delegated to
/// <see cref="TagConfigJson.ParseOrNew"/> / <see cref="TagConfigJson.Set"/>), so neither clobbers the
/// other's fields. These keys are intentionally NOT carried inside any per-driver typed model.
/// </para>
/// </summary>
public static class TagHistorizeConfig
{
    /// <summary>The two history-intent values parsed from a TagConfig JSON's root.</summary>
    /// <param name="IsHistorized">Whether the server exposes OPC UA HistoryRead over this tag's node.</param>
    /// <param name="HistorianTagname">Optional historian tagname override; <c>""</c> means default to the tag's FullName.</param>
    public readonly record struct HistorizeState(bool IsHistorized, string HistorianTagname);

    /// <summary>Reads the history-intent keys from a TagConfig JSON, defaulting any absent key
    /// (null/blank/malformed input ⇒ <c>(false, "")</c>).</summary>
    /// <param name="json">The tag's TagConfig JSON, or null/empty/malformed input.</param>
    /// <returns>The parsed history-intent state, defaulted to <c>(false, "")</c> when keys are absent.</returns>
    public static HistorizeState Read(string? json)
    {
        var o = TagConfigJson.ParseOrNew(json);
        return new HistorizeState(
            TagConfigJson.GetBool(o, "isHistorized"),
            TagConfigJson.GetString(o, "historianTagname") ?? "");
    }

    /// <summary>Merges the two history-intent keys into <paramref name="json"/>, preserving every other
    /// (driver-specific or unknown) key. <c>isHistorized</c> is dropped when false (absent ⇒ false at the
    /// composer); <c>historianTagname</c> is dropped when null/blank (absent ⇒ defaults to FullName) and
    /// trimmed otherwise.</summary>
    /// <param name="json">The tag's existing TagConfig JSON, or null/empty to start from a new object.</param>
    /// <param name="isHistorized">Whether the server should expose OPC UA HistoryRead over this tag's node.</param>
    /// <param name="historianTagname">Optional historian tagname override; null/blank omits the key.</param>
    /// <returns>The merged TagConfig JSON with the two history-intent keys applied.</returns>
    public static string Set(string? json, bool isHistorized, string? historianTagname)
    {
        var o = TagConfigJson.ParseOrNew(json);
        TagConfigJson.Set(o, "isHistorized", isHistorized ? true : null);
        TagConfigJson.Set(o, "historianTagname",
            string.IsNullOrWhiteSpace(historianTagname) ? null : historianTagname.Trim());
        return TagConfigJson.Serialize(o);
    }
}
