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

namespace JSMR.Infrastructure.Data.Repositories.Creators;

public class CreatorSearchProvider(AppDbContext context) : SearchProvider<CreatorSearchItem, CreatorSearchCriteria, CreatorSortField, CreatorSearchItem>, ICreatorSearchProvider
{
    protected override bool UseSelectIdQuery => false;

    protected override IQueryable<CreatorSearchItem> GetBaseQuery()
    {
        return
            from creator in context.Creators
            join voiceWorkCreators in context.VoiceWorkCreators on creator.CreatorId equals voiceWorkCreators.CreatorId into vwcs
            select new CreatorSearchItem
            {
                CreatorId = creator.CreatorId,
                Name = creator.Name,
                Favorite = creator.Favorite,
                Blacklisted = creator.Blacklisted,
                VoiceWorkCount = vwcs.Count()
            };
    }

    protected override IQueryable<CreatorSearchItem> ApplyFilters(IQueryable<CreatorSearchItem> query, CreatorSearchCriteria criteria)
    {
        IQueryable<CreatorSearchItem> filteredQuery = query;

        if (string.IsNullOrEmpty(criteria.Name) == false)
        {
            string name = criteria.Name.Trim();

            filteredQuery = filteredQuery.Where(x => x.Name.Contains(name));
        }

        return filteredQuery;
    }

    protected override Expression<Func<CreatorSearchItem, object?>> GetSortExpression(CreatorSortField field)
    {
        Expression<Func<CreatorSearchItem, object?>> selector = field switch
        {
            CreatorSortField.VoiceWorkCount => x => x.VoiceWorkCount,
            CreatorSortField.Favorite => x => x.Favorite,
            CreatorSortField.Blacklisted => x => x.Blacklisted,
            _ => x => x.Name
        };

        return selector;
    }

    protected override IEnumerable<(Expression<Func<CreatorSearchItem, object>> Selector, SortDirection Dir)> GetDefaultSortChain()
    {
        yield return (x => x.Name, SortDirection.Ascending);
    }

    protected override IOrderedQueryable<CreatorSearchItem> GetSelectQuery(CreatorSearchCriteria criteria, IOrderedQueryable<CreatorSearchItem> query)
    {
        return query;
    }

    protected override IQueryable<int> GetSelectIdQuery(IOrderedQueryable<CreatorSearchItem> query)
    {
        throw new NotImplementedException();
    }

    protected override Task<Dictionary<int, CreatorSearchItem>> GetItems(CreatorSearchCriteria criteria, int[] ids)
    {
        return Task.FromResult(new Dictionary<int, CreatorSearchItem>());
    }
}