using System;
using System.Linq;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace Jellyfin.Api.Controllers;
/// 
/// Filters controller.
/// 
[Route("")]
[Authorize]
public class FilterController : BaseJellyfinApiController
{
    private readonly ILibraryManager _libraryManager;
    private readonly IUserManager _userManager;
    /// 
    /// Initializes a new instance of the  class.
    /// 
    /// Instance of the  interface.
    /// Instance of the  interface.
    public FilterController(ILibraryManager libraryManager, IUserManager userManager)
    {
        _libraryManager = libraryManager;
        _userManager = userManager;
    }
    /// 
    /// Gets legacy query filters.
    /// 
    /// Optional. User id.
    /// Optional. Parent id.
    /// Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited.
    /// Optional. Filter by MediaType. Allows multiple, comma delimited.
    /// Legacy filters retrieved.
    /// Legacy query filters.
    [HttpGet("Items/Filters")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public ActionResult GetQueryFiltersLegacy(
        [FromQuery] Guid? userId,
        [FromQuery] Guid? parentId,
        [FromQuery, ModelBinder(typeof(CommaDelimitedCollectionModelBinder))] BaseItemKind[] includeItemTypes,
        [FromQuery, ModelBinder(typeof(CommaDelimitedCollectionModelBinder))] MediaType[] mediaTypes)
    {
        userId = RequestHelpers.GetUserId(User, userId);
        var user = userId.IsNullOrEmpty()
            ? null
            : _userManager.GetUserById(userId.Value);
        BaseItem? item = null;
        if (includeItemTypes.Length != 1
            || !(includeItemTypes[0] == BaseItemKind.BoxSet
                 || includeItemTypes[0] == BaseItemKind.Playlist
                 || includeItemTypes[0] == BaseItemKind.Trailer
                 || includeItemTypes[0] == BaseItemKind.Program))
        {
            item = _libraryManager.GetParentItem(parentId, user?.Id);
        }
        var query = new InternalItemsQuery
        {
            User = user,
            MediaTypes = mediaTypes,
            IncludeItemTypes = includeItemTypes,
            Recursive = true,
            EnableTotalRecordCount = false,
            DtoOptions = new DtoOptions
            {
                Fields = new[] { ItemFields.Genres, ItemFields.Tags },
                EnableImages = false,
                EnableUserData = false
            }
        };
        if (item is not Folder folder)
        {
            return new QueryFiltersLegacy();
        }
        var itemList = folder.GetItemList(query);
        return new QueryFiltersLegacy
        {
            Years = itemList.Select(i => i.ProductionYear ?? -1)
                .Where(i => i > 0)
                .Distinct()
                .Order()
                .ToArray(),
            Genres = itemList.SelectMany(i => i.Genres)
                .DistinctNames()
                .Order()
                .ToArray(),
            Tags = itemList
                .SelectMany(i => i.Tags)
                .Distinct(StringComparer.OrdinalIgnoreCase)
                .Order()
                .ToArray(),
            OfficialRatings = itemList
                .Select(i => i.OfficialRating)
                .Where(i => !string.IsNullOrWhiteSpace(i))
                .Distinct(StringComparer.OrdinalIgnoreCase)
                .Order()
                .ToArray()
        };
    }
    /// 
    /// Gets query filters.
    /// 
    /// Optional. User id.
    /// Optional. Specify this to localize the search to a specific item or folder. Omit to use the root.
    /// Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited.
    /// Optional. Is item airing.
    /// Optional. Is item movie.
    /// Optional. Is item sports.
    /// Optional. Is item kids.
    /// Optional. Is item news.
    /// Optional. Is item series.
    /// Optional. Search recursive.
    /// Filters retrieved.
    /// Query filters.
    [HttpGet("Items/Filters2")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public ActionResult GetQueryFilters(
        [FromQuery] Guid? userId,
        [FromQuery] Guid? parentId,
        [FromQuery, ModelBinder(typeof(CommaDelimitedCollectionModelBinder))] BaseItemKind[] includeItemTypes,
        [FromQuery] bool? isAiring,
        [FromQuery] bool? isMovie,
        [FromQuery] bool? isSports,
        [FromQuery] bool? isKids,
        [FromQuery] bool? isNews,
        [FromQuery] bool? isSeries,
        [FromQuery] bool? recursive)
    {
        userId = RequestHelpers.GetUserId(User, userId);
        var user = userId.IsNullOrEmpty()
            ? null
            : _userManager.GetUserById(userId.Value);
        BaseItem? parentItem = null;
        if (includeItemTypes.Length == 1
            && (includeItemTypes[0] == BaseItemKind.BoxSet
                || includeItemTypes[0] == BaseItemKind.Playlist
                || includeItemTypes[0] == BaseItemKind.Trailer
                || includeItemTypes[0] == BaseItemKind.Program))
        {
            parentItem = null;
        }
        else if (parentId.HasValue)
        {
            parentItem = _libraryManager.GetItemById(parentId.Value);
        }
        var filters = new QueryFilters();
        var genreQuery = new InternalItemsQuery(user)
        {
            IncludeItemTypes = includeItemTypes,
            DtoOptions = new DtoOptions
            {
                Fields = Array.Empty(),
                EnableImages = false,
                EnableUserData = false
            },
            IsAiring = isAiring,
            IsMovie = isMovie,
            IsSports = isSports,
            IsKids = isKids,
            IsNews = isNews,
            IsSeries = isSeries
        };
        if ((recursive ?? true) || parentItem is UserView || parentItem is ICollectionFolder)
        {
            genreQuery.AncestorIds = parentItem is null ? Array.Empty() : new[] { parentItem.Id };
        }
        else
        {
            genreQuery.Parent = parentItem;
        }
        if (includeItemTypes.Length == 1
            && (includeItemTypes[0] == BaseItemKind.MusicAlbum
                || includeItemTypes[0] == BaseItemKind.MusicVideo
                || includeItemTypes[0] == BaseItemKind.MusicArtist
                || includeItemTypes[0] == BaseItemKind.Audio))
        {
            filters.Genres = _libraryManager.GetMusicGenres(genreQuery).Items.Select(i => new NameGuidPair
            {
                Name = i.Item.Name,
                Id = i.Item.Id
            }).ToArray();
        }
        else
        {
            filters.Genres = _libraryManager.GetGenres(genreQuery).Items.Select(i => new NameGuidPair
            {
                Name = i.Item.Name,
                Id = i.Item.Id
            }).ToArray();
        }
        return filters;
    }
}