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

namespace MilitaryTrainingManagement.Tests.Properties;

/// <summary>
/// 数据汇总属性测试
/// **功能：military-training-material-management，属性4：层级数据汇总**
/// **验证需求：需求3.4, 4.1**
/// </summary>
public class DataAggregationPropertyTests
{
    /// <summary>
    /// 属性4：层级数据汇总
    /// *对于任何*组织单位，显示的汇总数据应等于所有直接下级单位数据的总和
    /// **验证需求：需求3.4, 4.1**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool HierarchicalAggregation_ParentTotalEqualsSubordinateSum(
        PositiveInt quota1Int,
        PositiveInt quota2Int,
        PositiveInt quota3Int,
        PositiveInt completion1Int,
        PositiveInt completion2Int,
        PositiveInt completion3Int)
    {
        var quota1 = (decimal)quota1Int.Get;
        var quota2 = (decimal)quota2Int.Get;
        var quota3 = (decimal)quota3Int.Get;
        var completion1 = (decimal)completion1Int.Get;
        var completion2 = (decimal)completion2Int.Get;
        var completion3 = (decimal)completion3Int.Get;

        // 创建下级单位汇总数据
        var subordinateSummaries = new List<SubordinateUnitSummary>
        {
            new SubordinateUnitSummary
            {
                UnitId = 1,
                UnitName = "团1",
                UnitLevel = "Regiment",
                TotalQuota = quota1,
                TotalActualCompletion = completion1,
                CompletionRate = quota1 > 0 ? completion1 / quota1 : 0
            },
            new SubordinateUnitSummary
            {
                UnitId = 2,
                UnitName = "团2",
                UnitLevel = "Regiment",
                TotalQuota = quota2,
                TotalActualCompletion = completion2,
                CompletionRate = quota2 > 0 ? completion2 / quota2 : 0
            },
            new SubordinateUnitSummary
            {
                UnitId = 3,
                UnitName = "团3",
                UnitLevel = "Regiment",
                TotalQuota = quota3,
                TotalActualCompletion = completion3,
                CompletionRate = quota3 > 0 ? completion3 / quota3 : 0
            }
        };

        // 计算父级汇总（应等于下级总和）
        var parentTotalQuota = quota1 + quota2 + quota3;
        var parentTotalActualCompletion = completion1 + completion2 + completion3;

        // 验证：父级汇总应等于所有下级单位数据的总和
        var subordinateTotalQuota = subordinateSummaries.Sum(s => s.TotalQuota);
        var subordinateTotalActualCompletion = subordinateSummaries.Sum(s => s.TotalActualCompletion);

        return parentTotalQuota == subordinateTotalQuota &&
               parentTotalActualCompletion == subordinateTotalActualCompletion;
    }

    /// <summary>
    /// 属性4扩展：汇总配额总和等于各分配配额之和
    /// **验证需求：需求3.4, 4.1**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool AggregatedQuota_EqualsSumOfDistributions(
        PositiveInt quota1Int,
        PositiveInt quota2Int,
        PositiveInt quota3Int,
        PositiveInt quota4Int)
    {
        var quota1 = (decimal)quota1Int.Get;
        var quota2 = (decimal)quota2Int.Get;
        var quota3 = (decimal)quota3Int.Get;
        var quota4 = (decimal)quota4Int.Get;

        // 创建分配记录
        var distributions = new List<AllocationDistribution>
        {
            CreateDistribution(1, quota1, quota1 * 0.8m),
            CreateDistribution(2, quota2, quota2 * 0.6m),
            CreateDistribution(3, quota3, quota3 * 0.9m),
            CreateDistribution(4, quota4, quota4 * 0.5m)
        };

        // 使用服务计算汇总
        var aggregator = new TestDataAggregator();
        var totalQuota = aggregator.SumTotalQuota(distributions);
        var expectedTotal = quota1 + quota2 + quota3 + quota4;

        // 验证：汇总配额应等于各分配配额之和
        return totalQuota == expectedTotal;
    }

    /// <summary>
    /// 属性4扩展：汇总实际完成等于各分配实际完成之和
    /// **验证需求：需求3.4, 4.1**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool AggregatedActualCompletion_EqualsSumOfDistributions(
        PositiveInt completion1Int,
        PositiveInt completion2Int,
        PositiveInt completion3Int)
    {
        var completion1 = (decimal)completion1Int.Get;
        var completion2 = (decimal)completion2Int.Get;
        var completion3 = (decimal)completion3Int.Get;

        // 创建分配记录
        var distributions = new List<AllocationDistribution>
        {
            CreateDistribution(1, 100m, completion1),
            CreateDistribution(2, 100m, completion2),
            CreateDistribution(3, 100m, completion3)
        };

        // 使用服务计算汇总
        var aggregator = new TestDataAggregator();
        var totalActualCompletion = aggregator.SumTotalActualCompletion(distributions);
        var expectedTotal = completion1 + completion2 + completion3;

        // 验证：汇总实际完成应等于各分配实际完成之和
        return totalActualCompletion == expectedTotal;
    }

    /// <summary>
    /// 属性4扩展：整体完成率等于总实际完成除以总配额
    /// **验证需求：需求3.4, 4.1**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool OverallCompletionRate_EqualsTotalCompletionDividedByTotalQuota(
        PositiveInt totalQuotaInt,
        PositiveInt totalCompletionInt)
    {
        var totalQuota = (decimal)totalQuotaInt.Get;
        var totalCompletion = (decimal)totalCompletionInt.Get;

        var aggregator = new TestDataAggregator();
        var overallRate = aggregator.CalculateOverallCompletionRate(totalQuota, totalCompletion);
        var expectedRate = totalCompletion / totalQuota;

        // 验证：整体完成率应等于总实际完成除以总配额
        return overallRate == expectedRate;
    }

    /// <summary>
    /// 属性4扩展：零配额时整体完成率为零
    /// **验证需求：需求3.4, 4.1**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool ZeroTotalQuota_ReturnsZeroOverallCompletionRate(PositiveInt totalCompletionInt)
    {
        var totalCompletion = (decimal)totalCompletionInt.Get;

        var aggregator = new TestDataAggregator();
        var overallRate = aggregator.CalculateOverallCompletionRate(0, totalCompletion);

        // 验证：零配额时整体完成率应为零
        return overallRate == 0;
    }

    /// <summary>
    /// 属性4扩展：空分配列表的汇总为零
    /// **验证需求：需求3.4, 4.1**
    /// </summary>
    [Fact]
    public void EmptyDistributions_ReturnsZeroAggregation()
    {
        var distributions = new List<AllocationDistribution>();

        var aggregator = new TestDataAggregator();
        var totalQuota = aggregator.SumTotalQuota(distributions);
        var totalActualCompletion = aggregator.SumTotalActualCompletion(distributions);

        // 验证：空分配列表的汇总应为零
        Assert.Equal(0, totalQuota);
        Assert.Equal(0, totalActualCompletion);
    }

    /// <summary>
    /// 属性4扩展：无实际完成的分配汇总为零
    /// **验证需求：需求3.4, 4.1**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool NullActualCompletion_TreatedAsZero(
        PositiveInt quota1Int,
        PositiveInt quota2Int)
    {
        var quota1 = (decimal)quota1Int.Get;
        var quota2 = (decimal)quota2Int.Get;

        // 创建分配记录，部分没有实际完成
        var distributions = new List<AllocationDistribution>
        {
            new AllocationDistribution
            {
                Id = 1,
                AllocationId = 1,
                TargetUnitId = 1,
                UnitQuota = quota1,
                ActualCompletion = null
            },
            new AllocationDistribution
            {
                Id = 2,
                AllocationId = 1,
                TargetUnitId = 2,
                UnitQuota = quota2,
                ActualCompletion = null
            }
        };

        var aggregator = new TestDataAggregator();
        var totalActualCompletion = aggregator.SumTotalActualCompletion(distributions);

        // 验证：无实际完成的分配应被视为零
        return totalActualCompletion == 0;
    }

    /// <summary>
    /// 属性4扩展：验证汇总一致性方法
    /// **验证需求：需求3.4, 4.1**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool ValidateAggregationConsistency_ReturnsTrueForConsistentData(
        PositiveInt quota1Int,
        PositiveInt quota2Int,
        PositiveInt completion1Int,
        PositiveInt completion2Int)
    {
        var quota1 = (decimal)quota1Int.Get;
        var quota2 = (decimal)quota2Int.Get;
        var completion1 = (decimal)completion1Int.Get;
        var completion2 = (decimal)completion2Int.Get;

        var subordinateSummaries = new List<SubordinateUnitSummary>
        {
            new SubordinateUnitSummary
            {
                UnitId = 1,
                UnitName = "团1",
                TotalQuota = quota1,
                TotalActualCompletion = completion1
            },
            new SubordinateUnitSummary
            {
                UnitId = 2,
                UnitName = "团2",
                TotalQuota = quota2,
                TotalActualCompletion = completion2
            }
        };

        var parentTotalQuota = quota1 + quota2;
        var parentTotalActualCompletion = completion1 + completion2;

        var aggregator = new TestDataAggregator();
        var isConsistent = aggregator.ValidateAggregationConsistency(
            parentTotalQuota,
            parentTotalActualCompletion,
            subordinateSummaries);

        // 验证：一致的数据应返回true
        return isConsistent;
    }

    /// <summary>
    /// 属性4扩展：验证汇总不一致性检测
    /// **验证需求：需求3.4, 4.1**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool ValidateAggregationConsistency_ReturnsFalseForInconsistentData(
        PositiveInt quota1Int,
        PositiveInt quota2Int,
        PositiveInt extraInt)
    {
        var quota1 = (decimal)quota1Int.Get;
        var quota2 = (decimal)quota2Int.Get;
        var extra = (decimal)(extraInt.Get % 100 + 1); // 确保有差异

        var subordinateSummaries = new List<SubordinateUnitSummary>
        {
            new SubordinateUnitSummary
            {
                UnitId = 1,
                UnitName = "团1",
                TotalQuota = quota1,
                TotalActualCompletion = quota1 * 0.5m
            },
            new SubordinateUnitSummary
            {
                UnitId = 2,
                UnitName = "团2",
                TotalQuota = quota2,
                TotalActualCompletion = quota2 * 0.5m
            }
        };

        // 父级数据与下级总和不一致
        var parentTotalQuota = quota1 + quota2 + extra;
        var parentTotalActualCompletion = (quota1 + quota2) * 0.5m;

        var aggregator = new TestDataAggregator();
        var isConsistent = aggregator.ValidateAggregationConsistency(
            parentTotalQuota,
            parentTotalActualCompletion,
            subordinateSummaries);

        // 验证：不一致的数据应返回false
        return !isConsistent;
    }

    /// <summary>
    /// 创建分配记录辅助方法
    /// </summary>
    private static AllocationDistribution CreateDistribution(int id, decimal quota, decimal? completion)
    {
        return new AllocationDistribution
        {
            Id = id,
            AllocationId = 1,
            TargetUnitId = id,
            UnitQuota = quota,
            ActualCompletion = completion
        };
    }

    /// <summary>
    /// 测试用数据汇总器（不依赖数据库）
    /// </summary>
    private class TestDataAggregator
    {
        public decimal SumTotalQuota(IEnumerable<AllocationDistribution> distributions)
        {
            return distributions.Sum(d => d.UnitQuota);
        }

        public decimal SumTotalActualCompletion(IEnumerable<AllocationDistribution> distributions)
        {
            return distributions.Sum(d => d.ActualCompletion ?? 0);
        }

        public decimal CalculateOverallCompletionRate(decimal totalQuota, decimal totalActualCompletion)
        {
            if (totalQuota <= 0)
                return 0;

            return totalActualCompletion / totalQuota;
        }

        public bool ValidateAggregationConsistency(
            decimal parentTotalQuota,
            decimal parentTotalActualCompletion,
            IEnumerable<SubordinateUnitSummary> subordinateSummaries)
        {
            var summaryList = subordinateSummaries.ToList();

            if (!summaryList.Any())
                return true;

            var subordinateTotalQuota = summaryList.Sum(s => s.TotalQuota);
            var subordinateTotalActualCompletion = summaryList.Sum(s => s.TotalActualCompletion);

            return parentTotalQuota == subordinateTotalQuota &&
                   parentTotalActualCompletion == subordinateTotalActualCompletion;
        }
    }
}
