using JSMR.Application.Tags.Queries.Search.Contracts;
using JSMR.Application.Tags.Queries.Search.Ports;
using JSMR.Infrastructure.Common.Queries;
using System.Linq.Expressions;

namespace JSMR.Infrastructure.Data.Repositories.Tags;



//public class TagReader(AppDbContext context) : ITagReader
//{
//    public async Task<TagSearchResults> SearchAsync(TagSearchOptions options, CancellationToken cancellationToken = default)
//    {
//        IQueryable<TagSearchItem> baseQuery = GetQuery();
//        IQueryable<TagSearchItem> filteredQuery = ApplyFilters(baseQuery, options);

//        int total = await filteredQuery.CountAsync(cancellationToken);

//        IOrderedQueryable<TagSearchItem> orderedQuery = ApplySorting(filteredQuery, options);

//        TagSearchItem[] items = await orderedQuery
//            .Skip((options.PageNumber - 1) * options.PageSize)
//            .Take(options.PageSize)
//            .ToArrayAsync(cancellationToken);

//        return new TagSearchResults()
//        {
//            Items = items,
//            TotalItems = total
//        };
//    }

//    private IQueryable<TagSearchItem> GetQuery()
//    {
//        return
//            from tag in context.Tags
//            join englishTag in context.EnglishTags on tag.TagId equals englishTag.TagId into test
//            from subEnglishTag in test.DefaultIfEmpty()
//            join voiceWorkTags in context.VoiceWorkTags on tag.TagId equals voiceWorkTags.TagId into vwts
//            select new TagSearchItem
//            {
//                TagId = tag.TagId,
//                Name = tag.Name,
//                EnglishName = subEnglishTag.Name,
//                Favorite = tag.Favorite,
//                Blacklisted = tag.Blacklisted,
//                VoiceWorkCount = context.VoiceWorkTags.Count(x => x.TagId == tag.TagId)
//            };
//    }

//    private static IQueryable<TagSearchItem> ApplyFilters(IQueryable<TagSearchItem> query, TagSearchOptions options)
//    {
//        IQueryable<TagSearchItem> filteredQuery = query;

//        if (string.IsNullOrEmpty(options.Criteria.Name) == false)
//        {
//            string name = options.Criteria.Name.Trim();

//            filteredQuery = filteredQuery.Where(x =>
//                x.Name.Contains(name) || (x.EnglishName != null && x.EnglishName.Contains(name)));
//        }

//        return filteredQuery;
//    }

//    private static IOrderedQueryable<TagSearchItem> ApplySorting(IQueryable<TagSearchItem> query, TagSearchOptions options)
//    {
//        IOrderedQueryable<TagSearchItem>? ordered = null;

//        for (int i = 0; i < options.SortOptions.Length; i++)
//        {
//            var (field, direction) = (options.SortOptions[i].Field, options.SortOptions[i].Direction);
//            bool isDescending = direction == SortDirection.Descending;

//            IOrderedQueryable<TagSearchItem> applyFirst(Expression<Func<TagSearchItem, object>> selector) => isDescending ? query.OrderByDescending(selector) : query.OrderBy(selector);
//            IOrderedQueryable<TagSearchItem> applyNext(Expression<Func<TagSearchItem, object>> selector) => isDescending ? ordered!.ThenByDescending(selector) : ordered!.ThenBy(selector);

//            Expression<Func<TagSearchItem, object>> selector = field switch
//            {
//                TagSortField.EnglishName => x => x.EnglishName ?? "",
//                TagSortField.VoiceWorkCount => x => x.VoiceWorkCount,
//                TagSortField.Favorite => x => x.Favorite,
//                TagSortField.Blacklisted => x => x.Blacklisted,
//                _ => x => x.Name
//            };

//            ordered = (i == 0) ? applyFirst(selector) : applyNext(selector);
//        }

//        ordered ??= query.OrderBy(x => x.Name);

//        return ordered;
//    }
//}