using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Domain.Entities.Store.ValueObject; using Microsoft.EntityFrameworkCore; namespace Application.Features.Admin.Store.Product.Search; public sealed class Handler(IAppDbContext db) : IQueryHandler { public async Task Handle(Query request, CancellationToken ct) { var query = db.Product.AsNoTracking().Include(c => c.Game).AsQueryable(); if (request.GameID.HasValue) { query = query.Where(c => c.GameID == request.GameID.Value); } if (request.Type.HasValue) { query = query.Where(c => c.Type == request.Type.Value); } if (request.IsActive.HasValue) { query = query.Where(c => c.IsActive == request.IsActive.Value); } if (!string.IsNullOrWhiteSpace(request.Keyword)) { var kw = request.Keyword.Trim(); query = request.Search switch { 1 => int.TryParse(kw, out var id) ? query.Where(c => c.ID == id) : query.Where(c => false), _ => query.Where(c => c.Name.Contains(kw)) }; } if (DateTime.TryParse(request.StartAt, out var startAt)) { query = query.Where(c => c.CreatedAt >= startAt); } if (DateTime.TryParse(request.EndAt, out var endAt)) { query = query.Where(c => c.CreatedAt <= endAt); } var total = await query.CountAsync(ct); var list = await query .OrderBy(c => c.Order) .ThenByDescending(c => c.ID) .Skip((request.Page - 1) * request.PerPage) .Take(request.PerPage) .Select(c => new { c.ID, c.GameID, GameName = c.Game!.KorName, c.Name, c.Thumbnail, c.Type, c.Price, c.DiscountType, c.DiscountValue, c.Stock, c.IsActive, c.Order, c.SaleStartAt, c.SaleEndAt, c.UpdatedAt, c.CreatedAt }) .ToListAsync(ct); var startNum = total - ((request.Page - 1) * request.PerPage); return new Response( total, [.. list.Select((c, i) => { var salePrice = c.DiscountType switch { DiscountType.Percent => Math.Max(0, c.Price - (c.Price * c.DiscountValue / 100)), DiscountType.Amount => Math.Max(0, c.Price - c.DiscountValue), _ => c.Price }; return new Response.Row( Num: startNum - i, c.ID, c.GameID, c.GameName, c.Name, c.Thumbnail, c.Type, c.Price, c.DiscountType, c.DiscountValue, salePrice, c.Stock, c.IsActive, c.Order, c.SaleStartAt, c.SaleEndAt, c.UpdatedAt, c.CreatedAt ); })] ); } }