using System.Linq;
using API.Data.Repositories;
using API.Entities;
using API.Entities.Person;
using Microsoft.EntityFrameworkCore;
namespace API.Extensions.QueryExtensions;
#nullable enable
/// 
/// All extensions against IQueryable that enables the dynamic including based on bitwise flag pattern
/// 
public static class IncludesExtensions
{
    public static IQueryable Includes(this IQueryable queryable,
        CollectionTagIncludes includes)
    {
        if (includes.HasFlag(CollectionTagIncludes.SeriesMetadata))
        {
            queryable = queryable.Include(c => c.SeriesMetadatas);
        }
        if (includes.HasFlag(CollectionTagIncludes.SeriesMetadataWithSeries))
        {
            queryable = queryable.Include(c => c.SeriesMetadatas).ThenInclude(s => s.Series);
        }
        return queryable.AsSplitQuery();
    }
    public static IQueryable Includes(this IQueryable queryable,
        CollectionIncludes includes)
    {
        if (includes.HasFlag(CollectionIncludes.Series))
        {
            queryable = queryable.Include(c => c.Items);
        }
        return queryable.AsSplitQuery();
    }
    public static IQueryable Includes(this IQueryable queryable,
        ChapterIncludes includes)
    {
        if (includes.HasFlag(ChapterIncludes.Volumes))
        {
            queryable = queryable.Include(v => v.Volume);
        }
        if (includes.HasFlag(ChapterIncludes.Files))
        {
            queryable = queryable
                .Include(c => c.Files);
        }
        if (includes.HasFlag(ChapterIncludes.People))
        {
            queryable = queryable
                .Include(c => c.People)
                .ThenInclude(cp => cp.Person);
        }
        if (includes.HasFlag(ChapterIncludes.Genres))
        {
            queryable = queryable
                .Include(c => c.Genres);
        }
        if (includes.HasFlag(ChapterIncludes.Tags))
        {
            queryable = queryable
                .Include(c => c.Tags);
        }
        if (includes.HasFlag(ChapterIncludes.ExternalReviews))
        {
            queryable = queryable
                .Include(c => c.ExternalReviews);
        }
        if (includes.HasFlag(ChapterIncludes.ExternalRatings))
        {
            queryable = queryable
                .Include(c => c.ExternalRatings);
        }
        return queryable.AsSplitQuery();
    }
    public static IQueryable Includes(this IQueryable queryable,
        VolumeIncludes includes)
    {
        if (includes.HasFlag(VolumeIncludes.Files))
        {
            queryable = queryable
                .Include(vol => vol.Chapters)
                .ThenInclude(c => c.Files);
        } else if (includes.HasFlag(VolumeIncludes.Chapters))
        {
            queryable = queryable
                .Include(vol => vol.Chapters);
        }
        if (includes.HasFlag(VolumeIncludes.People))
        {
            queryable = queryable
                .Include(vol => vol.Chapters)
                .ThenInclude(c => c.People);
        }
        if (includes.HasFlag(VolumeIncludes.Tags))
        {
            queryable = queryable
                .Include(vol => vol.Chapters)
                .ThenInclude(c => c.Tags);
        }
        return queryable.AsSplitQuery();
    }
    public static IQueryable Includes(this IQueryable query,
        SeriesIncludes includeFlags)
    {
        if (includeFlags.HasFlag(SeriesIncludes.Library))
        {
            query = query.Include(u => u.Library);
        }
        if (includeFlags.HasFlag(SeriesIncludes.Volumes))
        {
            query = query.Include(s => s.Volumes);
        }
        if (includeFlags.HasFlag(SeriesIncludes.Chapters))
        {
            query = query
                .Include(s => s.Volumes)
                .ThenInclude(v => v.Chapters.OrderBy(c => c.SortOrder));
        }
        if (includeFlags.HasFlag(SeriesIncludes.Related))
        {
            query = query.Include(s => s.Relations)
                .ThenInclude(r => r.TargetSeries)
                .Include(s => s.RelationOf);
        }
        if (includeFlags.HasFlag(SeriesIncludes.ExternalReviews))
        {
            query = query
                .Include(s => s.ExternalSeriesMetadata)
                .ThenInclude(s => s.ExternalReviews);
        }
        if (includeFlags.HasFlag(SeriesIncludes.ExternalRatings))
        {
            query = query
                .Include(s => s.ExternalSeriesMetadata)
                .ThenInclude(s => s.ExternalRatings);
        }
        if (includeFlags.HasFlag(SeriesIncludes.ExternalMetadata))
        {
            query = query
                .Include(s => s.ExternalSeriesMetadata);
        }
        if (includeFlags.HasFlag(SeriesIncludes.ExternalRecommendations))
        {
            query = query
                .Include(s => s.ExternalSeriesMetadata)
                .ThenInclude(s => s.ExternalRecommendations);
        }
        if (includeFlags.HasFlag(SeriesIncludes.Metadata))
        {
            query = query
                .Include(s => s.Metadata)
                .ThenInclude(m => m.Genres.OrderBy(g => g.NormalizedTitle))
                .Include(s => s.Metadata)
                .ThenInclude(m => m.People)
                .ThenInclude(smp => smp.Person)
                .Include(s => s.Metadata)
                .ThenInclude(m => m.Tags.OrderBy(g => g.NormalizedTitle));
        }
        return query.AsSplitQuery();
    }
    public static IQueryable Includes(this IQueryable query, AppUserIncludes includeFlags)
    {
        if (includeFlags.HasFlag(AppUserIncludes.Bookmarks))
        {
            query = query.Include(u => u.Bookmarks);
        }
        if (includeFlags.HasFlag(AppUserIncludes.Progress))
        {
            query = query.Include(u => u.Progresses);
        }
        if (includeFlags.HasFlag(AppUserIncludes.ReadingLists))
        {
            query = query.Include(u => u.ReadingLists);
        }
        if (includeFlags.HasFlag(AppUserIncludes.ReadingListsWithItems))
        {
            query = query.Include(u => u.ReadingLists)
                .ThenInclude(r => r.Items);
        }
        if (includeFlags.HasFlag(AppUserIncludes.Ratings))
        {
            query = query.Include(u => u.Ratings);
        }
        if (includeFlags.HasFlag(AppUserIncludes.UserPreferences))
        {
            query = query
                .Include(u => u.UserPreferences)
                .ThenInclude(p => p.Theme);
        }
        if (includeFlags.HasFlag(AppUserIncludes.WantToRead))
        {
            query = query.Include(u => u.WantToRead);
        }
        if (includeFlags.HasFlag(AppUserIncludes.Devices))
        {
            query = query.Include(u => u.Devices);
        }
        if (includeFlags.HasFlag(AppUserIncludes.ScrobbleHolds))
        {
            query = query.Include(u => u.ScrobbleHolds);
        }
        if (includeFlags.HasFlag(AppUserIncludes.SmartFilters))
        {
            query = query.Include(u => u.SmartFilters);
        }
        if (includeFlags.HasFlag(AppUserIncludes.DashboardStreams))
        {
            query = query.Include(u => u.DashboardStreams)
                .ThenInclude(s => s.SmartFilter);
        }
        if (includeFlags.HasFlag(AppUserIncludes.SideNavStreams))
        {
            query = query.Include(u => u.SideNavStreams)
                .ThenInclude(s => s.SmartFilter);
        }
        if (includeFlags.HasFlag(AppUserIncludes.ExternalSources))
        {
            query = query.Include(u => u.ExternalSources);
        }
        if (includeFlags.HasFlag(AppUserIncludes.Collections))
        {
            query = query.Include(u => u.Collections)
                .ThenInclude(c => c.Items);
        }
        if (includeFlags.HasFlag(AppUserIncludes.ChapterRatings))
        {
            query = query.Include(u => u.ChapterRatings);
        }
        return query.AsSplitQuery();
    }
    public static IQueryable Includes(this IQueryable queryable,
        ReadingListIncludes includes)
    {
        if (includes.HasFlag(ReadingListIncludes.Items))
        {
            queryable = queryable.Include(r => r.Items.OrderBy(item => item.Order));
        }
        if (includes.HasFlag(ReadingListIncludes.ItemChapter))
        {
            queryable = queryable
                .Include(r => r.Items.OrderBy(item => item.Order))
                .ThenInclude(ri => ri.Chapter);
        }
        return queryable.AsSplitQuery();
    }
    public static IQueryable Includes(this IQueryable query, LibraryIncludes includeFlags)
    {
        if (includeFlags.HasFlag(LibraryIncludes.Folders))
        {
            query = query.Include(l => l.Folders);
        }
        if (includeFlags.HasFlag(LibraryIncludes.FileTypes))
        {
            query = query.Include(l => l.LibraryFileTypes);
        }
        if (includeFlags.HasFlag(LibraryIncludes.Series))
        {
            query = query.Include(l => l.Series);
        }
        if (includeFlags.HasFlag(LibraryIncludes.AppUser))
        {
            query = query.Include(l => l.AppUsers);
        }
        if (includeFlags.HasFlag(LibraryIncludes.ExcludePatterns))
        {
            query = query.Include(l => l.LibraryExcludePatterns);
        }
        return query.AsSplitQuery();
    }
    public static IQueryable Includes(this IQueryable queryable, PersonIncludes includeFlags)
    {
        if (includeFlags.HasFlag(PersonIncludes.Aliases))
        {
            queryable = queryable.Include(p => p.Aliases);
        }
        if (includeFlags.HasFlag(PersonIncludes.ChapterPeople))
        {
            queryable = queryable.Include(p => p.ChapterPeople);
        }
        if (includeFlags.HasFlag(PersonIncludes.SeriesPeople))
        {
            queryable = queryable.Include(p => p.SeriesMetadataPeople);
        }
        return queryable;
    }
}