using GermanApp.Domain.Entities; using GermanApp.Domain.Interfaces; using GermanApp.Infrastructure.Data.DbContext; using Microsoft.EntityFrameworkCore; namespace GermanApp.Infrastructure.Data.Repositories; /// /// Entity Framework Core implementation of IQuizQuestionRepository. /// This is part of the Infrastructure layer. /// public class QuizQuestionRepository : IQuizQuestionRepository { private readonly AppDbContext _context; public QuizQuestionRepository(AppDbContext context) { _context = context; } public async Task GetByIdAsync(int id, CancellationToken cancellationToken = default) { return await _context.QuizQuestions .Include(q => q.Quiz) .ThenInclude(q => q.Lesson) .Include(q => q.Options.OrderBy(o => o.Order)) .FirstOrDefaultAsync(q => q.Id == id, cancellationToken); } public async Task> GetAllAsync(CancellationToken cancellationToken = default) { return await _context.QuizQuestions .Include(q => q.Quiz) .ThenInclude(q => q.Lesson) .Include(q => q.Options) .AsNoTracking() .ToListAsync(cancellationToken); } public async Task AddAsync(QuizQuestion entity, CancellationToken cancellationToken = default) { await _context.QuizQuestions.AddAsync(entity, cancellationToken); await _context.SaveChangesAsync(cancellationToken); return entity; } public async Task UpdateAsync(QuizQuestion entity, CancellationToken cancellationToken = default) { _context.QuizQuestions.Update(entity); await _context.SaveChangesAsync(cancellationToken); } public async Task DeleteAsync(QuizQuestion entity, CancellationToken cancellationToken = default) { _context.QuizQuestions.Remove(entity); await _context.SaveChangesAsync(cancellationToken); } public async Task ExistsAsync(int id, CancellationToken cancellationToken = default) { return await _context.QuizQuestions .AnyAsync(q => q.Id == id, cancellationToken); } public async Task> GetByLessonAsync(int lessonId, CancellationToken cancellationToken = default) { return await _context.QuizQuestions .Include(q => q.Quiz) .ThenInclude(q => q.Lesson) .Include(q => q.Options.OrderBy(o => o.Order)) .Where(q => q.Quiz != null && q.Quiz.LessonId == lessonId) .OrderBy(q => q.Order) .AsNoTracking() .ToListAsync(cancellationToken); } public async Task> GetAllOrderedAsync(CancellationToken cancellationToken = default) { return await _context.QuizQuestions .Include(q => q.Quiz) .ThenInclude(q => q.Lesson) .Include(q => q.Options.OrderBy(o => o.Order)) .OrderBy(q => q.Quiz.Lesson.Order) .ThenBy(q => q.Quiz.Id) .ThenBy(q => q.Order) .AsNoTracking() .ToListAsync(cancellationToken); } public async Task> GetActiveByLessonAsync(int lessonId, CancellationToken cancellationToken = default) { return await _context.QuizQuestions .Include(q => q.Quiz) .ThenInclude(q => q.Lesson) .Include(q => q.Options.OrderBy(o => o.Order)) .Where(q => q.Quiz != null && q.Quiz.LessonId == lessonId && q.IsActive) .OrderBy(q => q.Order) .AsNoTracking() .ToListAsync(cancellationToken); } public async Task> GetRandomQuestionsForLessonAsync(int lessonId, int count, CancellationToken cancellationToken = default) { return await _context.QuizQuestions .Include(q => q.Quiz) .ThenInclude(q => q.Lesson) .Include(q => q.Options.OrderBy(o => o.Order)) .Where(q => q.Quiz != null && q.Quiz.LessonId == lessonId && q.IsActive) .OrderBy(q => Guid.NewGuid()) // Random ordering .Take(count) .AsNoTracking() .ToListAsync(cancellationToken); } public async Task> GetByDifficultyAsync(int difficulty, CancellationToken cancellationToken = default) { return await _context.QuizQuestions .Include(q => q.Quiz) .Include(q => q.Options) .Where(q => q.Difficulty == difficulty) .OrderBy(q => q.Order) .AsNoTracking() .ToListAsync(cancellationToken); } public async Task> GetByTypeAsync(QuestionType type, CancellationToken cancellationToken = default) { return await _context.QuizQuestions .Include(q => q.Quiz) .Include(q => q.Options) .Where(q => q.Type == type) .OrderBy(q => q.Order) .AsNoTracking() .ToListAsync(cancellationToken); } public async Task OrderExistsInLessonAsync(int lessonId, int order, int? excludeId = null, CancellationToken cancellationToken = default) { var query = _context.QuizQuestions .Where(q => q.Quiz != null && q.Quiz.LessonId == lessonId && q.Order == order); if (excludeId.HasValue) { query = query.Where(q => q.Id != excludeId.Value); } return await query.AnyAsync(cancellationToken); } // ============================================ // Quiz-based methods (QuizId) // ============================================ public async Task> GetByQuizAsync(int quizId, CancellationToken cancellationToken = default) { return await _context.QuizQuestions .Include(q => q.Quiz) .Include(q => q.Options.OrderBy(o => o.Order)) .Where(q => q.QuizId == quizId) .OrderBy(q => q.Order) .AsNoTracking() .ToListAsync(cancellationToken); } public async Task> GetActiveByQuizAsync(int quizId, CancellationToken cancellationToken = default) { return await _context.QuizQuestions .Include(q => q.Quiz) .Include(q => q.Options.OrderBy(o => o.Order)) .Where(q => q.QuizId == quizId && q.IsActive) .OrderBy(q => q.Order) .AsNoTracking() .ToListAsync(cancellationToken); } public async Task> GetByQuizWithOptionsAsync(int quizId, CancellationToken cancellationToken = default) { return await _context.QuizQuestions .Include(q => q.Quiz) .Include(q => q.Options.OrderBy(o => o.Order)) .Where(q => q.QuizId == quizId) .OrderBy(q => q.Order) .AsNoTracking() .ToListAsync(cancellationToken); } public async Task> GetRandomQuestionsForQuizAsync(int quizId, int count, CancellationToken cancellationToken = default) { return await _context.QuizQuestions .Include(q => q.Quiz) .Include(q => q.Options.OrderBy(o => o.Order)) .Where(q => q.QuizId == quizId && q.IsActive) .OrderBy(q => Guid.NewGuid()) // Random ordering .Take(count) .AsNoTracking() .ToListAsync(cancellationToken); } public async Task GetTotalPointsForQuizAsync(int quizId, CancellationToken cancellationToken = default) { var questions = await _context.QuizQuestions .Where(q => q.QuizId == quizId && q.IsActive) .Select(q => q.Points) .ToListAsync(cancellationToken); return questions.Sum(); } public async Task OrderExistsInQuizAsync(int quizId, int order, int? excludeId = null, CancellationToken cancellationToken = default) { var query = _context.QuizQuestions .Where(q => q.QuizId == quizId && q.Order == order); if (excludeId.HasValue) { query = query.Where(q => q.Id != excludeId.Value); } return await query.AnyAsync(cancellationToken); } }