namespace adas_core.Domain.Models.Filter;

public record PaginationFilter
{
    public PaginationFilter()
    {
    }

    public PaginationFilter(int pageNumber, int pageSize, FilteredRequest? filtered)
    {
        PageNumber = pageNumber < 1 ? 1 : pageNumber;
        PageSize = pageSize <= 0 ? 100 : pageSize;
        FilteredRequest = filtered;
    }

    public int PageNumber { get; set; } = 1;
    public int PageSize { get; set; } = 100;
    public FilteredRequest? FilteredRequest { get; set; }

    /// <summary>
    /// Determines whether the pagination state is considered empty by checking if both <c>PageNumber</c> and <c>PageSize</c> are less than or equal to zero.
    /// </summary>
    /// <returns><c>true</c> if both <c>PageNumber</c> and <c>PageSize</c> are less than or equal to zero; otherwise, <c>false</c>.</returns>
    public bool IsEmpty()
        {
            return PageNumber <= 0 && PageSize <= 0;
        }
}

/// <summary>
/// Provides static extension methods for working with pagination filter objects.
/// </summary>
public static class PaginationFilterExtensions
{
    /// <summary>
    /// Applies pagination to the source queryable using the provided <see cref="PaginationFilter"/>, skipping the appropriate number of records and taking the requested page size. If the filter is <c>null</c> or contains an invalid page number (less than 0) or page size (not greater than 0), the original queryable is returned unchanged.
    /// </summary>
    /// <param name="queryable">The source <see cref="IQueryable{T}"/> to paginate.</param>
    /// <param name="filter">The pagination settings containing the page number and page size. If <c>null</c> or invalid, no pagination is applied.</param>
    /// <returns>The paginated <see cref="IQueryable{T}"/>, or the original queryable when the filter is <c>null</c> or contains invalid values.</returns>
    public static IQueryable<T> ApplyPagination<T>(this IQueryable<T> queryable, PaginationFilter? filter)
        {
            var modifQueryable = queryable;
            if (filter is not { PageNumber: >= 0, PageSize: > 0 }) return modifQueryable;
            var pageNumber = filter.PageNumber;
            var pageSize = filter.PageSize;
            modifQueryable = modifQueryable
                    .Skip((pageNumber - 1) * pageSize)
                    .Take(pageSize)
                ;
    
            return modifQueryable;
        }
}