using System.Globalization;
using System.Text;
using MediatR;
using TakeoutSaaS.Application.App.Finance.Settlement.Dto;
using TakeoutSaaS.Application.App.Finance.Settlement.Queries;
using TakeoutSaaS.Domain.Finance.Repositories;
using TakeoutSaaS.Shared.Abstractions.Tenancy;

namespace TakeoutSaaS.Application.App.Finance.Settlement.Handlers;

/// <summary>
/// 到账汇总导出处理器。
/// </summary>
public sealed class ExportFinanceSettlementCsvQueryHandler(
    IFinanceTransactionRepository financeTransactionRepository,
    ITenantProvider tenantProvider)
    : IRequestHandler<ExportFinanceSettlementCsvQuery, FinanceSettlementExportDto>
{
    /// <inheritdoc />
    public async Task<FinanceSettlementExportDto> Handle(
        ExportFinanceSettlementCsvQuery request,
        CancellationToken cancellationToken)
    {
        var tenantId = tenantProvider.GetCurrentTenantId();
        var rows = await financeTransactionRepository.ListSettlementForExportAsync(
            tenantId,
            request.StoreId,
            request.StartAt,
            request.EndAt,
            request.PaymentMethod,
            cancellationToken);

        var list = rows.Select(FinanceSettlementMapping.ToListItem).ToList();
        var csv = BuildCsv(list);
        return new FinanceSettlementExportDto
        {
            FileName = $"settlement-{request.StoreId}-{DateTime.UtcNow:yyyyMMddHHmmss}.csv",
            FileContentBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(csv)),
            TotalCount = list.Count
        };
    }

    private static string BuildCsv(IReadOnlyList<FinanceSettlementListItemDto> rows)
    {
        var sb = new StringBuilder();
        sb.Append('\uFEFF');
        sb.AppendLine("到账日期,支付渠道,交易笔数,到账金额");

        foreach (var row in rows)
        {
            sb.AppendLine(string.Join(',',
                Escape(row.ArrivedDate.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)),
                Escape(row.ChannelText),
                Escape(row.TransactionCount.ToString(CultureInfo.InvariantCulture)),
                Escape(FinanceSettlementMapping.FormatAmount(row.ArrivedAmount))));
        }

        return sb.ToString();
    }

    private static string Escape(string? value)
    {
        var normalized = value ?? string.Empty;
        if (normalized.Contains(',') || normalized.Contains('"') || normalized.Contains('\n'))
        {
            return $"\"{normalized.Replace("\"", "\"\"", StringComparison.Ordinal)}\"";
        }

        return normalized;
    }
}
