using FsCheck;
using FsCheck.Xunit;
using MilitaryTrainingManagement.Models.Entities;
using MilitaryTrainingManagement.Services.Implementations;

namespace MilitaryTrainingManagement.Tests.Properties;

/// <summary>
/// 完成率计算属性测试
/// **功能：military-training-material-management，属性3：完成率计算一致性**
/// **验证需求：需求3.3**
/// </summary>
public class CompletionRatePropertyTests
{
    /// <summary>
    /// 属性3：完成率计算一致性
    /// *对于任何*具有实际完成和单位指标的配额分配，完成率应等于实际完成除以单位指标
    /// **验证需求：需求3.3**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool CompletionRate_EqualsActualCompletionDividedByQuota(
        PositiveInt actualCompletionInt,
        PositiveInt unitQuotaInt)
    {
        var actualCompletion = (decimal)actualCompletionInt.Get;
        var unitQuota = (decimal)unitQuotaInt.Get;

        // 创建分配记录
        var distribution = new AllocationDistribution
        {
            Id = 1,
            AllocationId = 1,
            TargetUnitId = 1,
            UnitQuota = unitQuota,
            ActualCompletion = actualCompletion
        };

        // 计算预期完成率
        var expectedRate = actualCompletion / unitQuota;

        // 验证：完成率应等于实际完成除以单位指标
        return distribution.CompletionRate == expectedRate;
    }

    /// <summary>
    /// 属性3扩展：服务层计算与实体计算一致
    /// **验证需求：需求3.3**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool ServiceCalculation_MatchesEntityCalculation(
        PositiveInt actualCompletionInt,
        PositiveInt unitQuotaInt)
    {
        var actualCompletion = (decimal)actualCompletionInt.Get;
        var unitQuota = (decimal)unitQuotaInt.Get;

        // 创建分配记录
        var distribution = new AllocationDistribution
        {
            Id = 1,
            AllocationId = 1,
            TargetUnitId = 1,
            UnitQuota = unitQuota,
            ActualCompletion = actualCompletion
        };

        // 使用服务层计算（纯函数版本）
        var serviceRate = CalculateCompletionRatePure(actualCompletion, unitQuota);

        // 验证：服务层计算应与实体计算一致
        return distribution.CompletionRate == serviceRate;
    }

    /// <summary>
    /// 属性3扩展：零配额时完成率为零
    /// **验证需求：需求3.3**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool ZeroQuota_ReturnsZeroCompletionRate(PositiveInt actualCompletionInt)
    {
        var actualCompletion = (decimal)actualCompletionInt.Get;

        var distribution = new AllocationDistribution
        {
            Id = 1,
            AllocationId = 1,
            TargetUnitId = 1,
            UnitQuota = 0,
            ActualCompletion = actualCompletion
        };

        // 验证：零配额时完成率应为零（避免除零错误）
        return distribution.CompletionRate == 0;
    }

    /// <summary>
    /// 属性3扩展：无实际完成时完成率为零
    /// **验证需求：需求3.3**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool NullActualCompletion_ReturnsZeroCompletionRate(PositiveInt unitQuotaInt)
    {
        var unitQuota = (decimal)unitQuotaInt.Get;

        var distribution = new AllocationDistribution
        {
            Id = 1,
            AllocationId = 1,
            TargetUnitId = 1,
            UnitQuota = unitQuota,
            ActualCompletion = null
        };

        // 验证：无实际完成时完成率应为零
        return distribution.CompletionRate == 0;
    }

    /// <summary>
    /// 属性3扩展：完成率非负
    /// **验证需求：需求3.3**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool CompletionRate_IsNonNegative(
        PositiveInt actualCompletionInt,
        PositiveInt unitQuotaInt)
    {
        var actualCompletion = (decimal)actualCompletionInt.Get;
        var unitQuota = (decimal)unitQuotaInt.Get;

        var distribution = new AllocationDistribution
        {
            Id = 1,
            AllocationId = 1,
            TargetUnitId = 1,
            UnitQuota = unitQuota,
            ActualCompletion = actualCompletion
        };

        // 验证：完成率应非负
        return distribution.CompletionRate >= 0;
    }

    /// <summary>
    /// 属性3扩展：完成率与实际完成成正比
    /// **验证需求：需求3.3**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool CompletionRate_ProportionalToActualCompletion(
        PositiveInt actualCompletion1Int,
        PositiveInt actualCompletion2Int,
        PositiveInt unitQuotaInt)
    {
        var actualCompletion1 = (decimal)actualCompletion1Int.Get;
        var actualCompletion2 = (decimal)actualCompletion2Int.Get;
        var unitQuota = (decimal)unitQuotaInt.Get;

        var distribution1 = new AllocationDistribution
        {
            Id = 1,
            AllocationId = 1,
            TargetUnitId = 1,
            UnitQuota = unitQuota,
            ActualCompletion = actualCompletion1
        };

        var distribution2 = new AllocationDistribution
        {
            Id = 2,
            AllocationId = 1,
            TargetUnitId = 2,
            UnitQuota = unitQuota,
            ActualCompletion = actualCompletion2
        };

        // 验证：如果实际完成1 > 实际完成2，则完成率1 > 完成率2
        if (actualCompletion1 > actualCompletion2)
            return distribution1.CompletionRate > distribution2.CompletionRate;
        else if (actualCompletion1 < actualCompletion2)
            return distribution1.CompletionRate < distribution2.CompletionRate;
        else
            return distribution1.CompletionRate == distribution2.CompletionRate;
    }

    /// <summary>
    /// 属性3扩展：完成率与配额成反比
    /// **验证需求：需求3.3**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool CompletionRate_InverselyProportionalToQuota(
        PositiveInt actualCompletionInt,
        PositiveInt unitQuota1Int,
        PositiveInt unitQuota2Int)
    {
        var actualCompletion = (decimal)actualCompletionInt.Get;
        var unitQuota1 = (decimal)unitQuota1Int.Get;
        var unitQuota2 = (decimal)unitQuota2Int.Get;

        var distribution1 = new AllocationDistribution
        {
            Id = 1,
            AllocationId = 1,
            TargetUnitId = 1,
            UnitQuota = unitQuota1,
            ActualCompletion = actualCompletion
        };

        var distribution2 = new AllocationDistribution
        {
            Id = 2,
            AllocationId = 1,
            TargetUnitId = 2,
            UnitQuota = unitQuota2,
            ActualCompletion = actualCompletion
        };

        // 验证：如果配额1 > 配额2，则完成率1 < 完成率2（相同实际完成情况下）
        if (unitQuota1 > unitQuota2)
            return distribution1.CompletionRate < distribution2.CompletionRate;
        else if (unitQuota1 < unitQuota2)
            return distribution1.CompletionRate > distribution2.CompletionRate;
        else
            return distribution1.CompletionRate == distribution2.CompletionRate;
    }

    /// <summary>
    /// 纯函数版本的完成率计算（模拟服务层逻辑）
    /// </summary>
    private static decimal CalculateCompletionRatePure(decimal? actualCompletion, decimal unitQuota)
    {
        if (unitQuota <= 0 || !actualCompletion.HasValue)
            return 0;

        return actualCompletion.Value / unitQuota;
    }
}
