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

namespace Application.Features.Api.Crew.GetCrewList;

internal sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Response>
{
    public async Task<Response> Handle(Query request, CancellationToken ct)
    {
        var query = db.Crew.AsNoTracking().Where(c => c.ChannelID == request.ChannelID);

        var total = await query.CountAsync(ct);

        // 정렬을 Select 전 엔티티 위에서 수행 (EF Core SQL 변환 가능)
        var sorted = (request.SortBy, request.SortDir) switch
        {
            ("amount", "asc") => query.OrderBy(c => c.Sessions.Sum(s => s.TotalAmount)),
            ("amount", _) => query.OrderByDescending(c => c.Sessions.Sum(s => s.TotalAmount)),
            ("members", "asc") => query.OrderBy(c => c.Members.Count(m => m.IsActive)),
            ("members", _) => query.OrderByDescending(c => c.Members.Count(m => m.IsActive)),
            ("date", "asc") => query.OrderBy(c => c.CreatedAt),
            _ => query.OrderByDescending(c => c.CreatedAt)
        };

        var list = await sorted
            .Skip((request.PageNum - 1) * request.PerPage)
            .Take(request.PerPage)
            .Select(c => new CrewItem(
                c.ID, c.Name, c.Description, c.MinAmount, c.IsActive,
                c.Members.Count(m => m.IsActive),
                c.Sessions.Count,
                c.Sessions.Sum(s => s.TotalAmount),
                c.CreatedAt
            ))
            .ToListAsync(ct);

        return new Response(total, list);
    }
}