namespace ZB.MOM.WW.OtOpcUa.Core.Authorization;

/// <summary>
///     Address of a node in the 6-level scope hierarchy the Phase 6.2 evaluator walks.
///     Assembled by the dispatch layer from the node's namespace + UNS path + tag; passed
///     to <see cref="IPermissionEvaluator"/> which walks the matching trie path.
/// </summary>
/// <remarks>
///     <para>Per decision #129 and the Phase 6.2 Stream B plan the hierarchy is
///     <c>Cluster → Namespace → UnsArea → UnsLine → Equipment → Tag</c> for UNS
///     (Equipment-kind) namespaces. Galaxy (SystemPlatform-kind) namespaces instead use
///     <c>Cluster → Namespace → FolderSegment(s) → Tag</c>, and each folder segment takes
///     one trie level — so a deeply-nested Galaxy folder implicitly reaches the same
///     depth as a full UNS path.</para>
///
///     <para>Unset mid-path levels (e.g. a Cluster-scoped request with no UnsArea) leave
///     the corresponding id <c>null</c>. The evaluator walks as far as the scope goes +
///     stops at the first null.</para>
/// </remarks>
public sealed record NodeScope
{
    /// <summary>Cluster the node belongs to. Required.</summary>
    public required string ClusterId { get; init; }

    /// <summary>Namespace within the cluster. Null is not allowed for a request against a real node.</summary>
    public string? NamespaceId { get; init; }

    /// <summary>For Equipment-kind namespaces: UNS area (e.g. "warsaw-west"). Null on Galaxy.</summary>
    public string? UnsAreaId { get; init; }

    /// <summary>For Equipment-kind namespaces: UNS line below the area. Null on Galaxy.</summary>
    public string? UnsLineId { get; init; }

    /// <summary>For Equipment-kind namespaces: equipment row below the line. Null on Galaxy.</summary>
    public string? EquipmentId { get; init; }

    /// <summary>
    ///     For Galaxy (SystemPlatform-kind) namespaces only: the folder path segments from
    ///     namespace root to the target tag, in order. Empty on Equipment namespaces.
    /// </summary>
    public IReadOnlyList<string> FolderSegments { get; init; } = [];

    /// <summary>Target tag id when the scope addresses a specific tag; null for folder / equipment-level scopes.</summary>
    public string? TagId { get; init; }

    /// <summary>Which hierarchy applies — Equipment-kind (UNS) or SystemPlatform-kind (Galaxy).</summary>
    public required NodeHierarchyKind Kind { get; init; }
}

/// <summary>Selector between the two scope-hierarchy shapes.</summary>
public enum NodeHierarchyKind
{
    /// <summary><c>Cluster → Namespace → UnsArea → UnsLine → Equipment → Tag</c> — UNS / Equipment kind.</summary>
    Equipment,

    /// <summary><c>Cluster → Namespace → FolderSegment(s) → Tag</c> — Galaxy / SystemPlatform kind.</summary>
    SystemPlatform,
}
