using MediatR;
using TakeoutSaaS.Application.App.Customers.Dto;
using TakeoutSaaS.Application.App.Customers.Queries;
using TakeoutSaaS.Domain.Orders.Repositories;
using TakeoutSaaS.Shared.Abstractions.Data;
using TakeoutSaaS.Shared.Abstractions.Results;
using TakeoutSaaS.Shared.Abstractions.Tenancy;

namespace TakeoutSaaS.Application.App.Customers.Handlers;

/// <summary>
/// 客户列表查询处理器。
/// </summary>
public sealed class SearchCustomerListQueryHandler(
    IOrderRepository orderRepository,
    IDapperExecutor dapperExecutor,
    ITenantProvider tenantProvider)
    : IRequestHandler<SearchCustomerListQuery, PagedResult<CustomerListItemDto>>
{
    /// <inheritdoc />
    public async Task<PagedResult<CustomerListItemDto>> Handle(
        SearchCustomerListQuery request,
        CancellationToken cancellationToken)
    {
        // 1. 规范化分页参数
        var page = Math.Max(1, request.Page);
        var pageSize = Math.Clamp(request.PageSize, 1, 200);
        if (request.VisibleStoreIds.Count == 0)
        {
            return new PagedResult<CustomerListItemDto>([], page, pageSize, 0);
        }

        // 2. 加载客户聚合并应用筛选
        var customers = await CustomerAnalyticsSupport.LoadCustomersAsync(
            orderRepository,
            dapperExecutor,
            tenantProvider,
            request.VisibleStoreIds,
            cancellationToken);

        var nowUtc = DateTime.UtcNow;
        var filteredCustomers = CustomerAnalyticsSupport.ApplyFilters(
            customers,
            request.Keyword,
            CustomerAnalyticsSupport.NormalizeTag(request.Tag),
            CustomerAnalyticsSupport.NormalizeOrderCountRange(request.OrderCountRange),
            request.RegisterPeriodDays,
            nowUtc)
            .OrderByDescending(item => item.LastOrderAt)
            .ThenBy(item => item.CustomerKey, StringComparer.Ordinal)
            .ToList();

        // 3. 执行分页与列表映射
        var totalCount = filteredCustomers.Count;
        var maxOrderCount = Math.Max(1, filteredCustomers.Select(item => item.OrderCount).DefaultIfEmpty(1).Max());

        var items = filteredCustomers
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .Select(item => new CustomerListItemDto
            {
                CustomerKey = item.CustomerKey,
                Name = item.Name,
                PhoneMasked = item.PhoneMasked,
                AvatarText = item.AvatarText,
                AvatarColor = item.AvatarColor,
                OrderCount = item.OrderCount,
                OrderCountBarPercent = Math.Max(4, (int)Math.Round(item.OrderCount * 100d / maxOrderCount, MidpointRounding.AwayFromZero)),
                TotalAmount = item.TotalAmount,
                AverageAmount = item.AverageAmount,
                RegisteredAt = item.RegisteredAt,
                LastOrderAt = item.LastOrderAt,
                Tags = item.Tags,
                IsDimmed = item.IsDimmed
            })
            .ToList();

        return new PagedResult<CustomerListItemDto>(items, page, pageSize, totalCount);
    }
}
