#nullable enable
namespace Baya.Application.Contracts.Common;

/// <summary>
/// The channel a notification is delivered through. Only <see cref="InApp"/> is wired now; SMS/push
/// arrive in later phases behind the same seam.
/// </summary>
public enum NotificationChannel
{
    InApp,
    Sms,
    Push
}

/// <summary>A notification to mint for a recipient over one channel.</summary>
/// <param name="RecipientUserId">The target user.</param>
/// <param name="Type">Stable type code driving front-end rendering/deep-link (e.g. <c>booking_confirmed</c>).</param>
/// <param name="Title">Short title/subject.</param>
/// <param name="Body">Optional message body (no secrets/PII in logs).</param>
/// <param name="DataJson">Optional typed, versioned deep-link payload — a contract, not an arbitrary blob.</param>
/// <param name="Channel">Delivery channel (in-app now; SMS/push deferred).</param>
public sealed record Notification(
    int RecipientUserId,
    string Type,
    string Title,
    string? Body = null,
    string? DataJson = null,
    NotificationChannel Channel = NotificationChannel.InApp);

/// <summary>
/// Seam for minting notifications from domains like booking, payments, and reviews. The real in-app
/// implementation writes a <c>notifications</c> row; SMS/push channels are added later behind this same
/// interface, so callers use <see cref="DispatchAsync"/> unchanged.
/// </summary>
public interface INotificationDispatcher
{
    ValueTask DispatchAsync(Notification notification, CancellationToken cancellationToken = default);
}
