namespace ZB.MOM.WW.ScadaBridge.NotificationOutbox.Delivery;

/// <summary>
/// Classification of a single delivery attempt. Transient failures are eligible for
/// retry; permanent failures are terminal and not retried.
/// </summary>
public enum DeliveryResult
{
    /// <summary>The notification was delivered successfully.</summary>
    Success,

    /// <summary>Delivery failed for a transient reason and may succeed on retry.</summary>
    TransientFailure,

    /// <summary>Delivery failed for a permanent reason and must not be retried.</summary>
    PermanentFailure
}

/// <summary>
/// Result of a delivery attempt produced by an <see cref="INotificationDeliveryAdapter"/>.
/// </summary>
/// <param name="Result">The classification of the attempt.</param>
/// <param name="ResolvedTargets">
/// The concrete delivery targets used, snapshotted for audit. Set only on success.
/// </param>
/// <param name="Error">A human-readable failure description. Set only on failure.</param>
public record DeliveryOutcome(DeliveryResult Result, string? ResolvedTargets, string? Error)
{
    /// <summary>Creates a successful outcome carrying the resolved delivery targets.</summary>
    /// <param name="resolvedTargets">The concrete delivery targets used, for audit.</param>
    /// <returns>A <see cref="DeliveryOutcome"/> with <see cref="DeliveryResult.Success"/> and the resolved targets set.</returns>
    public static DeliveryOutcome Success(string resolvedTargets) =>
        new(DeliveryResult.Success, resolvedTargets, null);

    /// <summary>Creates a transient-failure outcome carrying an error description.</summary>
    /// <param name="error">Human-readable description of the transient failure.</param>
    /// <returns>A <see cref="DeliveryOutcome"/> with <see cref="DeliveryResult.TransientFailure"/> and the error set.</returns>
    public static DeliveryOutcome Transient(string error) =>
        new(DeliveryResult.TransientFailure, null, error);

    /// <summary>Creates a permanent-failure outcome carrying an error description.</summary>
    /// <param name="error">Human-readable description of the permanent failure.</param>
    /// <returns>A <see cref="DeliveryOutcome"/> with <see cref="DeliveryResult.PermanentFailure"/> and the error set.</returns>
    public static DeliveryOutcome Permanent(string error) =>
        new(DeliveryResult.PermanentFailure, null, error);
}
