using FluentValidation;
using TakeoutSaaS.Application.App.Stores.Commands;
using TakeoutSaaS.Domain.Stores.Enums;

namespace TakeoutSaaS.Application.App.Stores.Validators;

/// <summary>
/// 更新门店费用配置命令验证器。
/// </summary>
public sealed class UpdateStoreFeeCommandValidator : AbstractValidator<UpdateStoreFeeCommand>
{
    /// <summary>
    /// 初始化验证规则。
    /// </summary>
    public UpdateStoreFeeCommandValidator()
    {
        RuleFor(x => x.StoreId).GreaterThan(0);
        RuleFor(x => x.MinimumOrderAmount).GreaterThanOrEqualTo(0).LessThanOrEqualTo(9999.99m);
        RuleFor(x => x.DeliveryFee).GreaterThanOrEqualTo(0).LessThanOrEqualTo(999.99m);
        RuleFor(x => x.PlatformServiceRate).GreaterThanOrEqualTo(0).LessThanOrEqualTo(100m);
        RuleFor(x => x.FreeDeliveryThreshold).GreaterThanOrEqualTo(0).When(x => x.FreeDeliveryThreshold.HasValue);

        RuleFor(x => x.FixedPackagingFee)
            .NotNull()
            .When(x => x.PackagingFeeMode == PackagingFeeMode.Fixed && x.OrderPackagingFeeMode == OrderPackagingFeeMode.Fixed)
            .WithMessage("总计打包费模式下必须填写固定打包费");

        RuleFor(x => x.FixedPackagingFee)
            .Must(fee => !fee.HasValue || fee.Value <= 99.99m)
            .WithMessage("固定打包费不能超过 99.99");

        RuleFor(x => x.FixedPackagingFee)
            .Must(fee => !fee.HasValue || fee.Value >= 0)
            .WithMessage("固定打包费不能为负数");

        RuleFor(x => x.CutleryFeeAmount)
            .GreaterThanOrEqualTo(0)
            .LessThanOrEqualTo(99.99m);

        RuleFor(x => x.RushFeeAmount)
            .GreaterThanOrEqualTo(0)
            .LessThanOrEqualTo(99.99m);

        RuleFor(x => x)
            .Custom((command, context) =>
            {
                if (command.PackagingFeeMode != PackagingFeeMode.Fixed || command.OrderPackagingFeeMode != OrderPackagingFeeMode.Tiered)
                {
                    return;
                }

                if (command.PackagingFeeTiers is null || command.PackagingFeeTiers.Count == 0)
                {
                    context.AddFailure("阶梯价模式必须配置至少 1 个区间");
                    return;
                }

                if (command.PackagingFeeTiers.Count > 10)
                {
                    context.AddFailure("阶梯价最多支持 10 个区间");
                    return;
                }

                var expectedMin = 0m;
                for (var index = 0; index < command.PackagingFeeTiers.Count; index++)
                {
                    var tier = command.PackagingFeeTiers[index];
                    if (tier.Fee < 0 || tier.Fee > 99.99m)
                    {
                        context.AddFailure($"第 {index + 1} 个阶梯打包费需在 0~99.99 之间");
                        return;
                    }

                    if (tier.MaxPrice.HasValue && tier.MaxPrice.Value <= expectedMin)
                    {
                        context.AddFailure($"第 {index + 1} 个阶梯上限必须大于 {expectedMin:0.##}");
                        return;
                    }

                    if (!tier.MaxPrice.HasValue && index != command.PackagingFeeTiers.Count - 1)
                    {
                        context.AddFailure("仅允许最后一个阶梯的上限为空");
                        return;
                    }

                    if (tier.MaxPrice.HasValue && tier.MaxPrice.Value > 99999.99m)
                    {
                        context.AddFailure($"第 {index + 1} 个阶梯上限不能超过 99999.99");
                        return;
                    }

                    expectedMin = tier.MaxPrice ?? expectedMin;
                }
            });
    }
}
