using System.Globalization;
using System.Text;
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>
/// 客户列表 CSV 导出处理器。
/// </summary>
public sealed class ExportCustomerCsvQueryHandler(
    IOrderRepository orderRepository,
    IDapperExecutor dapperExecutor,
    ITenantProvider tenantProvider)
    : IRequestHandler<ExportCustomerCsvQuery, CustomerExportDto>
{
    /// <inheritdoc />
    public async Task<CustomerExportDto> Handle(
        ExportCustomerCsvQuery request,
        CancellationToken cancellationToken)
    {
        if (request.VisibleStoreIds.Count == 0)
        {
            return BuildExport([], 0);
        }

        // 1. 加载聚合并应用筛选
        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)
            .OrderByDescending(item => item.LastOrderAt)
            .ThenBy(item => item.CustomerKey, StringComparer.Ordinal)
            .ToList();

        return BuildExport(filteredCustomers, filteredCustomers.Count);
    }

    private static CustomerExportDto BuildExport(
        IReadOnlyList<CustomerAggregate> customers,
        int totalCount)
    {
        var csv = BuildCsv(customers);
        var bytes = Encoding.UTF8.GetPreamble().Concat(Encoding.UTF8.GetBytes(csv)).ToArray();

        return new CustomerExportDto
        {
            FileName = $"客户列表_{DateTime.UtcNow:yyyyMMddHHmmss}.csv",
            FileContentBase64 = Convert.ToBase64String(bytes),
            TotalCount = totalCount
        };
    }

    private static string BuildCsv(IReadOnlyList<CustomerAggregate> customers)
    {
        var sb = new StringBuilder();
        sb.AppendLine("客户名称,手机号,下单次数,累计消费,客单价,最近下单时间,注册时间,客户标签");

        foreach (var customer in customers)
        {
            var tags = customer.Tags.Count == 0
                ? string.Empty
                : string.Join('、', customer.Tags.Select(item => item.Label));

            var row = new[]
            {
                Escape(customer.Name),
                Escape(customer.PhoneMasked),
                Escape(customer.OrderCount.ToString(CultureInfo.InvariantCulture)),
                Escape(customer.TotalAmount.ToString("0.00", CultureInfo.InvariantCulture)),
                Escape(customer.AverageAmount.ToString("0.00", CultureInfo.InvariantCulture)),
                Escape(customer.LastOrderAt.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)),
                Escape(customer.RegisteredAt.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)),
                Escape(tags)
            };

            sb.AppendLine(string.Join(',', row));
        }

        return sb.ToString();
    }

    private static string Escape(string input)
    {
        if (!input.Contains('"') && !input.Contains(',') && !input.Contains('\n') && !input.Contains('\r'))
        {
            return input;
        }

        return $"\"{input.Replace("\"", "\"\"")}\"";
    }
}
