using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Domain.Entities.Common.ValueObject; using Microsoft.EntityFrameworkCore; namespace Application.Features.Admin.Mail.Search; public sealed class Handler(IAppDbContext db) : IQueryHandler { public async Task Handle(Query request, CancellationToken ct) { var query = db.EmailLog.AsNoTracking().AsQueryable(); if (!string.IsNullOrWhiteSpace(request.Keyword)) { var keyword = request.Keyword.Trim(); query = request.Search switch { 1 => long.TryParse(keyword, out var id) ? query.Where(x => x.ID == id) : query.Where(x => false), 2 => query.Where(x => x.ToAddress.Contains(keyword)), 3 => query.Where(x => x.Subject.Contains(keyword)), 4 => query.Where(x => x.Category != null && x.Category.Contains(keyword)), _ => query }; } if (!string.IsNullOrWhiteSpace(request.StartAt) && DateTime.TryParse(request.StartAt, out var startAt)) { query = query.Where(x => x.CreatedAt >= startAt); } if (!string.IsNullOrWhiteSpace(request.EndAt) && DateTime.TryParse(request.EndAt, out var endAt)) { query = query.Where(x => x.CreatedAt <= endAt); } // 탭별 건수 집계 (탭 필터 적용 전) var counts = await query.GroupBy(c => 1).Select(c => new { Pending = c.Count(x => x.Status == MailStatus.Pending), Processing = c.Count(x => x.Status == MailStatus.Processing), Sent = c.Count(x => x.Status == MailStatus.Sent), Failed = c.Count(x => x.Status == MailStatus.Failed) }).FirstOrDefaultAsync(ct); var pendingCount = counts?.Pending ?? 0; var processingCount = counts?.Processing ?? 0; var sentCount = counts?.Sent ?? 0; var failedCount = counts?.Failed ?? 0; query = request.Tab switch { 1 => query.Where(x => x.Status == MailStatus.Pending), 2 => query.Where(x => x.Status == MailStatus.Processing), 3 => query.Where(x => x.Status == MailStatus.Sent), 4 => query.Where(x => x.Status == MailStatus.Failed), _ => query }; var total = await query.CountAsync(ct); var skip = (request.Page - 1) * request.PerPage; var list = await query .OrderByDescending(x => x.ID) .Skip(skip) .Take(request.PerPage) .Select(x => new { x.ID, x.ToAddress, x.Subject, x.Status, x.RetryCount, x.MaxRetryCount, x.NextRetryAt, x.LastError, x.Category, x.CreatedAt, x.ProcessedAt, x.FailedAt }) .ToListAsync(ct); var rows = list.Select((x, idx) => new Response.Row { Num = total - skip - idx, ID = x.ID, ToAddress = x.ToAddress, Subject = x.Subject, Status = (byte)x.Status, StatusName = x.Status.ToString(), RetryCount = x.RetryCount, MaxRetryCount = x.MaxRetryCount, NextRetryAt = x.NextRetryAt, LastError = x.LastError, Category = x.Category, CreatedAt = x.CreatedAt, ProcessedAt = x.ProcessedAt, FailedAt = x.FailedAt }).ToList(); return new Response { Total = total, Pending = pendingCount, Processing = processingCount, Sent = sentCount, Failed = failedCount, List = rows }; } }