namespace ZB.MOM.WW.Audit;

/// <summary>
/// Canonical, transport-agnostic audit record — who did what, when, with what outcome.
/// Required core + optional common fields + a <see cref="DetailsJson"/> extension bag. Each
/// sister app maps its own record onto this; domain vocabularies (channels/kinds/event-types)
/// map into <see cref="Action"/>/<see cref="Category"/>/<see cref="DetailsJson"/> and are not
/// modelled here. See scadaproj/components/audit/spec/EVENT-MODEL.md.
/// </summary>
public sealed record AuditEvent
{
    /// <summary>Idempotency key uniquely identifying this audit event.</summary>
    public required Guid EventId { get; init; }

    /// <summary>When the audited action occurred. Normalized to UTC on assignment.</summary>
    /// <remarks>Participates in record value-equality as a normalized instant: two events whose
    /// <c>OccurredAtUtc</c> denote the same instant at different offsets (e.g. <c>12:00+05:00</c> and
    /// <c>07:00Z</c>) compare equal and share a hash code. Relevant to consumers that dedup/key on
    /// <see cref="AuditEvent"/> value-equality.</remarks>
    public required DateTimeOffset OccurredAtUtc
    {
        get => _occurredAtUtc;
        init => _occurredAtUtc = value.ToUniversalTime();
    }
    private readonly DateTimeOffset _occurredAtUtc;

    /// <summary>Who performed the action (identity string; the ZB.MOM.WW.Auth principal at adoption).</summary>
    public required string Actor { get; init; }

    /// <summary>What was done — a verb/event-type string.</summary>
    public required string Action { get; init; }

    /// <summary>Normalized outcome.</summary>
    public required AuditOutcome Outcome { get; init; }

    /// <summary>Optional subsystem/grouping for the action.</summary>
    public string? Category { get; init; }

    /// <summary>Optional target of the action (resource/method/connection).</summary>
    public string? Target { get; init; }

    /// <summary>Optional node that emitted the event.</summary>
    public string? SourceNode { get; init; }

    /// <summary>Optional correlation id joining this row to its originating request/workflow.</summary>
    public Guid? CorrelationId { get; init; }

    /// <summary>Optional JSON extension carrying project-specific fields.</summary>
    public string? DetailsJson { get; init; }
}
