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

namespace TakeoutSaaS.Application.App.Members.PointsMall.Handlers;

/// <summary>
/// 导出积分商城兑换记录处理器。
/// </summary>
public sealed class ExportPointMallRecordCsvQueryHandler(
    IPointMallRepository repository,
    ITenantProvider tenantProvider)
    : IRequestHandler<ExportPointMallRecordCsvQuery, MemberPointMallRecordExportDto>
{
    /// <inheritdoc />
    public async Task<MemberPointMallRecordExportDto> Handle(
        ExportPointMallRecordCsvQuery request,
        CancellationToken cancellationToken)
    {
        var tenantId = tenantProvider.GetCurrentTenantId();
        var redeemType = MemberPointMallMapping.TryParseRedeemType(request.RedeemType);
        var status = MemberPointMallMapping.TryParseRecordStatus(request.Status);
        var keyword = MemberPointMallMapping.NormalizeKeyword(request.Keyword);
        var (startUtc, endUtc) = MemberPointMallMapping.NormalizeDateRange(
            request.StartDateUtc,
            request.EndDateUtc);

        var records = await repository.ListRecordsForExportAsync(
            tenantId,
            request.StoreId,
            redeemType,
            status,
            startUtc,
            endUtc,
            keyword,
            cancellationToken);

        var csv = BuildCsv(records);
        var bytes = Encoding.UTF8.GetBytes($"\uFEFF{csv}");

        return new MemberPointMallRecordExportDto
        {
            FileName = $"积分商城兑换记录_{DateTime.UtcNow:yyyyMMddHHmmss}.csv",
            FileContentBase64 = Convert.ToBase64String(bytes),
            TotalCount = records.Count
        };
    }

    private static string BuildCsv(IReadOnlyCollection<MemberPointMallRecord> records)
    {
        var lines = new List<string>
        {
            "兑换单号,会员,手机号,兑换商品,类型,消耗积分,现金部分,兑换时间,状态,核销时间"
        };

        foreach (var item in records)
        {
            lines.Add(string.Join(",",
                Escape(item.RecordNo),
                Escape(item.MemberName),
                Escape(item.MemberMobileMasked),
                Escape(item.ProductName),
                Escape(MemberPointMallMapping.ToRedeemTypeDisplayText(item.RedeemType)),
                item.UsedPoints.ToString(),
                item.CashAmount.ToString("0.00"),
                Escape(item.RedeemedAt.ToString("yyyy-MM-dd HH:mm:ss")),
                Escape(MemberPointMallMapping.ToRecordStatusDisplayText(item.Status)),
                Escape(item.VerifiedAt?.ToString("yyyy-MM-dd HH:mm:ss") ?? string.Empty)));
        }

        return string.Join('\n', lines);
    }

    private static string Escape(string value)
    {
        var normalized = value.Replace("\"", "\"\"");
        return $"\"{normalized}\"";
    }
}
