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

/// <summary>
///     Single source of truth for equipment-namespace OPC UA NodeId strings. The variable NodeId is
///     FOLDER-SCOPED (<c>{parent}/{Name}</c>), NOT the driver-side FullName — a driver wire ref is not
///     unique across identical machines, so FullName-as-NodeId would collide in the sink. Used by the
///     materialiser (AddressSpaceApplier), the VirtualTag publish map, and the driver live-value router so all
///     three agree on the exact NodeId a variable was placed at.
/// </summary>
public static class EquipmentNodeIds
{
    /// <summary>The sub-folder NodeId under an equipment for a non-empty FolderPath: <c>{equipmentId}/{folderPath}</c>.</summary>
    /// <param name="equipmentId">The owning equipment's NodeId.</param>
    /// <param name="folderPath">The tag/vtag FolderPath (must be non-empty for this to be meaningful).</param>
    /// <returns>The sub-folder NodeId string.</returns>
    public static string SubFolder(string equipmentId, string folderPath) => $"{equipmentId}/{folderPath}";

    /// <summary>
    ///     The folder-scoped variable NodeId: <c>{parent}/{name}</c> where <c>parent = equipmentId</c> when
    ///     <paramref name="folderPath"/> is null/empty, else <see cref="SubFolder"/>.
    /// </summary>
    /// <param name="equipmentId">The owning equipment's NodeId.</param>
    /// <param name="folderPath">The tag/vtag FolderPath, or null/empty for "directly under the equipment".</param>
    /// <param name="name">The tag/vtag Name (the leaf browse segment).</param>
    /// <returns>The folder-scoped variable NodeId string.</returns>
    public static string Variable(string equipmentId, string? folderPath, string name)
    {
        var parent = string.IsNullOrWhiteSpace(folderPath) ? equipmentId : SubFolder(equipmentId, folderPath);
        return $"{parent}/{name}";
    }
}
