using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Microsoft.EntityFrameworkCore; namespace Application.Features.Api.Channel.SearchForOrder; public sealed class Handler(IAppDbContext db) : IQueryHandler { public async Task Handle(Query request, CancellationToken ct) { var query = db.Channel.AsNoTracking() .Where(c => c.IsActive && c.MemberID != request.MemberID) .AsQueryable(); if (!string.IsNullOrWhiteSpace(request.Keyword)) { var kw = request.Keyword.Trim(); var codeKw = kw.ToUpperInvariant(); query = query.Where(c => c.Name.Contains(kw) || (c.Handle != null && c.Handle.Contains(kw)) || (c.DonationCode != null && c.DonationCode == codeKw)); } var total = await query.CountAsync(ct); // Random=true 면 SQL NEWID() 로 셔플 — 공평한 노출. // 그 외는 인증/구독자 수 정렬 (관리자 노출 기준). var ordered = request.Random ? query.OrderBy(c => Guid.NewGuid()) : query .OrderByDescending(c => c.IsVerified) .ThenByDescending(c => c.SubscriberCount); var list = await ordered .Skip((request.Page - 1) * request.PerPage) .Take(request.PerPage) .Select(c => new Response.Row( c.ID, c.SID, c.Name, c.Handle, c.ThumbnailUrl, c.SubscriberCount, c.IsVerified, c.DonationCode )) .ToListAsync(ct); return new Response(total, list); } }