namespace Domain.Ports.Repositories;

using Domain.Entities;
using Domain.ReadModels;

/// <summary>
/// Repository interface for enrollment persistence operations.
/// </summary>
public interface IEnrollmentRepository
{
    /// <summary>
    /// Gets an enrollment by its unique identifier.
    /// </summary>
    Task<Enrollment?> GetByIdAsync(int id, CancellationToken ct = default);

    /// <summary>
    /// Gets an enrollment by student and subject combination.
    /// </summary>
    Task<Enrollment?> GetByStudentAndSubjectAsync(int studentId, int subjectId, CancellationToken ct = default);

    /// <summary>
    /// Gets all enrollments for a specific student with related entities.
    /// </summary>
    Task<IReadOnlyList<Enrollment>> GetByStudentIdAsync(int studentId, CancellationToken ct = default);

    /// <summary>
    /// Gets all enrollments for a specific subject with related entities.
    /// </summary>
    Task<IReadOnlyList<Enrollment>> GetBySubjectIdAsync(int subjectId, CancellationToken ct = default);

    /// <summary>
    /// Gets classmates (other students) enrolled in the same subject.
    /// </summary>
    Task<IReadOnlyList<ClassmateInfo>> GetClassmatesAsync(int studentId, int subjectId, CancellationToken ct = default);

    /// <summary>
    /// Batch query to get classmates for multiple subjects in a single database call.
    /// Eliminates N+1 query problem when loading classmates for all enrolled subjects.
    /// </summary>
    Task<IReadOnlyDictionary<int, IReadOnlyList<ClassmateInfo>>> GetClassmatesBatchAsync(
        int studentId, IEnumerable<int> subjectIds, CancellationToken ct = default);

    /// <summary>
    /// Adds a new enrollment to the context.
    /// </summary>
    void Add(Enrollment enrollment);

    /// <summary>
    /// Removes an enrollment from the context.
    /// </summary>
    void Delete(Enrollment enrollment);
}
