using MediatR;
using TakeoutSaaS.Application.App.Members.Commands;
using TakeoutSaaS.Domain.Membership.Repositories;
using TakeoutSaaS.Domain.Orders.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;
using TakeoutSaaS.Shared.Abstractions.Tenancy;

namespace TakeoutSaaS.Application.App.Members.Handlers;

/// <summary>
/// 删除会员等级命令处理器。
/// </summary>
public sealed class DeleteMemberTierCommandHandler(
    IMemberRepository memberRepository,
    IOrderRepository orderRepository,
    ITenantProvider tenantProvider)
    : IRequestHandler<DeleteMemberTierCommand>
{
    /// <inheritdoc />
    public async Task Handle(DeleteMemberTierCommand request, CancellationToken cancellationToken)
    {
        await MemberCenterSupport.EnsureMemberCenterInitializedAsync(
            memberRepository,
            orderRepository,
            tenantProvider,
            cancellationToken);

        var tenantId = tenantProvider.GetCurrentTenantId();
        var tiers = await memberRepository.GetTiersAsync(tenantId, cancellationToken);
        var tier = tiers.FirstOrDefault(item => item.Id == request.TierId)
                   ?? throw new BusinessException(ErrorCodes.NotFound, "会员等级不存在");

        if (tier.IsDefault)
        {
            throw new BusinessException(ErrorCodes.BadRequest, "默认等级不允许删除");
        }

        var profiles = await memberRepository.GetProfilesAsync(tenantId, cancellationToken);
        if (profiles.Any(item => item.MemberTierId == request.TierId))
        {
            throw new BusinessException(ErrorCodes.BadRequest, "当前等级下存在会员，无法删除");
        }

        await memberRepository.DeleteTierAsync(tier, cancellationToken);
        await memberRepository.SaveChangesAsync(cancellationToken);

        var latestTiers = await memberRepository.GetTiersAsync(tenantId, cancellationToken);
        if (!latestTiers.Any(item => item.IsDefault) && latestTiers.Count > 0)
        {
            var fallback = latestTiers
                .OrderBy(item => item.SortOrder)
                .ThenBy(item => item.Id)
                .First();
            fallback.IsDefault = true;
            await memberRepository.UpdateTierAsync(fallback, cancellationToken);
            await memberRepository.SaveChangesAsync(cancellationToken);
        }
    }
}
