namespace Domain.Ports.Repositories;

using Domain.Entities;
using System.Linq.Expressions;

/// <summary>
/// Repository interface for subject persistence operations.
/// </summary>
public interface ISubjectRepository
{
    /// <summary>
    /// Gets a subject by ID without related entities.
    /// </summary>
    Task<Subject?> GetByIdAsync(int id, CancellationToken ct = default);

    /// <summary>
    /// Gets a subject by ID with its professor.
    /// </summary>
    Task<Subject?> GetByIdWithProfessorAsync(int id, CancellationToken ct = default);

    /// <summary>
    /// Gets all subjects without related entities.
    /// </summary>
    Task<IReadOnlyList<Subject>> GetAllAsync(CancellationToken ct = default);

    /// <summary>
    /// Gets all subjects with their professors.
    /// </summary>
    Task<IReadOnlyList<Subject>> GetAllWithProfessorsAsync(CancellationToken ct = default);

    /// <summary>
    /// Gets subjects available for a student (not enrolled, no professor conflict).
    /// </summary>
    Task<IReadOnlyList<Subject>> GetAvailableForStudentAsync(int studentId, CancellationToken ct = default);

    /// <summary>
    /// Gets all subjects with custom projection to avoid over-fetching.
    /// </summary>
    Task<IReadOnlyList<TResult>> GetAllProjectedAsync<TResult>(
        Expression<Func<Subject, TResult>> selector,
        CancellationToken ct = default);
}
