using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; namespace QuestionsApi.Models; public static class DonationStatus { public const string Pending = "pending"; public const string Paid = "paid"; public const string Failed = "failed"; public const string Expired = "expired"; } public sealed class Donation { [BsonId, BsonRepresentation(BsonType.ObjectId)] public string? Id { get; set; } public string UserId { get; set; } = ""; public long AmountCents { get; set; } public string Currency { get; set; } = "usd"; public string Status { get; set; } = DonationStatus.Pending; [BsonIgnoreIfNull] public string? StripeCheckoutSessionId { get; set; } public string StripePaymentIntentId { get; set; } = ""; public string LastStripeEventId { get; set; } = ""; public string FailureCode { get; set; } = ""; public DateTime CreatedUtc { get; set; } = DateTime.UtcNow; public DateTime UpdatedUtc { get; set; } = DateTime.UtcNow; public DateTime? PaidUtc { get; set; } } public sealed class CreateDonationCheckoutRequest { public long AmountCents { get; set; } } public sealed class DonationCheckoutResponse { public string DonationId { get; set; } = ""; public string CheckoutUrl { get; set; } = ""; public long AmountCents { get; set; } public string Currency { get; set; } = "usd"; public string Status { get; set; } = DonationStatus.Pending; } public sealed class DonationStatusResponse { public string DonationId { get; set; } = ""; public long AmountCents { get; set; } public string Currency { get; set; } = "usd"; public string Status { get; set; } = DonationStatus.Pending; public DateTime CreatedUtc { get; set; } public DateTime? PaidUtc { get; set; } public static DonationStatusResponse FromModel(Donation donation) => new() { DonationId = donation.Id ?? "", AmountCents = donation.AmountCents, Currency = donation.Currency, Status = donation.Status, CreatedUtc = donation.CreatedUtc, PaidUtc = donation.PaidUtc }; } public static class DonationValidator { public const long MinimumAmountCents = 500; public const long MaximumAmountCents = 1_000_000; public static string? ValidateAmount(long amountCents) => amountCents switch { < MinimumAmountCents => "amountCents must be at least 500", > MaximumAmountCents => "amountCents must be no more than 1000000", _ => null }; }