using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; namespace QuestionsApi.Models; public static class AccessCatalog { public const int FreeQuestionLimit = 20; public const int CreditEarningLimit = 20; public const int DayPassCreditCost = 100; public static readonly IReadOnlyDictionary Products = new Dictionary(StringComparer.Ordinal) { ["access_day_1"] = new("access_day_1", "One-day QBank token", 100, "usd", AccessGrant.DayToken), ["access_week_1"] = new("access_week_1", "Seven-day QBank token", 500, "usd", AccessGrant.WeekToken), ["access_month_1"] = new("access_month_1", "Thirty-day QBank token", 2000, "usd", AccessGrant.MonthToken), ["exam_token_1"] = new("exam_token_1", "Exam simulation token", 199, "usd", AccessGrant.ExamToken), ["qbank_reset_1"] = new("qbank_reset_1", "QBank reset token", 499, "usd", AccessGrant.ResetToken) }; } public static class AccessGrant { public const string DayToken = "day_token"; public const string WeekToken = "week_token"; public const string MonthToken = "month_token"; public const string ExamToken = "exam_token"; public const string ResetToken = "reset_token"; } public sealed record AccessProduct(string Sku, string Name, long AmountCents, string Currency, string Grant); public sealed class AccessEvent { public string Id { get; set; } = ""; public string SubjectId { get; set; } = ""; public DateTime CreatedUtc { get; set; } } public sealed class UserAccessAccount { [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string? Id { get; set; } public string UserId { get; set; } = ""; public int Credits { get; set; } public int DayTokens { get; set; } public int WeekTokens { get; set; } public int MonthTokens { get; set; } public int ExamTokens { get; set; } public int ResetTokens { get; set; } public int BankCycle { get; set; } public DateTime? UnlimitedUntilUtc { get; set; } public List RecentUsage { get; set; } = []; public List RecentCredits { get; set; } = []; public List AppliedOperationIds { get; set; } = []; public int Revision { get; set; } public DateTime UpdatedUtc { get; set; } = DateTime.UtcNow; } public sealed class AccessStatusResponse { public int FreeQuestionLimit { get; set; } = AccessCatalog.FreeQuestionLimit; public int QuestionsUsed { get; set; } public int QuestionsRemaining { get; set; } public DateTime? NextQuestionAvailableUtc { get; set; } public int Credits { get; set; } public int DayPassCreditCost { get; set; } = AccessCatalog.DayPassCreditCost; public int DayTokens { get; set; } public int WeekTokens { get; set; } public int MonthTokens { get; set; } public int ExamTokens { get; set; } public int ResetTokens { get; set; } public int BankCycle { get; set; } public bool Unlimited { get; set; } public DateTime? UnlimitedUntilUtc { get; set; } public List Products { get; set; } = []; } public sealed class ActivateAccessTokenRequest { public string Token { get; set; } = ""; public string OperationId { get; set; } = ""; } public sealed class RedeemCreditsRequest { public string OperationId { get; set; } = ""; } public sealed class ResetQBankRequest { public string Confirmation { get; set; } = ""; public string OperationId { get; set; } = ""; } public sealed class CreateAccessCheckoutRequest { public string Sku { get; set; } = ""; } public sealed class AccessCheckoutResponse { public string PurchaseId { get; set; } = ""; public string CheckoutUrl { get; set; } = ""; public string Sku { get; set; } = ""; public long AmountCents { get; set; } } public static class AccessPurchaseStatus { public const string Pending = "pending"; public const string Paid = "paid"; public const string Failed = "failed"; public const string Expired = "expired"; public const string Refunded = "refunded"; } public sealed class AccessPurchase { [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string? Id { get; set; } public string UserId { get; set; } = ""; public string Sku { get; set; } = ""; public long AmountCents { get; set; } public string Currency { get; set; } = "usd"; public string Status { get; set; } = AccessPurchaseStatus.Pending; public string Provider { get; set; } = "stripe"; public string ProviderSessionId { get; set; } = ""; public string ProviderPaymentId { get; set; } = ""; public List ProviderEventIds { get; set; } = []; public bool GrantApplied { get; set; } public DateTime CreatedUtc { get; set; } = DateTime.UtcNow; public DateTime UpdatedUtc { get; set; } = DateTime.UtcNow; } public sealed class AccessPurchaseStatusResponse { public string PurchaseId { get; set; } = ""; public string Sku { get; set; } = ""; public long AmountCents { get; set; } public string Currency { get; set; } = ""; public string Status { get; set; } = ""; }