using MediatR;
using Microsoft.EntityFrameworkCore;
using FacebookService.API.Application.Dtos;
using FacebookService.Domain.AggregatesModel.CustomerAggregate;
using FacebookService.Infrastructure;

namespace FacebookService.API.Application.Queries;

/// <summary>
/// EN: Handler for GetCustomersQuery - returns paginated customers list.
/// VI: Handler cho GetCustomersQuery - trả về danh sách customers phân trang.
/// </summary>
public class GetCustomersQueryHandler : IRequestHandler<GetCustomersQuery, GetCustomersQueryResult>
{
    private readonly FacebookServiceContext _context;

    public GetCustomersQueryHandler(FacebookServiceContext context)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
    }

    public async Task<GetCustomersQueryResult> Handle(
        GetCustomersQuery request,
        CancellationToken cancellationToken)
    {
        // EN: Build base query / VI: Xây dựng query cơ bản
        var query = _context.Customers.AsNoTracking().AsQueryable();

        // EN: Filter by search term (name match) / VI: Lọc theo từ khóa tìm kiếm (tên)
        if (!string.IsNullOrWhiteSpace(request.Search))
        {
            var searchTerm = request.Search.Trim();
            query = query.Where(c =>
                EF.Property<string?>(c, "_name") != null &&
                EF.Property<string>(c, "_name")!.Contains(searchTerm));
        }

        // EN: Filter by tags if provided / VI: Lọc theo tags nếu có
        if (request.Tags != null && request.Tags.Any())
        {
            var tagList = request.Tags.ToList();
            foreach (var tag in tagList)
            {
                // EN: Each tag must be present / VI: Mỗi tag phải có mặt
                query = query.Where(c => c.Tags.Contains(tag));
            }
        }

        // EN: Get total count for pagination / VI: Lấy tổng số cho phân trang
        var totalCount = await query.CountAsync(cancellationToken);

        // EN: Get paginated customers ordered by last interaction
        // VI: Lấy customers phân trang sắp xếp theo tương tác cuối
        var customers = await query
            .OrderByDescending(c => EF.Property<DateTime>(c, "_lastInteractionAt"))
            .Skip(request.Skip)
            .Take(request.Take)
            .ToListAsync(cancellationToken);

        // EN: Map to summary DTOs / VI: Map sang DTO tóm tắt
        var summaries = customers.Select(c => new CustomerSummaryDto(
            c.Id,
            c.FacebookUserId,
            c.Name,
            c.ProfilePicUrl,
            c.Tags,
            c.LastInteractionAt
        )).ToList();

        return new GetCustomersQueryResult(summaries, totalCount);
    }
}

/// <summary>
/// EN: Handler for GetCustomerByIdQuery.
/// VI: Handler cho GetCustomerByIdQuery.
/// </summary>
public class GetCustomerByIdQueryHandler : IRequestHandler<GetCustomerByIdQuery, CustomerDto?>
{
    private readonly ICustomerRepository _customerRepository;

    public GetCustomerByIdQueryHandler(ICustomerRepository customerRepository)
    {
        _customerRepository = customerRepository ?? throw new ArgumentNullException(nameof(customerRepository));
    }

    public async Task<CustomerDto?> Handle(
        GetCustomerByIdQuery request,
        CancellationToken cancellationToken)
    {
        var customer = await _customerRepository.GetByIdAsync(request.CustomerId, cancellationToken);

        if (customer is null)
        {
            return null;
        }

        return MapToDto(customer);
    }

    private static CustomerDto MapToDto(Customer customer)
    {
        return new CustomerDto(
            customer.Id,
            customer.FacebookUserId,
            customer.Name,
            customer.Email,
            customer.Phone,
            customer.ProfilePicUrl,
            customer.Locale,
            customer.Timezone,
            customer.Tags,
            customer.CustomFields,
            customer.FirstSeenAt,
            customer.LastInteractionAt
        );
    }
}

/// <summary>
/// EN: Handler for GetCustomerByFacebookIdQuery.
/// VI: Handler cho GetCustomerByFacebookIdQuery.
/// </summary>
public class GetCustomerByFacebookIdQueryHandler : IRequestHandler<GetCustomerByFacebookIdQuery, CustomerDto?>
{
    private readonly ICustomerRepository _customerRepository;

    public GetCustomerByFacebookIdQueryHandler(ICustomerRepository customerRepository)
    {
        _customerRepository = customerRepository ?? throw new ArgumentNullException(nameof(customerRepository));
    }

    public async Task<CustomerDto?> Handle(
        GetCustomerByFacebookIdQuery request,
        CancellationToken cancellationToken)
    {
        var customer = await _customerRepository.GetByFacebookUserIdAsync(request.FacebookUserId, cancellationToken);

        if (customer is null)
        {
            return null;
        }

        return new CustomerDto(
            customer.Id,
            customer.FacebookUserId,
            customer.Name,
            customer.Email,
            customer.Phone,
            customer.ProfilePicUrl,
            customer.Locale,
            customer.Timezone,
            customer.Tags,
            customer.CustomFields,
            customer.FirstSeenAt,
            customer.LastInteractionAt
        );
    }
}
