using EllieBot.Modules.Searches.Youtube;

namespace EllieBot.Modules.Searches;

public partial class Searches
{
    public partial class SearchCommands : EllieModule
    {
        private readonly ISearchServiceFactory _searchFactory;
        private readonly IBotCache _cache;

        public SearchCommands(
            ISearchServiceFactory searchFactory,
            IBotCache cache)
        {
            _searchFactory = searchFactory;
            _cache = cache;
        }

        [Cmd]
        public async Task Google([Leftover] string? query = null)
        {
            query = query?.Trim();

            if (string.IsNullOrWhiteSpace(query))
            {
                await Response().Error(strs.specify_search_params).SendAsync();
                return;
            }

            _ = ctx.Channel.TriggerTypingAsync();

            var search = _searchFactory.GetSearchService();
            var data = await search.SearchAsync(query);

            if (data is null or { Entries: null or { Count: 0 } })
            {
                await Response().Error(strs.no_results).SendAsync();
                return;
            }

            // 3 with an answer
            // 4 without an answer
            // 5 is ideal but it lookes horrible on mobile

            var takeCount = string.IsNullOrWhiteSpace(data.Answer)
                ? 4
                : 3;

            var descStr = data.Entries
                              .Take(takeCount)
                              .Select(static res => $@"**[{Format.Sanitize(res.Title)}]({res.Url})**
*{Format.EscapeUrl(res.DisplayUrl)}*
{Format.Sanitize(res.Description ?? "-")}")
                              .Join("\n\n");

            if (!string.IsNullOrWhiteSpace(data.Answer))
                descStr = Format.Code(data.Answer) + "\n\n" + descStr;

            descStr = descStr.TrimTo(4096);

            var embed = CreateEmbed()
                        .WithOkColor()
                        .WithAuthor(ctx.User)
                        .WithTitle(query.TrimTo(64)!)
                        .WithDescription(descStr)
                        .WithFooter(
                            GetText(strs.results_in(data.Info.TotalResults, data.Info.SearchTime)),
                            "https://i.imgur.com/G46fm8J.png");

            await Response().Embed(embed).SendAsync();
        }

        [Cmd]
        public async Task Image([Leftover] string query)
        {
            query = query.Trim();

            if (string.IsNullOrWhiteSpace(query))
            {
                await Response().Error(strs.specify_search_params).SendAsync();
                return;
            }

            _ = ctx.Channel.TriggerTypingAsync();

            var search = _searchFactory.GetImageSearchService();
            var data = await search.SearchImagesAsync(query);

            if (data is null or { Entries: null or { Count: 0 } })
            {
                await Response().Error(strs.no_search_results).SendAsync();
                return;
            }

            EmbedBuilder CreateImageEmbed(IImageSearchResultEntry entry)
            {
                return CreateEmbed()
                       .WithOkColor()
                       .WithAuthor(ctx.User)
                       .WithTitle(query)
                       .WithImageUrl(entry.Link);
            }

            await Response()
                  .Paginated()
                  .Items(data.Entries)
                  .PageSize(1)
                  .AddFooter(false)
                  .Page((items, _) =>
                  {
                      var item = items.FirstOrDefault();

                      if (item is null)
                          return CreateEmbed()
                                 .WithPendingColor()
                                 .WithDescription(GetText(strs.no_search_results));

                      var embed = CreateImageEmbed(item);

                      return embed;
                  })
                  .SendAsync();
        }

        private TypedKey<string[]> GetYtCacheKey(string query)
            => new($"search:yt:{query}");

        private async Task AddYoutubeUrlToCacheAsync(string query, string[] url)
            => await _cache.AddAsync(GetYtCacheKey(query), url, expiry: 1.Hours());

        private async Task<VideoInfo[]?> GetYoutubeUrlFromCacheAsync(string query)
        {
            var result = await _cache.GetAsync(GetYtCacheKey(query));

            if (!result.TryGetValue(out var urls) || urls.Length == 0)
                return null;

            return urls.Map(url => new VideoInfo()
            {
                Url = url
            });
        }

        [Cmd]
        public async Task Youtube([Leftover] string query)
        {
            query = query.Trim();

            _ = ctx.Channel.TriggerTypingAsync();

            var maybeResults = await GetYoutubeUrlFromCacheAsync(query)
                               ?? await _searchFactory.GetYoutubeSearchService().SearchAsync(query);

            if (maybeResults is not { } result || result.Length == 0)
            {
                await Response().Error(strs.no_results).SendAsync();
                return;
            }

            await AddYoutubeUrlToCacheAsync(query, result.Map(x => x.Url));

            await Response().Text(result[0].Url).SendAsync();
        }

        //     [Cmd]
        //     public async Task DuckDuckGo([Leftover] string query = null)
        //     {
        //         query = query?.Trim();
        //         if (!await ValidateQuery(query))
        //             return;
        //
        //         _ = ctx.Channel.TriggerTypingAsync();
        //
        //         var data = await _service.DuckDuckGoSearchAsync(query);
        //         if (data is null)
        //         {
        //             await Response().Error(strs.no_results).SendAsync();
        //             return;
        //         }
        //
        //         var desc = data.Results.Take(5)
        //                        .Select(res => $@"[**{res.Title}**]({res.Link})
        // {res.Text.TrimTo(380 - res.Title.Length - res.Link.Length)}");
        //
        //         var descStr = string.Join("\n\n", desc);
        //
        //         var embed = CreateEmbed()
        //                        .WithAuthor(ctx.User.ToString(),
        //                            "https://upload.wikimedia.org/wikipedia/en/9/90/The_DuckDuckGo_Duck.png")
        //                        .WithDescription($"{GetText(strs.search_for)} **{query}**\n\n" + descStr)
        //                        .WithOkColor();
        //
        //         await Response().Embed(embed).SendAsync();
        //     }
    }
}