using ZB.MOM.WW.OtOpcUa.Configuration.Enums;

namespace ZB.MOM.WW.OtOpcUa.Configuration.Entities;

/// <summary>
///     Maps an LDAP group to an <see cref="AdminRole"/> for Admin UI access. Optionally scoped
///     to one <see cref="ClusterId"/>; when <see cref="IsSystemWide"/> is true, the grant
///     applies fleet-wide.
/// </summary>
/// <remarks>
///     <para>This entity is <b>control-plane
///     only</b>. The OPC UA data-path evaluator does not read these rows; it reads
///     <see cref="NodeAcl"/> joined directly against the session's resolved LDAP group
///     memberships. Collapsing the two would let a user inherit tag permissions via an
///     admin-role claim path never intended as a data-path grant.</para>
///
///     <para>Uniqueness: <c>(LdapGroup, ClusterId)</c> — the same LDAP group may hold
///     different roles on different clusters, but only one row per cluster. A system-wide row
///     (<c>IsSystemWide = true</c>, <c>ClusterId = null</c>) stacks additively with any
///     cluster-scoped rows for the same group.</para>
/// </remarks>
public sealed class LdapGroupRoleMapping
{
    /// <summary>Surrogate primary key.</summary>
    public Guid Id { get; set; }

    /// <summary>
    ///     LDAP group DN the membership query returns (e.g. <c>cn=fleet-admin,ou=groups,dc=corp,dc=example</c>).
    ///     Comparison is case-insensitive per LDAP conventions.
    /// </summary>
    public required string LdapGroup { get; set; }

    /// <summary>Admin role this group grants.</summary>
    public required AdminRole Role { get; set; }

    /// <summary>
    ///     Cluster the grant applies to; <c>null</c> when <see cref="IsSystemWide"/> is true.
    ///     Foreign key to <see cref="ServerCluster.ClusterId"/>.
    /// </summary>
    public string? ClusterId { get; set; }

    /// <summary>
    ///     <c>true</c> = grant applies across every cluster in the fleet; <c>ClusterId</c> must be null.
    ///     <c>false</c> = grant is cluster-scoped; <c>ClusterId</c> must be populated.
    /// </summary>
    public required bool IsSystemWide { get; set; }

    /// <summary>Row creation timestamp (UTC).</summary>
    public DateTime CreatedAtUtc { get; set; }

    /// <summary>Optional human-readable note (e.g. "added 2026-04-19 for Warsaw fleet admin handoff").</summary>
    public string? Notes { get; set; }

    /// <summary>Navigation for EF core when the row is cluster-scoped.</summary>
    public ServerCluster? Cluster { get; set; }
}
