using ZB.MOM.WW.ScadaBridge.Commons.Types;

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

/// <summary>
/// Central operational state row for a cached call.
/// One row per <see cref="TrackedOperationId"/> in the <c>SiteCalls</c> table — append-once
/// then monotonic status update. Status transitions are forward-only
/// (<c>Submitted → Forwarded → Attempted → Delivered|Failed|Parked|Discarded</c>); an
/// out-of-order or duplicate upsert is a silent no-op so duplicate gRPC packets and
/// reconciliation pulls can both feed the same writer without rolling state back.
/// </summary>
/// <remarks>
/// Sites remain the source of truth — this row is the eventually-consistent mirror the
/// Central UI's Site Calls page reads. Unlike the partitioned <c>AuditLog</c> table this
/// entity backs operational (mutable) state on a standard non-partitioned table on
/// <c>[PRIMARY]</c>; no DB-role restriction applies.
/// </remarks>
public sealed record SiteCall
{
    /// <summary>Strong-typed idempotency key shared with every audit row for the operation.</summary>
    public required TrackedOperationId TrackedOperationId { get; init; }

    /// <summary>Trust-boundary channel — <c>"ApiOutbound"</c> or <c>"DbOutbound"</c>.</summary>
    public required string Channel { get; init; }

    /// <summary>Human-readable target (e.g. <c>"ERP.GetOrder"</c>).</summary>
    public required string Target { get; init; }

    /// <summary>Site id that submitted the cached call.</summary>
    public required string SourceSite { get; init; }

    /// <summary>
    /// The cluster node on which the cached call was emitted — <c>node-a</c> /
    /// <c>node-b</c> for site rows (qualified by <see cref="SourceSite"/>),
    /// <c>central-a</c> / <c>central-b</c> for central-originated rows. Stamped
    /// by the emitting node from <c>INodeIdentityProvider</c>; nullable so
    /// reconciled rows from a node that has since been retired don't block ingest.
    /// </summary>
    public string? SourceNode { get; init; }

    /// <summary>
    /// Lifecycle status — string form of
    /// <see cref="ZB.MOM.WW.ScadaBridge.Commons.Types.Enums.AuditStatus"/>. Monotonic: later rank
    /// wins, earlier rank is a no-op.
    /// </summary>
    public required string Status { get; init; }

    /// <summary>Number of dispatch attempts so far; 0 prior to first attempt.</summary>
    public required int RetryCount { get; init; }

    /// <summary>Most recent error message; null when no failures have occurred.</summary>
    public string? LastError { get; init; }

    /// <summary>Most recent HTTP status code (API calls only); null otherwise.</summary>
    public int? HttpStatus { get; init; }

    /// <summary>UTC timestamp the cached call was first submitted at the site.</summary>
    public required DateTime CreatedAtUtc { get; init; }

    /// <summary>UTC timestamp of the latest status mutation at the site.</summary>
    public required DateTime UpdatedAtUtc { get; init; }

    /// <summary>UTC timestamp the row reached a terminal status; null while still active.</summary>
    public DateTime? TerminalAtUtc { get; init; }

    /// <summary>UTC timestamp central ingested (or last refreshed) this row.</summary>
    public required DateTime IngestedAtUtc { get; init; }
}
