namespace Baya.Domain.Entities.Reviews;

/// <summary>
/// The moderation lifecycle of a <see cref="Review"/>, persisted as these stable snake_case codes (never a
/// C# enum member name). A review is born <see cref="PendingModeration"/> and is <b>never public</b> until an
/// admin/AI transition moves it to <see cref="Published"/>. Only <see cref="Published"/> reviews are rendered
/// publicly and only <see cref="Published"/> reviews count toward the nurse aggregate — which is recomputed
/// from source on <b>every</b> transition so hiding a low rating never leaves a stale, inflated average.
/// </summary>
public static class ReviewModerationStatus
{
    /// <summary>Default on submit. Not public, not counted in the aggregate.</summary>
    public const string PendingModeration = "pending_moderation";

    /// <summary>Approved and publicly visible. The only status counted in the nurse aggregate.</summary>
    public const string Published = "published";

    /// <summary>Withheld from the public list (e.g. off-topic, abusive) — removed from the aggregate.</summary>
    public const string Hidden = "hidden";

    /// <summary>Rejected outright (e.g. fake/spam) — never public, not counted.</summary>
    public const string Rejected = "rejected";

    public static readonly IReadOnlyList<string> All = [PendingModeration, Published, Hidden, Rejected];

    public static bool IsValid(string status) => All.Contains(status);
}

/// <summary>The moderator action codes accepted by the moderation endpoint, mapped to a target status.</summary>
public static class ReviewModerationAction
{
    public const string Publish = "publish";
    public const string Hide = "hide";
    public const string Reject = "reject";

    /// <summary>Pull a published review back to <see cref="ReviewModerationStatus.PendingModeration"/> — it
    /// leaves the public list and the aggregate is recomputed downward.</summary>
    public const string Unpublish = "unpublish";

    public static readonly IReadOnlyList<string> All = [Publish, Hide, Reject, Unpublish];

    /// <summary>Maps an action to its resulting <see cref="ReviewModerationStatus"/>, or null if unknown.</summary>
    public static string? ToStatus(string action) => action switch
    {
        Publish => ReviewModerationStatus.Published,
        Hide => ReviewModerationStatus.Hidden,
        Reject => ReviewModerationStatus.Rejected,
        Unpublish => ReviewModerationStatus.PendingModeration,
        _ => null
    };

    /// <summary>Hide and reject must carry a reason; publish/unpublish need none.</summary>
    public static bool RequiresReason(string action) => action is Hide or Reject;
}
