using Application.Abstractions.Messaging;
using Application.Abstractions.Data;
using Microsoft.EntityFrameworkCore;

namespace Application.Features.Admin.Crypto.List.Search
{
    public sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Response>
    {
        public async Task<Response> Handle(Query request, CancellationToken ct)
        {
            var query = db.Coin.AsNoTracking().Include(c => c.CoinCategoryMap).ThenInclude(m => m.CoinCategory).AsQueryable();

            if (request.CategoryID.HasValue)
            {
                query = query.Where(c => c.CoinCategoryMap.Any(m => m.CategoryID == request.CategoryID.Value));
            }

            if (!string.IsNullOrWhiteSpace(request.Keyword))
            {
                var kw = request.Keyword.Trim();
                query = query.Where(c => c.Symbol.Contains(kw) || c.KorName.Contains(kw) || c.EngName.Contains(kw));
            }

            if (request.IsActive.HasValue)
            {
                query = query.Where(c => c.IsActive == request.IsActive.Value);
            }

            if (request.IsWarning.HasValue)
            {
                query = query.Where(c => c.IsWarning == request.IsWarning.Value);
            }

            if (request.IsNew.HasValue)
            {
                query = query.Where(c => c.IsNew == request.IsNew.Value);
            }

            if (request.IsDelisted.HasValue)
            {
                query = query.Where(c => c.IsDelisted == request.IsDelisted.Value);
            }

            var baseQuery = query;

            var allCount = await baseQuery.CountAsync(ct);
            var krwCount = await baseQuery.Where(c => c.CoinMarket.Any(m => m.Market.StartsWith("KRW-"))).CountAsync(ct);
            var btcCount = await baseQuery.Where(c => c.CoinMarket.Any(m => m.Market.StartsWith("BTC-"))).CountAsync(ct);
            var usdtCount = await baseQuery.Where(c => c.CoinMarket.Any(m => m.Market.StartsWith("USDT-"))).CountAsync(ct);

            if (request.Tab > 0)
            {
                var prefix = request.Tab switch
                {
                    1 => "KRW-",
                    2 => "BTC-",
                    3 => "USDT-",
                    _ => ""
                };

                if (prefix.Length > 0)
                {
                    query = query.Where(c => c.CoinMarket.Any(m => m.Market.StartsWith(prefix)));
                }
            }

            var total = await query.CountAsync(ct);

            var list = await query
                .OrderByDescending(c => c.ID)
                .Skip((request.PageNum - 1) * request.PerPage)
                .Take(request.PerPage)
                .Select(c => new
                {
                    c.ID,
                    c.CoinMarket,
                    c.Symbol,
                    c.KorName,
                    c.EngName,
                    c.LogoImage,
                    CategoryNames = c.CoinCategoryMap.Select(m => m.CoinCategory.Name).ToList(),
                    c.IsActive,
                    c.IsWarning,
                    c.IsNew,
                    c.IsDelisted,
                    c.UpdatedAt,
                    c.CreatedAt
                })
                .ToListAsync(ct);

            var startNum = total - ((request.PageNum - 1) * request.PerPage);

            return new Response(
                total,
                [..list.Select((c, i) => new Response.Row(
                    Num: startNum - i,
                    c.ID,
                    c.CoinMarket,
                    c.Symbol,
                    c.KorName,
                    c.EngName,
                    c.LogoImage,
                    c.CategoryNames,
                    c.IsActive,
                    c.IsWarning,
                    c.IsNew,
                    c.IsDelisted,
                    c.UpdatedAt,
                    c.CreatedAt
                ))],
                allCount,
                krwCount,
                btcCount,
                usdtCount
            );
        }
    }
}