using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
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 IStoryProgressRepository.
/// This is part of the Infrastructure layer.
///
public class StoryProgressRepository : IStoryProgressRepository
{
private readonly AppDbContext _context;
public StoryProgressRepository(AppDbContext context)
{
_context = context;
}
public async Task> GetByUserAndLevelAsync(
int userId,
int levelId,
CancellationToken cancellationToken = default)
{
return await _context.StoryProgress
.Where(p => p.UserId == userId && p.LevelId == levelId)
.Include(p => p.StorySegment)
.OrderBy(p => p.StorySegment != null ? p.StorySegment.Order : 0)
.AsNoTracking()
.ToListAsync(cancellationToken);
}
public async Task GetByUserAndSegmentAsync(
int userId,
int storySegmentId,
CancellationToken cancellationToken = default)
{
return await _context.StoryProgress
.FirstOrDefaultAsync(
p => p.UserId == userId && p.StorySegmentId == storySegmentId,
cancellationToken);
}
public async Task GetHighestUnlockedOrderAsync(
int userId,
int levelId,
CancellationToken cancellationToken = default)
{
var highestOrder = await _context.StoryProgress
.Where(p => p.UserId == userId && p.LevelId == levelId)
.Include(p => p.StorySegment)
.Select(p => p.StorySegment != null ? p.StorySegment.Order : 0)
.MaxAsync(cancellationToken);
return highestOrder ?? 0;
}
public async Task IsSegmentUnlockedAsync(
int userId,
int storySegmentId,
CancellationToken cancellationToken = default)
{
return await _context.StoryProgress
.AnyAsync(
p => p.UserId == userId && p.StorySegmentId == storySegmentId,
cancellationToken);
}
public async Task IsSegmentCompletedAsync(
int userId,
int storySegmentId,
CancellationToken cancellationToken = default)
{
return await _context.StoryProgress
.AnyAsync(
p => p.UserId == userId
&& p.StorySegmentId == storySegmentId
&& p.IsCompleted,
cancellationToken);
}
public async Task AddAsync(StoryProgress progress, CancellationToken cancellationToken = default)
{
await _context.StoryProgress.AddAsync(progress, cancellationToken);
await _context.SaveChangesAsync(cancellationToken);
return progress;
}
public async Task UpdateAsync(StoryProgress progress, CancellationToken cancellationToken = default)
{
_context.StoryProgress.Update(progress);
await _context.SaveChangesAsync(cancellationToken);
}
public async Task GetTotalSegmentsForLevelAsync(int levelId, CancellationToken cancellationToken = default)
{
return await _context.StorySegments
.CountAsync(s => s.LevelId == levelId && s.IsActive, cancellationToken);
}
public async Task GetUnlockedCountAsync(
int userId,
int levelId,
CancellationToken cancellationToken = default)
{
return await _context.StoryProgress
.CountAsync(
p => p.UserId == userId && p.LevelId == levelId,
cancellationToken);
}
public async Task GetCompletedCountAsync(
int userId,
int levelId,
CancellationToken cancellationToken = default)
{
return await _context.StoryProgress
.CountAsync(
p => p.UserId == userId && p.LevelId == levelId && p.IsCompleted,
cancellationToken);
}
}