using System;
using System.IO.Pipes;
using System.Security.AccessControl;
using System.Security.Principal;

namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Ipc;

/// <summary>
///     Builds a strict <see cref="PipeSecurity"/> for the historian sidecar pipe — only the
///     configured server-principal SID gets <c>ReadWrite | Synchronize</c>, LocalSystem is
///     explicitly denied (unless it's the allowed principal itself), and the allowed SID owns
///     the DACL. Mirrors the policy in Driver.Galaxy.Host's PipeAcl.
/// </summary>
public static class PipeAcl
{
    /// <summary>Creates a strict PipeSecurity for the historian sidecar pipe.</summary>
    /// <param name="allowedSid">The security identifier that should have read-write access to the pipe.</param>
    /// <returns>A configured PipeSecurity object with strict access control.</returns>
    public static PipeSecurity Create(SecurityIdentifier allowedSid)
    {
        if (allowedSid is null) throw new ArgumentNullException(nameof(allowedSid));

        var security = new PipeSecurity();

        security.AddAccessRule(new PipeAccessRule(
            allowedSid,
            PipeAccessRights.ReadWrite | PipeAccessRights.Synchronize,
            AccessControlType.Allow));

        var localSystem = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null);
        if (allowedSid != localSystem)
            security.AddAccessRule(new PipeAccessRule(localSystem, PipeAccessRights.FullControl, AccessControlType.Deny));

        // Owner = allowed SID so the deny rules can't be removed without write-DACL rights.
        security.SetOwner(allowedSid);

        return security;
    }
}
