// EN: Query to get all shops with pagination for admin.
// VI: Query để lấy tất cả shops 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 shops with filters (Admin only).
/// VI: Query để lấy tất cả shops với bộ lọc (chỉ Admin).
/// </summary>
public record GetAllShopsQuery(
    int Page = 1,
    int PageSize = 20,
    string? Status = null,
    Guid? MerchantId = null,
    string? Search = null) : IRequest<AdminShopListResultDto>;

/// <summary>
/// EN: Handler for GetAllShopsQuery.
/// VI: Handler cho GetAllShopsQuery.
/// </summary>
public class GetAllShopsQueryHandler : IRequestHandler<GetAllShopsQuery, AdminShopListResultDto>
{
    private readonly MerchantServiceContext _context;

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

    public async Task<AdminShopListResultDto> Handle(
        GetAllShopsQuery request,
        CancellationToken cancellationToken)
    {
        var query = _context.Shops
            .AsNoTracking()
            .Where(s => !s.IsDeleted);

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

        if (request.MerchantId.HasValue)
        {
            query = query.Where(s => s.MerchantId == request.MerchantId.Value);
        }

        if (!string.IsNullOrEmpty(request.Search))
        {
            var searchLower = request.Search.ToLower();
            query = query.Where(s => 
                s.Name.ToLower().Contains(searchLower) || 
                s.Slug.ToLower().Contains(searchLower));
        }

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

        // EN: Get shops with merchant info using join
        // VI: Lấy shops cùng với merchant info bằng join
        var items = await query
            .Join(
                _context.Merchants,
                shop => shop.MerchantId,
                merchant => merchant.Id,
                (shop, merchant) => new { Shop = shop, MerchantBusinessName = merchant.BusinessName })
            .OrderByDescending(x => x.Shop.CreatedAt)
            .Skip((request.Page - 1) * request.PageSize)
            .Take(request.PageSize)
            .Select(x => new AdminShopListItemDto(
                x.Shop.Id,
                x.Shop.MerchantId,
                x.MerchantBusinessName,
                x.Shop.Name,
                x.Shop.Slug,
                x.Shop.Status.Name,
                x.Shop.Category != null ? x.Shop.Category.Name : null,
                x.Shop.CreatedAt))
            .ToListAsync(cancellationToken);

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