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 GetCustomerMemberDetailQueryHandler(
    IOrderRepository orderRepository,
    IDapperExecutor dapperExecutor,
    ITenantProvider tenantProvider)
    : IRequestHandler<GetCustomerMemberDetailQuery, CustomerMemberDetailDto?>
{
    /// <inheritdoc />
    public async Task<CustomerMemberDetailDto?> Handle(
        GetCustomerMemberDetailQuery request,
        CancellationToken cancellationToken)
    {
        var customerKey = CustomerAnalyticsSupport.NormalizePhone(request.CustomerKey);
        if (request.VisibleStoreIds.Count == 0 || string.IsNullOrWhiteSpace(customerKey))
        {
            return null;
        }

        var customers = await CustomerAnalyticsSupport.LoadCustomersAsync(
            orderRepository,
            dapperExecutor,
            tenantProvider,
            request.VisibleStoreIds,
            cancellationToken);

        var customer = customers.FirstOrDefault(item =>
            string.Equals(item.CustomerKey, customerKey, StringComparison.Ordinal));
        if (customer is null)
        {
            return null;
        }

        var tenantId = tenantProvider.GetCurrentTenantId();
        if (tenantId <= 0)
        {
            return null;
        }

        var orderIds = customer.Orders
            .Select(item => item.OrderId)
            .ToList();

        var itemLookup = await orderRepository.GetItemsByOrderIdsAsync(orderIds, tenantId, cancellationToken);
        var recentOrders = CustomerAnalyticsSupport.BuildRecentOrders(customer.Orders, itemLookup, 5);
        var repurchaseRatePercent = CustomerAnalyticsSupport.ToRatePercent(
            Math.Max(0, customer.OrderCount - 1),
            customer.OrderCount);

        return new CustomerMemberDetailDto
        {
            CustomerKey = customer.CustomerKey,
            Name = customer.Name,
            PhoneMasked = customer.PhoneMasked,
            Source = customer.Source,
            RegisteredAt = customer.RegisteredAt,
            LastOrderAt = customer.LastOrderAt,
            Member = customer.Member,
            Tags = customer.Tags,
            TotalOrders = customer.OrderCount,
            TotalAmount = customer.TotalAmount,
            AverageAmount = customer.AverageAmount,
            RepurchaseRatePercent = repurchaseRatePercent,
            RecentOrders = recentOrders
        };
    }
}
