using MediatR;
using TakeoutSaaS.Application.App.Members.PointsMall.Commands;
using TakeoutSaaS.Application.App.Members.PointsMall.Dto;
using TakeoutSaaS.Domain.Membership.Repositories;
using TakeoutSaaS.Shared.Abstractions.Tenancy;

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

/// <summary>
/// 保存积分商城规则处理器。
/// </summary>
public sealed class SavePointMallRuleCommandHandler(
    IPointMallRepository repository,
    ITenantProvider tenantProvider)
    : IRequestHandler<SavePointMallRuleCommand, MemberPointMallRuleDto>
{
    /// <inheritdoc />
    public async Task<MemberPointMallRuleDto> Handle(
        SavePointMallRuleCommand request,
        CancellationToken cancellationToken)
    {
        var tenantId = tenantProvider.GetCurrentTenantId();
        var expiryMode = MemberPointMallMapping.ParseExpiryMode(request.ExpiryMode);
        var consumeAmountPerStep = request.IsConsumeRewardEnabled
            ? MemberPointMallMapping.NormalizePositiveInt(request.ConsumeAmountPerStep, "consumeAmountPerStep")
            : Math.Max(1, request.ConsumeAmountPerStep);
        var consumeRewardPointsPerStep = request.IsConsumeRewardEnabled
            ? MemberPointMallMapping.NormalizePositiveInt(request.ConsumeRewardPointsPerStep, "consumeRewardPointsPerStep")
            : Math.Max(0, request.ConsumeRewardPointsPerStep);
        var reviewRewardPoints = request.IsReviewRewardEnabled
            ? MemberPointMallMapping.NormalizePositiveInt(request.ReviewRewardPoints, "reviewRewardPoints")
            : Math.Max(0, request.ReviewRewardPoints);
        var registerRewardPoints = request.IsRegisterRewardEnabled
            ? MemberPointMallMapping.NormalizePositiveInt(request.RegisterRewardPoints, "registerRewardPoints")
            : Math.Max(0, request.RegisterRewardPoints);
        var signinRewardPoints = request.IsSigninRewardEnabled
            ? MemberPointMallMapping.NormalizePositiveInt(request.SigninRewardPoints, "signinRewardPoints")
            : Math.Max(0, request.SigninRewardPoints);

        var existing = await repository.GetRuleByStoreAsync(
            tenantId,
            request.StoreId,
            cancellationToken);

        if (existing is null)
        {
            var created = MemberPointMallDtoFactory.CreateRuleEntity(request, expiryMode);
            created.ConsumeAmountPerStep = consumeAmountPerStep;
            created.ConsumeRewardPointsPerStep = consumeRewardPointsPerStep;
            created.ReviewRewardPoints = reviewRewardPoints;
            created.RegisterRewardPoints = registerRewardPoints;
            created.SigninRewardPoints = signinRewardPoints;
            await repository.AddRuleAsync(created, cancellationToken);
            await repository.SaveChangesAsync(cancellationToken);

            return MemberPointMallDtoFactory.ToRuleDto(created);
        }

        existing.IsConsumeRewardEnabled = request.IsConsumeRewardEnabled;
        existing.ConsumeAmountPerStep = consumeAmountPerStep;
        existing.ConsumeRewardPointsPerStep = consumeRewardPointsPerStep;
        existing.IsReviewRewardEnabled = request.IsReviewRewardEnabled;
        existing.ReviewRewardPoints = reviewRewardPoints;
        existing.IsRegisterRewardEnabled = request.IsRegisterRewardEnabled;
        existing.RegisterRewardPoints = registerRewardPoints;
        existing.IsSigninRewardEnabled = request.IsSigninRewardEnabled;
        existing.SigninRewardPoints = signinRewardPoints;
        existing.ExpiryMode = expiryMode;

        await repository.UpdateRuleAsync(existing, cancellationToken);
        await repository.SaveChangesAsync(cancellationToken);

        return MemberPointMallDtoFactory.ToRuleDto(existing);
    }
}
