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.Tenancy;

namespace TakeoutSaaS.Application.App.Customers.Handlers;

/// <summary>
/// 客户列表统计查询处理器。
/// </summary>
public sealed class GetCustomerListStatsQueryHandler(
    IOrderRepository orderRepository,
    IDapperExecutor dapperExecutor,
    ITenantProvider tenantProvider)
    : IRequestHandler<GetCustomerListStatsQuery, CustomerListStatsDto>
{
    /// <inheritdoc />
    public async Task<CustomerListStatsDto> Handle(
        GetCustomerListStatsQuery request,
        CancellationToken cancellationToken)
    {
        // 1. 可见门店为空时直接返回空统计
        if (request.VisibleStoreIds.Count == 0)
        {
            return new CustomerListStatsDto();
        }

        // 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);

        // 3. 计算统计指标
        var monthStart = new DateTime(nowUtc.Year, nowUtc.Month, 1, 0, 0, 0, DateTimeKind.Utc);
        var nextMonthStart = monthStart.AddMonths(1);
        var previousMonthStart = monthStart.AddMonths(-1);

        var totalCustomers = filteredCustomers.Count;
        var monthlyNewCustomers = filteredCustomers.Count(item =>
            item.RegisteredAt >= monthStart &&
            item.RegisteredAt < nextMonthStart);
        var previousMonthlyNewCustomers = filteredCustomers.Count(item =>
            item.RegisteredAt >= previousMonthStart &&
            item.RegisteredAt < monthStart);
        var activeCustomers = filteredCustomers.Count(item =>
            item.LastOrderAt >= nowUtc.AddDays(-30));

        var recentOrders = filteredCustomers
            .SelectMany(item => item.Orders)
            .Where(item => item.OrderedAt >= nowUtc.AddDays(-30))
            .ToList();

        var averageAmountLast30Days = recentOrders.Count == 0
            ? 0
            : decimal.Round(
                recentOrders.Sum(item => item.Amount) / recentOrders.Count,
                2,
                MidpointRounding.AwayFromZero);

        return new CustomerListStatsDto
        {
            TotalCustomers = totalCustomers,
            MonthlyNewCustomers = monthlyNewCustomers,
            MonthlyGrowthRatePercent = CustomerAnalyticsSupport.ToGrowthRatePercent(
                monthlyNewCustomers,
                previousMonthlyNewCustomers),
            ActiveCustomers = activeCustomers,
            AverageAmountLast30Days = averageAmountLast30Days
        };
    }
}
