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

public class NotificationRecipient
{
    /// <summary>Gets or sets the database primary key.</summary>
    public int Id { get; set; }
    /// <summary>Gets or sets the id of the parent notification list.</summary>
    public int NotificationListId { get; set; }
    /// <summary>Gets or sets the display name of the recipient.</summary>
    public string Name { get; set; }
    /// <summary>Gets or sets the recipient's email address, or null for non-email recipients.</summary>
    public string? EmailAddress { get; set; }
    /// <summary>Gets or sets the recipient's phone number (E.164), or null for non-SMS recipients.</summary>
    public string? PhoneNumber { get; set; }

    /// <summary>
    /// Initializes a new <see cref="NotificationRecipient"/> with the required fields (email path).
    /// </summary>
    /// <param name="name">Display name of the recipient.</param>
    /// <param name="emailAddress">Email address of the recipient.</param>
    public NotificationRecipient(string name, string emailAddress)
    {
        // Match the ForEmail factory's guard so the invariant ("a recipient always
        // has a non-blank display name") holds regardless of construction path. EF
        // materializes via the private parameterless ctor + property injection — an
        // SMS-only recipient has a null EmailAddress — so this ctor is only reached
        // by code that genuinely intends the email path.
        if (string.IsNullOrWhiteSpace(name))
        {
            throw new ArgumentException("Name must not be empty.", nameof(name));
        }

        Name = name;
        EmailAddress = emailAddress ?? throw new ArgumentNullException(nameof(emailAddress));
    }

    /// <summary>
    /// Creates an email recipient with the given name and email address; the phone number is left null.
    /// </summary>
    /// <param name="name">Display name of the recipient.</param>
    /// <param name="emailAddress">Email address of the recipient.</param>
    /// <returns>A new email <see cref="NotificationRecipient"/>.</returns>
    public static NotificationRecipient ForEmail(string name, string emailAddress)
    {
        if (string.IsNullOrWhiteSpace(name))
        {
            throw new ArgumentException("Name must not be empty.", nameof(name));
        }

        if (emailAddress is null)
        {
            throw new ArgumentNullException(nameof(emailAddress));
        }

        return new NotificationRecipient(name, emailAddress);
    }

    /// <summary>
    /// Creates an SMS recipient with the given name and phone number; the email address is left null.
    /// </summary>
    /// <param name="name">Display name of the recipient.</param>
    /// <param name="phoneNumber">Phone number (E.164) of the recipient.</param>
    /// <returns>A new SMS <see cref="NotificationRecipient"/>.</returns>
    public static NotificationRecipient ForSms(string name, string phoneNumber)
    {
        if (string.IsNullOrWhiteSpace(name))
        {
            throw new ArgumentException("Name must not be empty.", nameof(name));
        }

        if (phoneNumber is null)
        {
            throw new ArgumentNullException(nameof(phoneNumber));
        }

        return new NotificationRecipient
        {
            Name = name,
            PhoneNumber = phoneNumber
        };
    }

    /// <summary>
    /// Private parameterless constructor that backs the <see cref="ForSms"/> factory path,
    /// where the contact field is assigned via property setters rather than constructor
    /// parameters — without exposing a half-initialized public constructor to callers.
    /// </summary>
    private NotificationRecipient()
    {
        Name = string.Empty;
    }
}
