using ErsatzTV.Core.Interfaces.Search;
using ErsatzTV.Core.Search;
using ErsatzTV.Infrastructure.Search;

namespace ErsatzTV.Application.Search;

public class QuerySearchIndexAllItemsHandler(ISearchIndex searchIndex)
    : IRequestHandler<QuerySearchIndexAllItems, SearchResultAllItemsViewModel>
{
    public async Task<SearchResultAllItemsViewModel> Handle(
        QuerySearchIndexAllItems request,
        CancellationToken cancellationToken)
    {
        int skip = request.PageNum * request.PageSize;
        int limit = request.PageSize;

        (List<int> Ids, int Total) movies =
            await GetIds(LuceneSearchIndex.MovieType, request.Query, skip, limit, cancellationToken);
        (List<int> Ids, int Total) shows =
            await GetIds(LuceneSearchIndex.ShowType, request.Query, skip, limit, cancellationToken);
        (List<int> Ids, int Total) seasons =
            await GetIds(LuceneSearchIndex.SeasonType, request.Query, skip, limit, cancellationToken);
        (List<int> Ids, int Total) episodes =
            await GetIds(LuceneSearchIndex.EpisodeType, request.Query, skip, limit, cancellationToken);
        (List<int> Ids, int Total) artists =
            await GetIds(LuceneSearchIndex.ArtistType, request.Query, skip, limit, cancellationToken);
        (List<int> Ids, int Total) musicVideos =
            await GetIds(LuceneSearchIndex.MusicVideoType, request.Query, skip, limit, cancellationToken);
        (List<int> Ids, int Total) otherVideos =
            await GetIds(LuceneSearchIndex.OtherVideoType, request.Query, skip, limit, cancellationToken);
        (List<int> Ids, int Total) songs =
            await GetIds(LuceneSearchIndex.SongType, request.Query, skip, limit, cancellationToken);
        (List<int> Ids, int Total) images =
            await GetIds(LuceneSearchIndex.ImageType, request.Query, skip, limit, cancellationToken);
        (List<int> Ids, int Total) remoteStreams =
            await GetIds(LuceneSearchIndex.RemoteStreamType, request.Query, skip, limit, cancellationToken);

        return new SearchResultAllItemsViewModel(
            movies.Ids,
            shows.Ids,
            seasons.Ids,
            episodes.Ids,
            artists.Ids,
            musicVideos.Ids,
            otherVideos.Ids,
            songs.Ids,
            images.Ids,
            remoteStreams.Ids,
            new SearchResultAllItemsTotals(
                movies.Total,
                shows.Total,
                seasons.Total,
                episodes.Total,
                artists.Total,
                musicVideos.Total,
                otherVideos.Total,
                songs.Total,
                images.Total,
                remoteStreams.Total));
    }

    private async Task<(List<int> Ids, int Total)> GetIds(
        string type,
        string query,
        int skip,
        int limit,
        CancellationToken cancellationToken)
    {
        SearchResult result = await searchIndex.Search(
            $"type:{type} AND ({query})",
            string.Empty,
            skip,
            limit,
            cancellationToken);
        return (result.Items.Map(i => i.Id).ToList(), result.TotalCount);
    }
}
