using System;
using System.Linq;
using API.Data.Misc;
using API.Entities;
using API.Entities.Enums;
using API.Entities.Metadata;
using API.Entities.Person;
namespace API.Extensions.QueryExtensions;
#nullable enable
/// 
/// Responsible for restricting Entities based on an AgeRestriction
/// 
public static class RestrictByAgeExtensions
{
    public static IQueryable RestrictAgainstAgeRestriction(this IQueryable queryable, AgeRestriction restriction)
    {
        if (restriction.AgeRating == AgeRating.NotApplicable) return queryable;
        var q = queryable.Where(s => s.Metadata.AgeRating <= restriction.AgeRating);
        if (!restriction.IncludeUnknowns)
        {
            return q.Where(s => s.Metadata.AgeRating != AgeRating.Unknown);
        }
        return q;
    }
    public static IQueryable RestrictAgainstAgeRestriction(this IQueryable queryable, AgeRestriction restriction)
    {
        if (restriction.AgeRating == AgeRating.NotApplicable) return queryable;
        var q = queryable.Where(s => s.SeriesMetadata.AgeRating <= restriction.AgeRating);
        if (!restriction.IncludeUnknowns)
        {
            return q.Where(s => s.SeriesMetadata.AgeRating != AgeRating.Unknown);
        }
        return q;
    }
    public static IQueryable RestrictAgainstAgeRestriction(this IQueryable queryable, AgeRestriction restriction)
    {
        if (restriction.AgeRating == AgeRating.NotApplicable) return queryable;
        var q = queryable.Where(chapter => chapter.Volume.Series.Metadata.AgeRating <= restriction.AgeRating);
        if (!restriction.IncludeUnknowns)
        {
            return q.Where(s => s.Volume.Series.Metadata.AgeRating != AgeRating.Unknown);
        }
        return q;
    }
    public static IQueryable RestrictAgainstAgeRestriction(this IQueryable queryable, AgeRestriction restriction)
    {
        if (restriction.AgeRating == AgeRating.NotApplicable) return queryable;
        var q = queryable.Where(cp => cp.Chapter.Volume.Series.Metadata.AgeRating <= restriction.AgeRating);
        if (!restriction.IncludeUnknowns)
        {
            return q.Where(cp => cp.Chapter.Volume.Series.Metadata.AgeRating != AgeRating.Unknown);
        }
        return q;
    }
    public static IQueryable RestrictAgainstAgeRestriction(this IQueryable queryable, AgeRestriction restriction)
    {
        if (restriction.AgeRating == AgeRating.NotApplicable) return queryable;
        if (restriction.IncludeUnknowns)
        {
            return queryable.Where(c => c.Items.All(sm =>
                sm.Metadata.AgeRating <= restriction.AgeRating));
        }
        return queryable.Where(c => c.Items.All(sm =>
            sm.Metadata.AgeRating <= restriction.AgeRating && sm.Metadata.AgeRating > AgeRating.Unknown));
    }
    /// 
    /// Returns all Genres where any of the linked Series/Chapters are less than or equal to restriction age rating
    /// 
    /// 
    /// 
    /// 
    public static IQueryable RestrictAgainstAgeRestriction(this IQueryable queryable, AgeRestriction restriction)
    {
        if (restriction.AgeRating == AgeRating.NotApplicable) return queryable;
        if (restriction.IncludeUnknowns)
        {
            return queryable.Where(c =>
                c.SeriesMetadatas.Any(sm => sm.AgeRating <= restriction.AgeRating) ||
                c.Chapters.Any(cp => cp.AgeRating <= restriction.AgeRating));
        }
        return queryable.Where(c =>
            c.SeriesMetadatas.Any(sm => sm.AgeRating <= restriction.AgeRating && sm.AgeRating != AgeRating.Unknown) ||
            c.Chapters.Any(cp => cp.AgeRating <= restriction.AgeRating && cp.AgeRating != AgeRating.Unknown)
        );
    }
    public static IQueryable RestrictAgainstAgeRestriction(this IQueryable queryable, AgeRestriction restriction)
    {
        if (restriction.AgeRating == AgeRating.NotApplicable) return queryable;
        if (restriction.IncludeUnknowns)
        {
            return queryable.Where(c =>
                c.SeriesMetadatas.Any(sm => sm.AgeRating <= restriction.AgeRating) ||
                c.Chapters.Any(cp => cp.AgeRating <= restriction.AgeRating));
        }
        return queryable.Where(c =>
            c.SeriesMetadatas.Any(sm => sm.AgeRating <= restriction.AgeRating && sm.AgeRating != AgeRating.Unknown) ||
            c.Chapters.Any(cp => cp.AgeRating <= restriction.AgeRating && cp.AgeRating != AgeRating.Unknown)
        );
    }
    public static IQueryable RestrictAgainstAgeRestriction(this IQueryable queryable, AgeRestriction restriction)
    {
        if (restriction.AgeRating == AgeRating.NotApplicable) return queryable;
        if (restriction.IncludeUnknowns)
        {
            return queryable.Where(c =>
                c.SeriesMetadataPeople.Any(sm => sm.SeriesMetadata.AgeRating <= restriction.AgeRating) ||
                c.ChapterPeople.Any(cp => cp.Chapter.AgeRating <= restriction.AgeRating));
        }
        return queryable.Where(c =>
            c.SeriesMetadataPeople.Any(sm => sm.SeriesMetadata.AgeRating <= restriction.AgeRating && sm.SeriesMetadata.AgeRating != AgeRating.Unknown) ||
            c.ChapterPeople.Any(cp => cp.Chapter.AgeRating <= restriction.AgeRating && cp.Chapter.AgeRating != AgeRating.Unknown)
        );
    }
    public static IQueryable RestrictAgainstAgeRestriction(this IQueryable queryable, AgeRestriction restriction)
    {
        if (restriction.AgeRating == AgeRating.NotApplicable) return queryable;
        var q = queryable.Where(rl => rl.AgeRating <= restriction.AgeRating);
        if (!restriction.IncludeUnknowns)
        {
            return q.Where(rl => rl.AgeRating != AgeRating.Unknown);
        }
        return q;
    }
}