using MediatR;
using TakeoutSaaS.Application.App.Members.Commands;
using TakeoutSaaS.Application.App.Members.Dto;
using TakeoutSaaS.Domain.Membership.Entities;
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 SaveMemberDaySettingCommandHandler(
    IMemberRepository memberRepository,
    IOrderRepository orderRepository,
    ITenantProvider tenantProvider)
    : IRequestHandler<SaveMemberDaySettingCommand, MemberDaySettingDto>
{
    /// <inheritdoc />
    public async Task<MemberDaySettingDto> Handle(
        SaveMemberDaySettingCommand request,
        CancellationToken cancellationToken)
    {
        await MemberCenterSupport.EnsureMemberCenterInitializedAsync(
            memberRepository,
            orderRepository,
            tenantProvider,
            cancellationToken);

        if (request.Weekday is < 1 or > 7)
        {
            throw new BusinessException(ErrorCodes.BadRequest, "weekday 必须在 1-7 之间");
        }

        var normalizedDiscount = decimal.Round(request.ExtraDiscountRate, 2, MidpointRounding.AwayFromZero);
        if (normalizedDiscount <= 0 || normalizedDiscount > 10)
        {
            throw new BusinessException(ErrorCodes.BadRequest, "extraDiscountRate 必须大于 0 且不超过 10");
        }

        var tenantId = tenantProvider.GetCurrentTenantId();
        var setting = await memberRepository.GetMemberDaySettingAsync(tenantId, cancellationToken);
        if (setting is null)
        {
            setting = new MemberDaySetting
            {
                IsEnabled = request.IsEnabled,
                Weekday = request.Weekday,
                ExtraDiscountRate = normalizedDiscount
            };
            await memberRepository.AddMemberDaySettingAsync(setting, cancellationToken);
        }
        else
        {
            setting.IsEnabled = request.IsEnabled;
            setting.Weekday = request.Weekday;
            setting.ExtraDiscountRate = normalizedDiscount;
            await memberRepository.UpdateMemberDaySettingAsync(setting, cancellationToken);
        }

        await memberRepository.SaveChangesAsync(cancellationToken);
        return MemberCenterSupport.ToMemberDaySettingDto(setting);
    }
}
