using Health.Application.Exercises;

namespace Health.Infrastructure.Exercises;

public sealed class EfExerciseRepository(AppDbContext db) : IExerciseRepository
{
    private readonly AppDbContext _db = db;

    public async Task<IReadOnlyList<ExercisePlan>> ListActiveOnAsync(Guid userId, DateOnly date, CancellationToken ct) =>
        await _db.ExercisePlans.Include(p => p.Items)
            .Where(p => p.UserId == userId && p.StartDate <= date && p.EndDate >= date)
            .OrderByDescending(p => p.StartDate)
            .ToListAsync(ct);

    public async Task<IReadOnlyList<ExercisePlan>> ListAsync(Guid userId, int limit, CancellationToken ct) =>
        await _db.ExercisePlans.Include(p => p.Items)
            .Where(p => p.UserId == userId)
            .OrderByDescending(p => p.StartDate)
            .Take(limit)
            .ToListAsync(ct);

    public Task<ExercisePlan?> GetOwnedPlanAsync(Guid userId, Guid planId, CancellationToken ct) =>
        _db.ExercisePlans.Include(p => p.Items)
            .FirstOrDefaultAsync(p => p.Id == planId && p.UserId == userId, ct);

    public Task<ExercisePlan?> GetLatestAsync(Guid userId, CancellationToken ct) =>
        _db.ExercisePlans.Include(p => p.Items)
            .Where(p => p.UserId == userId)
            .OrderByDescending(p => p.StartDate)
            .FirstOrDefaultAsync(ct);

    public Task<ExercisePlanItem?> GetOwnedItemAsync(Guid userId, Guid itemId, CancellationToken ct) =>
        _db.ExercisePlanItems.Include(i => i.Plan)
            .FirstOrDefaultAsync(i => i.Id == itemId && i.Plan != null && i.Plan.UserId == userId, ct);

    public async Task AddAsync(ExercisePlan plan, CancellationToken ct) =>
        await _db.ExercisePlans.AddAsync(plan, ct);

    public void Delete(ExercisePlan plan) =>
        _db.ExercisePlans.Remove(plan);

    public Task SaveChangesAsync(CancellationToken ct) =>
        _db.SaveChangesAsync(ct);
}
