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

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

/// <summary>
/// A single notification queued in the central outbox. Created at a site (where the
/// <see cref="NotificationId"/> GUID is generated) and forwarded to the central cluster
/// for delivery, retry, and audit. The lifecycle is tracked by <see cref="Status"/>.
/// </summary>
public class Notification
{
    /// <summary>GUID primary key, generated at the originating site.</summary>
    public string NotificationId { get; set; }
    /// <summary>Gets or sets the notification type.</summary>
    public NotificationType Type { get; set; }
    /// <summary>Gets or sets the notification list name.</summary>
    public string ListName { get; set; }
    /// <summary>Gets or sets the notification subject.</summary>
    public string Subject { get; set; }
    /// <summary>Gets or sets the notification body.</summary>
    public string Body { get; set; }

    /// <summary>JSON extensibility hook for channel-specific payload data.</summary>
    public string? TypeData { get; set; }
    /// <summary>Gets or sets the notification delivery status.</summary>
    public NotificationStatus Status { get; set; } = NotificationStatus.Pending;
    /// <summary>Gets or sets the delivery retry count.</summary>
    public int RetryCount { get; set; }
    /// <summary>Gets or sets the last error message, if any.</summary>
    public string? LastError { get; set; }

    /// <summary>Resolved delivery targets snapshotted at delivery time, for audit.</summary>
    public string? ResolvedTargets { get; set; }
    /// <summary>Gets or sets the originating site ID.</summary>
    public string SourceSiteId { get; set; }

    /// <summary>
    /// The cluster node on which the notification was emitted — `node-a` / `node-b`
    /// for site rows (qualified by <see cref="SourceSiteId"/>), `central-a` / `central-b`
    /// for central-originated rows. Carried from the site on the
    /// <see cref="Commons.Messages.Notification.NotificationSubmit"/> and persisted at
    /// central; nullable so rows submitted before the column existed don't block ingest.
    /// </summary>
    public string? SourceNode { get; set; }
    /// <summary>Gets or sets the originating instance ID, if any.</summary>
    public string? SourceInstanceId { get; set; }
    /// <summary>Gets or sets the originating script name, if any.</summary>
    public string? SourceScript { get; set; }

    /// <summary>
    /// The originating script execution's <c>ExecutionId</c>. Carried from
    /// the site on the <see cref="Commons.Messages.Notification.NotificationSubmit"/> so the
    /// central dispatcher can stamp the same id onto its <c>NotifyDeliver</c> audit rows,
    /// correlating them with the site-emitted <c>NotifySend</c> row. Null for notifications
    /// submitted before the column existed, or raised outside a script-execution context.
    /// </summary>
    public Guid? OriginExecutionId { get; set; }

    /// <summary>
    /// The originating routed script execution's <c>ParentExecutionId</c>.
    /// Carried from the site on the <see cref="Commons.Messages.Notification.NotificationSubmit"/>
    /// so the central dispatcher can stamp the same parent id onto its <c>NotifyDeliver</c>
    /// audit rows, correlating them with the site-emitted <c>NotifySend</c> row. Null for
    /// non-routed runs, or for notifications submitted before the column existed.
    /// </summary>
    public Guid? OriginParentExecutionId { get; set; }
    /// <summary>Gets or sets the time when the notification was enqueued at the site.</summary>
    public DateTimeOffset SiteEnqueuedAt { get; set; }

    /// <summary>Central ingest time.</summary>
    public DateTimeOffset CreatedAt { get; set; }
    /// <summary>Gets or sets the time of the last delivery attempt, if any.</summary>
    public DateTimeOffset? LastAttemptAt { get; set; }
    /// <summary>Gets or sets the time of the next scheduled delivery attempt, if any.</summary>
    public DateTimeOffset? NextAttemptAt { get; set; }
    /// <summary>Gets or sets the time the notification was delivered, if any.</summary>
    public DateTimeOffset? DeliveredAt { get; set; }

    /// <summary>
    /// Initializes a new instance of the Notification class.
    /// </summary>
    /// <param name="notificationId">The notification ID (GUID).</param>
    /// <param name="type">The notification type.</param>
    /// <param name="listName">The notification list name.</param>
    /// <param name="subject">The notification subject.</param>
    /// <param name="body">The notification body text.</param>
    /// <param name="sourceSiteId">The originating site ID.</param>
    public Notification(string notificationId, NotificationType type, string listName,
        string subject, string body, string sourceSiteId)
    {
        NotificationId = notificationId ?? throw new ArgumentNullException(nameof(notificationId));
        Type = type;
        ListName = listName ?? throw new ArgumentNullException(nameof(listName));
        Subject = subject ?? throw new ArgumentNullException(nameof(subject));
        Body = body ?? throw new ArgumentNullException(nameof(body));
        SourceSiteId = sourceSiteId ?? throw new ArgumentNullException(nameof(sourceSiteId));
    }
}
