using MongoDB.Bson; using MongoDB.Driver; using QuestionsApi.Models; namespace QuestionsApi.Services; public sealed class CcsCaseReportStore { private readonly IMongoCollection _reports; public CcsCaseReportStore(MongoDatabaseProvider mongo) { _reports = mongo.Database.GetCollection("CcsCaseReports"); _reports.Indexes.CreateMany([ new CreateIndexModel(Builders.IndexKeys.Ascending(value => value.Status).Descending(value => value.CreatedUtc)), new CreateIndexModel(Builders.IndexKeys.Ascending(value => value.CaseExternalId)), new CreateIndexModel(Builders.IndexKeys.Ascending(value => value.AttemptId)), new CreateIndexModel(Builders.IndexKeys.Ascending(value => value.UserId)) ]); } public async Task CreateAsync(CcsAttempt attempt, CcsCaseRevision definition, string category, string details) { var now = DateTime.UtcNow; var report = new CcsCaseReport { CaseExternalId = attempt.CaseExternalId, CaseRevisionId = attempt.CaseRevisionId, CaseVersion = attempt.CaseVersion, AttemptId = attempt.Id ?? "", UserId = attempt.UserId, Category = category, Details = details, CaseSnapshot = definition, AttemptSnapshot = attempt, CreatedUtc = now, UpdatedUtc = now }; await _reports.InsertOneAsync(report); return report; } public async Task GetAsync(string id) => ObjectId.TryParse(id, out _) ? await _reports.Find(value => value.Id == id).FirstOrDefaultAsync() : null; public async Task SearchAsync(string status, string category, string caseId, string userId, int skip, int limit) { var filter = Builders.Filter.Empty; if (status != "all") filter &= Builders.Filter.Eq(value => value.Status, status); if (category.Length > 0) filter &= Builders.Filter.Eq(value => value.Category, category); if (caseId.Length > 0) filter &= Builders.Filter.Eq(value => value.CaseExternalId, caseId); if (userId.Length > 0) filter &= Builders.Filter.Eq(value => value.UserId, userId); var reports = await _reports.Find(filter).SortByDescending(value => value.CreatedUtc).Skip(skip).Limit(limit).ToListAsync(); return new CcsCaseReportListResponse { Items = reports.Select(value => new CcsCaseReportSummary { Id = value.Id ?? "", CaseExternalId = value.CaseExternalId, CaseVersion = value.CaseVersion, AttemptId = value.AttemptId, UserId = value.UserId, Category = value.Category, Details = value.Details, Status = value.Status, CreatedUtc = value.CreatedUtc }).ToList(), Total = await _reports.CountDocumentsAsync(filter), Skip = skip, Limit = limit }; } public async Task CloseAsync(string id, string status, string reviewer, string note) { if (!ObjectId.TryParse(id, out _)) return null; var now = DateTime.UtcNow; return await _reports.FindOneAndUpdateAsync( value => value.Id == id && value.Status == QuestionReportStatus.Open, Builders.Update.Set(value => value.Status, status).Set(value => value.ReviewerNote, note) .Set(value => value.ReviewedByUserId, reviewer).Set(value => value.ReviewedUtc, now).Set(value => value.UpdatedUtc, now), new FindOneAndUpdateOptions { ReturnDocument = ReturnDocument.After }); } }