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

namespace ZB.MOM.WW.ScadaBridge.StoreAndForward;

/// <summary>
/// Represents a single store-and-forward message as stored in SQLite.
/// Maps to the sf_messages table.
/// </summary>
public class StoreAndForwardMessage
{
    /// <summary>Unique message ID (GUID).</summary>
    public string Id { get; set; } = string.Empty;

    /// <summary>Category: ExternalSystem, Notification, or CachedDbWrite.</summary>
    public StoreAndForwardCategory Category { get; set; }

    /// <summary>Target system name (external system, notification list, or DB connection).</summary>
    public string Target { get; set; } = string.Empty;

    /// <summary>JSON-serialized payload containing the call details.</summary>
    public string PayloadJson { get; set; } = string.Empty;

    /// <summary>
    /// Number of retry-sweep attempts performed so far. The initial (immediate or
    /// caller-made) delivery attempt is attempt 0 and is not counted here; this
    /// field counts only background retry attempts.
    /// </summary>
    public int RetryCount { get; set; }

    /// <summary>
    /// Maximum retry-sweep attempts before the message is parked.
    /// <c>0</c> = no limit — the message is retried on every sweep until delivered
    /// and is never parked for exhausting retries. This is <b>not</b> a "never retry"
    /// value; a positive value is required to bound delivery attempts.
    /// </summary>
    public int MaxRetries { get; set; }

    /// <summary>Retry interval in milliseconds.</summary>
    public long RetryIntervalMs { get; set; }

    /// <summary>When this message was first enqueued.</summary>
    public DateTimeOffset CreatedAt { get; set; }

    /// <summary>When delivery was last attempted (null if never attempted).</summary>
    public DateTimeOffset? LastAttemptAt { get; set; }

    /// <summary>Current status of the message.</summary>
    public StoreAndForwardMessageStatus Status { get; set; }

    /// <summary>Last error message from a failed delivery attempt.</summary>
    public string? LastError { get; set; }

    /// <summary>
    /// Instance that originated this message (for S&amp;F-survives-delete behavior).
    /// </summary>
    public string? OriginInstanceName { get; set; }

    /// <summary>
    /// The originating script execution's
    /// per-run correlation id, threaded from <c>ScriptRuntimeContext</c> through
    /// the cached-call enqueue path. Carried so the store-and-forward retry loop
    /// can stamp it onto the per-attempt / terminal cached-call audit rows
    /// (<c>ApiCallCached</c>/<c>DbWriteCached</c> Attempted, <c>CachedResolve</c>).
    /// <c>null</c> for non-cached-call categories (notifications) and for rows
    /// buffered before this field existed — back-compat with old persisted rows
    /// (the column is added by an additive migration and read as null when absent).
    /// </summary>
    public Guid? ExecutionId { get; set; }

    /// <summary>
    /// The originating script identifier,
    /// threaded alongside <see cref="ExecutionId"/> from the cached-call enqueue
    /// path so the retry-loop audit rows carry the same <c>SourceScript</c>
    /// provenance the script-side cached rows already carry. <c>null</c> when not
    /// known (non-cached categories, pre-migration rows).
    /// </summary>
    public string? SourceScript { get; set; }

    /// <summary>
    /// The <c>ExecutionId</c> of the
    /// inbound-API request that spawned the originating script execution,
    /// threaded alongside <see cref="ExecutionId"/> from the cached-call enqueue
    /// path. Carried so the store-and-forward retry loop can stamp it onto the
    /// per-attempt / terminal cached-call audit rows
    /// (<c>ApiCallCached</c>/<c>DbWriteCached</c> Attempted, <c>CachedResolve</c>),
    /// keeping them correlated with the cross-execution chain. <c>null</c> for a
    /// non-routed run, for non-cached-call categories (notifications), and for
    /// rows buffered before this field existed — back-compat with old persisted
    /// rows (the column is added by an additive migration and read as null when
    /// absent).
    /// </summary>
    public Guid? ParentExecutionId { get; set; }
}
