using System.Text;
using MediatR;
using TakeoutSaaS.Application.App.Members.Dto;
using TakeoutSaaS.Application.App.Members.Queries;
using TakeoutSaaS.Domain.Membership.Repositories;
using TakeoutSaaS.Domain.Orders.Repositories;
using TakeoutSaaS.Shared.Abstractions.Tenancy;

namespace TakeoutSaaS.Application.App.Members.Handlers;

/// <summary>
/// 会员列表 CSV 导出查询处理器。
/// </summary>
public sealed class ExportMemberCsvQueryHandler(
    IMemberRepository memberRepository,
    IOrderRepository orderRepository,
    ITenantProvider tenantProvider)
    : IRequestHandler<ExportMemberCsvQuery, MemberExportDto>
{
    /// <inheritdoc />
    public async Task<MemberExportDto> Handle(
        ExportMemberCsvQuery request,
        CancellationToken cancellationToken)
    {
        if (request.VisibleStoreIds.Count == 0)
        {
            return new MemberExportDto
            {
                FileName = BuildFileName(),
                FileContentBase64 = string.Empty,
                TotalCount = 0
            };
        }

        var context = await MemberCenterSupport.LoadMemberContextAsync(
            memberRepository,
            orderRepository,
            tenantProvider,
            request.VisibleStoreIds,
            cancellationToken);

        var filtered = MemberCenterSupport.ApplyFilters(
            context.Aggregates,
            request.Keyword,
            request.TierId)
            .OrderByDescending(item => item.Metrics.LastOrderAt)
            .ThenByDescending(item => item.MemberId)
            .ToList();

        var rows = filtered
            .Select(item => new MemberListItemDto
            {
                MemberId = item.MemberId,
                Name = item.Name,
                AvatarText = item.AvatarText,
                AvatarColor = item.AvatarColor,
                MobileMasked = item.MobileMasked,
                TierId = item.Tier?.Id,
                TierName = item.Tier?.Name ?? string.Empty,
                TierColorHex = item.Tier?.ColorHex ?? "#999999",
                TotalAmount = decimal.Round(item.Metrics.TotalAmount, 2, MidpointRounding.AwayFromZero),
                OrderCount = item.Metrics.TotalOrderCount,
                LastOrderAt = item.Metrics.LastOrderAt,
                StoredBalance = item.Profile.StoredBalance,
                PointsBalance = Math.Max(0, item.Profile.PointsBalance),
                IsDormant = item.IsDormant
            })
            .ToList();

        var csv = MemberCenterSupport.BuildCsv(rows);
        var payload = Encoding.UTF8.GetPreamble()
            .Concat(Encoding.UTF8.GetBytes(csv))
            .ToArray();

        return new MemberExportDto
        {
            FileName = BuildFileName(),
            FileContentBase64 = Convert.ToBase64String(payload),
            TotalCount = rows.Count
        };
    }

    private static string BuildFileName()
    {
        return $"member-list-{DateTime.UtcNow:yyyyMMddHHmmss}.csv";
    }
}
