using AdsManagerService.Domain.AggregatesModel.CampaignAggregate;
using AdsManagerService.Infrastructure;
using MediatR;
using Microsoft.EntityFrameworkCore;

namespace AdsManagerService.API.Application.Queries;

/// <summary>
/// EN: Handler for listing campaigns with filtering and pagination.
/// VI: Handler liệt kê chiến dịch với filtering và phân trang.
/// </summary>
public class ListCampaignsQueryHandler : IRequestHandler<ListCampaignsQuery, ListCampaignsResult>
{
    private readonly AdsManagerServiceContext _context;

    public ListCampaignsQueryHandler(AdsManagerServiceContext context)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
    }

    public async Task<ListCampaignsResult> Handle(ListCampaignsQuery request, CancellationToken cancellationToken)
    {
        // EN: Build query with filters
        // VI: Xây dựng query với các bộ lọc
        var query = _context.Campaigns.AsQueryable();

        // Filter by advertiser
        if (request.AdvertiserId.HasValue)
        {
            query = query.Where(c => c.AdvertiserId == request.AdvertiserId.Value);
        }

        // Filter by status
        if (!string.IsNullOrWhiteSpace(request.Status))
        {
            var status = CampaignStatus.FromName(request.Status);
            query = query.Where(c => c.StatusId == status.Id);
        }

        // Filter by objective
        if (!string.IsNullOrWhiteSpace(request.Objective))
        {
            var objective = CampaignObjective.FromName(request.Objective);
            query = query.Where(c => c.ObjectiveId == objective.Id);
        }

        // Search by name
        if (!string.IsNullOrWhiteSpace(request.SearchTerm))
        {
            query = query.Where(c => c.Name.Contains(request.SearchTerm));
        }

        // Get total count
        var totalCount = await query.CountAsync(cancellationToken);

        // Apply pagination
        var campaigns = await query
            .OrderByDescending(c => c.CreatedAt)
            .Skip((request.Page - 1) * request.PageSize)
            .Take(request.PageSize)
            .Select(c => new CampaignDto
            {
                Id = c.Id,
                AdvertiserId = c.AdvertiserId,
                Name = c.Name,
                Description = c.Description,
                Status = c.Status.Name,
                Objective = c.Objective.Name,
                BudgetType = c.Budget.Type.ToString(),
                BudgetAmount = c.Budget.Amount,
                Currency = c.Budget.Currency,
                TotalSpend = c.TotalSpend,
                StartDate = c.StartDate,
                EndDate = c.EndDate,
                CreatedAt = c.CreatedAt,
                UpdatedAt = c.UpdatedAt
            })
            .ToListAsync(cancellationToken);

        return new ListCampaignsResult
        {
            Items = campaigns,
            TotalCount = totalCount,
            Page = request.Page,
            PageSize = request.PageSize
        };
    }
}
