namespace ZB.MOM.WW.Audit.Tests;

public class AuditEventTests
{
    private static AuditEvent Minimal() => new()
    {
        EventId = Guid.NewGuid(),
        OccurredAtUtc = DateTimeOffset.UtcNow,
        Actor = "alice",
        Action = "ConfigPublished",
        Outcome = AuditOutcome.Success,
    };

    [Fact]
    public void Required_core_fields_round_trip()
    {
        var id = Guid.NewGuid();
        var evt = Minimal() with { EventId = id, Actor = "svc", Action = "ApiCall", Outcome = AuditOutcome.Denied };
        Assert.Equal(id, evt.EventId);
        Assert.Equal("svc", evt.Actor);
        Assert.Equal("ApiCall", evt.Action);
        Assert.Equal(AuditOutcome.Denied, evt.Outcome);
    }

    [Fact]
    public void OccurredAtUtc_is_normalized_to_utc()
    {
        var local = new DateTimeOffset(2026, 6, 1, 12, 0, 0, TimeSpan.FromHours(5));
        var evt = Minimal() with { OccurredAtUtc = local };
        Assert.Equal(TimeSpan.Zero, evt.OccurredAtUtc.Offset);
        Assert.Equal(local.UtcDateTime, evt.OccurredAtUtc.UtcDateTime);
    }

    [Fact]
    public void Optional_fields_default_to_null()
    {
        var evt = Minimal();
        Assert.Null(evt.Category);
        Assert.Null(evt.Target);
        Assert.Null(evt.SourceNode);
        Assert.Null(evt.CorrelationId);
        Assert.Null(evt.DetailsJson);
    }

    [Fact]
    public void Records_with_same_values_are_equal()
    {
        var id = Guid.NewGuid();
        var when = DateTimeOffset.UtcNow;
        AuditEvent Make() => new() { EventId = id, OccurredAtUtc = when, Actor = "a", Action = "x", Outcome = AuditOutcome.Success };
        Assert.Equal(Make(), Make());
    }

    [Fact]
    public void Same_instant_at_different_offset_compares_equal()
    {
        // Guards the UTC-normalizing init-setter: if OccurredAtUtc is ever "simplified" back to a
        // plain auto-property, these two (same instant, different offset) would stop comparing equal.
        var id = Guid.NewGuid();
        var utc = new DateTimeOffset(2026, 6, 1, 7, 0, 0, TimeSpan.Zero);
        var plus5 = new DateTimeOffset(2026, 6, 1, 12, 0, 0, TimeSpan.FromHours(5)); // same instant as utc
        AuditEvent With(DateTimeOffset when) =>
            new() { EventId = id, OccurredAtUtc = when, Actor = "a", Action = "x", Outcome = AuditOutcome.Success };
        Assert.Equal(With(utc), With(plus5));
        Assert.Equal(With(utc).GetHashCode(), With(plus5).GetHashCode());
    }
}
