using ZB.MOM.WW.ScadaBridge.Commons.Entities.Notifications;
using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums;

namespace ZB.MOM.WW.ScadaBridge.Commons.Tests.Entities;

/// <summary>
/// Verifies the <see cref="Notification"/> outbox entity's constructor defaults
/// and null-argument guards on required reference-type parameters.
/// </summary>
public class NotificationEntityTests
{
    [Fact]
    public void Constructor_SetsDefaults()
    {
        var n = new Notification("id-1", NotificationType.Email, "ops-team", "subj", "body", "SiteA");
        Assert.Equal(NotificationStatus.Pending, n.Status);
        Assert.Equal(0, n.RetryCount);
        Assert.Equal("id-1", n.NotificationId);
        Assert.Equal(NotificationType.Email, n.Type);
        Assert.Equal("ops-team", n.ListName);
        Assert.Equal("SiteA", n.SourceSiteId);
    }

    [Fact]
    public void OriginExecutionId_DefaultsToNull_AndIsSettable()
    {
        // Audit Log #23: OriginExecutionId carries the originating script
        // execution's id from the site so the dispatcher can echo it onto
        // NotifyDeliver rows. Null for notifications submitted before the
        // column existed; settable from the NotificationSubmit message.
        var n = new Notification("id-1", NotificationType.Email, "ops-team", "subj", "body", "SiteA");
        Assert.Null(n.OriginExecutionId);

        var executionId = Guid.NewGuid();
        n.OriginExecutionId = executionId;
        Assert.Equal(executionId, n.OriginExecutionId);
    }

    [Fact]
    public void OriginParentExecutionId_DefaultsToNull_AndIsSettable()
    {
        // Audit Log ParentExecutionId: OriginParentExecutionId carries the
        // routed run's parent ExecutionId from the site so the dispatcher can
        // echo it onto NotifyDeliver rows. Null for non-routed runs, or for
        // notifications submitted before the column existed.
        var n = new Notification("id-1", NotificationType.Email, "ops-team", "subj", "body", "SiteA");
        Assert.Null(n.OriginParentExecutionId);

        var parentExecutionId = Guid.NewGuid();
        n.OriginParentExecutionId = parentExecutionId;
        Assert.Equal(parentExecutionId, n.OriginParentExecutionId);
    }

    [Fact]
    public void SourceNode_DefaultsToNull_AndIsSettable()
    {
        // SourceNode identifies the cluster node that emitted the notification
        // (site node-a/node-b or central-a/central-b). Additive nullable
        // property — defaults to null on rows submitted before the column
        // existed, and round-trips its value when set.
        var n = new Notification("id-1", NotificationType.Email, "ops-team", "subj", "body", "SiteA");
        Assert.Null(n.SourceNode);

        n.SourceNode = "node-a";
        Assert.Equal("node-a", n.SourceNode);
    }

    [Fact]
    public void Constructor_NullArguments_Throw()
    {
        Assert.Throws<ArgumentNullException>(() => new Notification(null!, NotificationType.Email, "list", "s", "b", "SiteA"));
        Assert.Throws<ArgumentNullException>(() => new Notification("id", NotificationType.Email, null!, "s", "b", "SiteA"));
        Assert.Throws<ArgumentNullException>(() => new Notification("id", NotificationType.Email, "list", null!, "b", "SiteA"));
        Assert.Throws<ArgumentNullException>(() => new Notification("id", NotificationType.Email, "list", "s", null!, "SiteA"));
        Assert.Throws<ArgumentNullException>(() => new Notification("id", NotificationType.Email, "list", "s", "b", null!));
    }
}
