using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; namespace QuestionsApi.Models; public sealed class UserStudyProfile { [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string? Id { get; set; } public string UserId { get; set; } = ""; public DateTime? TargetExamDate { get; set; } public string PreparationStage { get; set; } = "pre_dedicated"; public int WeeklyGoalHours { get; set; } = 10; public string PreferredStudyMode { get; set; } = "mixed"; public double QuestionTextScale { get; set; } = 1.0; public double CcsTextScale { get; set; } = 1.0; public int Revision { get; set; } public DateTime UpdatedUtc { get; set; } = DateTime.UtcNow; } public sealed class UpdateUserStudyProfileRequest { public DateTime? TargetExamDate { get; set; } public string PreparationStage { get; set; } = "pre_dedicated"; public int WeeklyGoalHours { get; set; } = 10; public string PreferredStudyMode { get; set; } = "mixed"; } public sealed class UpdateTextScaleRequest { public double? QuestionTextScale { get; set; } public double? CcsTextScale { get; set; } } public sealed class DeletedUserTombstone { [BsonId] public string UserId { get; set; } = ""; public DateTime DeletedUtc { get; set; } = DateTime.UtcNow; } public static class UserStudyProfileValidator { private static readonly HashSet Stages = ["pre_dedicated", "dedicated", "final_review"]; private static readonly HashSet Goals = [5, 10, 15, 20, 25]; private static readonly HashSet Modes = ["mixed", "question_bank", "ccs", "exam_simulation"]; public static string? Validate(UpdateUserStudyProfileRequest request) { if (!Stages.Contains(request.PreparationStage)) return "Invalid preparation stage."; if (!Goals.Contains(request.WeeklyGoalHours)) return "Weekly goal must be 5, 10, 15, 20, or 25 hours."; if (!Modes.Contains(request.PreferredStudyMode)) return "Invalid preferred study mode."; if (request.TargetExamDate?.Kind == DateTimeKind.Local) request.TargetExamDate = request.TargetExamDate.Value.ToUniversalTime(); return null; } } public static class UpdateTextScaleRequestValidator { private const double Min = 0.85; private const double Max = 1.35; public static string? Validate(UpdateTextScaleRequest request) { if (request.QuestionTextScale is { } questionScale && (questionScale < Min || questionScale > Max)) return "Question text scale must be between 0.85 and 1.35."; if (request.CcsTextScale is { } ccsScale && (ccsScale < Min || ccsScale > Max)) return "CCS text scale must be between 0.85 and 1.35."; return null; } }