namespace Domain.Ports.Repositories;

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

public interface IStudentRepository
{
    Task<Student?> GetByIdAsync(int id, CancellationToken ct = default);
    Task<Student?> GetByIdWithEnrollmentsAsync(int id, CancellationToken ct = default);
    Task<IReadOnlyList<Student>> GetAllAsync(CancellationToken ct = default);
    Task<IReadOnlyList<Student>> GetAllWithEnrollmentsAsync(CancellationToken ct = default);
    Task<bool> ExistsAsync(int id, CancellationToken ct = default);
    Task<bool> EmailExistsAsync(string email, int? excludeId = null, CancellationToken ct = default);

    // Projection support for optimized queries
    Task<IReadOnlyList<TResult>> GetAllProjectedAsync<TResult>(
        Expression<Func<Student, TResult>> selector,
        CancellationToken ct = default);
    Task<TResult?> GetByIdProjectedAsync<TResult>(
        int id,
        Expression<Func<Student, TResult>> selector,
        CancellationToken ct = default);

    // Keyset pagination (more efficient than OFFSET)
    Task<(IReadOnlyList<TResult> Items, int? NextCursor, int TotalCount)> GetPagedProjectedAsync<TResult>(
        Expression<Func<Student, TResult>> selector,
        int? afterId = null,
        int pageSize = 10,
        CancellationToken ct = default);

    void Add(Student student);
    void Update(Student student);
    void Delete(Student student);
}
