// EN: Query to get all merchants with pagination for admin.
// VI: Query để lấy tất cả merchants với phân trang cho admin.

using MediatR;
using Microsoft.EntityFrameworkCore;
using MerchantService.Infrastructure;

namespace MerchantService.API.Application.Queries.Admin;

/// <summary>
/// EN: Query to get all merchants with filters (Admin only).
/// VI: Query để lấy tất cả merchants với bộ lọc (chỉ Admin).
/// </summary>
public record GetAllMerchantsQuery(
    int Page = 1,
    int PageSize = 20,
    string? Status = null,
    string? VerificationStatus = null,
    string? Search = null) : IRequest<AdminMerchantListResultDto>;

/// <summary>
/// EN: Handler for GetAllMerchantsQuery.
/// VI: Handler cho GetAllMerchantsQuery.
/// </summary>
public class GetAllMerchantsQueryHandler : IRequestHandler<GetAllMerchantsQuery, AdminMerchantListResultDto>
{
    private readonly MerchantServiceContext _context;

    public GetAllMerchantsQueryHandler(MerchantServiceContext context)
    {
        _context = context;
    }

    public async Task<AdminMerchantListResultDto> Handle(
        GetAllMerchantsQuery request,
        CancellationToken cancellationToken)
    {
        var query = _context.Merchants
            .AsNoTracking()
            .Where(m => !m.IsDeleted);

        // EN: Apply filters / VI: Áp dụng bộ lọc
        if (!string.IsNullOrEmpty(request.Status))
        {
            query = query.Where(m => m.Status.Name == request.Status);
        }

        if (!string.IsNullOrEmpty(request.VerificationStatus))
        {
            query = query.Where(m => m.VerificationStatus.Name == request.VerificationStatus);
        }

        if (!string.IsNullOrEmpty(request.Search))
        {
            var searchLower = request.Search.ToLower();
            query = query.Where(m => m.BusinessName.ToLower().Contains(searchLower));
        }

        var totalCount = await query.CountAsync(cancellationToken);
        var totalPages = (int)Math.Ceiling(totalCount / (double)request.PageSize);

        var items = await query
            .OrderByDescending(m => m.CreatedAt)
            .Skip((request.Page - 1) * request.PageSize)
            .Take(request.PageSize)
            .Select(m => new AdminMerchantListItemDto(
                m.Id,
                m.UserId,
                m.BusinessName,
                m.Type.Name,
                m.Status.Name,
                m.VerificationStatus.Name,
                _context.Shops.Count(s => s.MerchantId == m.Id && !s.IsDeleted),
                m.CreatedAt,
                m.VerifiedAt))
            .ToListAsync(cancellationToken);

        return new AdminMerchantListResultDto(
            items,
            totalCount,
            request.Page,
            request.PageSize,
            totalPages);
    }
}
