using Application.Abstractions.Data;
using Application.Abstractions.Messaging;
using Application.Abstractions.YouTube;
using Microsoft.EntityFrameworkCore;
using SharedKernel.Results;

namespace Application.Features.Api.Channel.List;

public sealed class Handler(IAppDbContext db, IYouTubeLiveStateStore liveStateStore, IYouTubeChannelCache channelCache) : IQueryHandler<Query, Result<Response>>
{
    public async Task<Result<Response>> Handle(Query request, CancellationToken ct)
    {
        // 1. 활성 채널 목록 조회
        var channels = await db.Channel.AsNoTracking().Where(c => c.IsActive).Select(c => new { c.SID, c.Name, c.Handle }).ToListAsync(ct);

        if (channels.Count == 0)
        {
            return new Response([]);
        }

        // 2. YouTube 채널 정보 캐시 일괄 조회 (Redis — API 호출 0)
        var channelIds = channels.Select(c => c.SID).ToList();
        var ytCache = await channelCache.GetManyAsync(channelIds);

        // 3. 현재 라이브 중인 채널 상태 조회 (Redis — 0 unit)
        var allLive = await liveStateStore.GetAllLiveAsync();
        var liveMap = allLive.ToDictionary(l => l.ChannelId);

        // 4. 채널별 정보 조합
        var items = new List<ChannelItem>();
        foreach (var ch in channels)
        {
            var isLive = liveMap.TryGetValue(ch.SID, out var liveInfo);
            var hasYtInfo = ytCache.TryGetValue(ch.SID, out var ytInfo);

            items.Add(new ChannelItem(
                ch.SID,
                ch.Name,
                ch.Handle,
                hasYtInfo ? ytInfo!.ThumbnailUrl : null,
                hasYtInfo ? ytInfo!.SubscriberCount : 0,
                isLive,
                0, // viewerCount — 추후 사이트 자체 접속자 수로 대체
                isLive ? liveInfo!.VideoId : null
            ));
        }

        // 5. 정렬: 온라인(시청자 많은 순) → 오프라인(이름순)
        items.Sort((a, b) => {
            if (a.IsLive && !b.IsLive) return -1;
            if (!a.IsLive && b.IsLive) return 1;
            if (a.IsLive && b.IsLive) return b.ViewerCount.CompareTo(a.ViewerCount);
            return string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase);
        });

        return new Response(items);
    }
}