using FsCheck;
using FsCheck.Xunit;
using MilitaryTrainingManagement.Models.Entities;
using MilitaryTrainingManagement.Models.Enums;

namespace MilitaryTrainingManagement.Tests.Properties;

/// <summary>
/// 人员等级分配属性测试
/// **功能：military-training-material-management，属性6：人员等级分配一致性**
/// **验证需求：需求7.2, 7.3, 7.5**
/// </summary>
public class PersonnelLevelAssignmentPropertyTests
{
    /// <summary>
    /// 属性6：人员等级分配一致性
    /// *对于任何*已批准的人员记录，分配的人员等级应与批准单位的组织层级完全对应
    /// **验证需求：需求7.2, 7.3, 7.5**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool Personnel_ApprovedLevel_MustMatchApprovalUnitLevel(OrganizationalLevel unitLevel)
    {
        // 创建审批单位
        var approvalUnit = new OrganizationalUnit
        {
            Id = 1,
            Name = "审批单位",
            Level = unitLevel,
            CreatedAt = DateTime.UtcNow
        };

        // 创建提交单位（必须是下级单位）
        var submittingUnit = new OrganizationalUnit
        {
            Id = 2,
            Name = "提交单位",
            Level = GetLowerLevel(unitLevel),
            ParentId = 1,
            CreatedAt = DateTime.UtcNow
        };

        // 创建人员记录
        var personnel = new Personnel
        {
            Id = 1,
            Name = "测试人员",
            Position = "测试职位",
            Rank = "测试军衔",
            Gender = "男",
            IdNumber = "123456789012345678",
            Age = 25,
            SubmittedByUnitId = submittingUnit.Id,
            SubmittedByUnit = submittingUnit,
            Status = PersonnelStatus.Approved,
            ApprovedByUnitId = approvalUnit.Id,
            ApprovedByUnit = approvalUnit,
            ApprovedLevel = (PersonnelLevel)(int)unitLevel, // 人员等级应与审批单位层级对应
            SubmittedAt = DateTime.UtcNow,
            ApprovedAt = DateTime.UtcNow
        };

        // 验证人员等级与审批单位层级一致
        var expectedPersonnelLevel = (PersonnelLevel)(int)unitLevel;
        return personnel.ApprovedLevel == expectedPersonnelLevel;
    }

    /// <summary>
    /// 属性6扩展：人员等级数值必须与组织层级数值完全匹配
    /// **验证需求：需求7.2, 7.3, 7.5**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool Personnel_LevelNumericValue_MustMatchUnitLevelValue(OrganizationalLevel unitLevel)
    {
        var personnelLevel = (PersonnelLevel)(int)unitLevel;
        
        // 验证数值完全匹配
        return (int)personnelLevel == (int)unitLevel;
    }

    /// <summary>
    /// 属性6扩展：只有有效的组织层级才能审批人员
    /// **验证需求：需求7.2, 7.3, 7.5**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool Personnel_ApprovalUnit_MustHaveValidLevel(OrganizationalLevel unitLevel)
    {
        // 所有组织层级都可以审批人员，但人员等级必须与之对应
        var validLevels = new[]
        {
            OrganizationalLevel.Division,   // 师团 -> 师级人才
            OrganizationalLevel.Regiment,   // 团 -> 团级人才
            OrganizationalLevel.Battalion,  // 营 -> 营级人才
            OrganizationalLevel.Company     // 连 -> 连级人才
        };

        var isValidUnitLevel = validLevels.Contains(unitLevel);
        
        if (isValidUnitLevel)
        {
            var correspondingPersonnelLevel = (PersonnelLevel)(int)unitLevel;
            var validPersonnelLevels = new[]
            {
                PersonnelLevel.Division,   // 师级人才
                PersonnelLevel.Regiment,   // 团级人才
                PersonnelLevel.Battalion,  // 营级人才
                PersonnelLevel.Company     // 连级人才
            };
            
            return validPersonnelLevels.Contains(correspondingPersonnelLevel);
        }

        return false;
    }

    /// <summary>
    /// 属性6扩展：跨层级人员转移时等级必须重新分配
    /// **验证需求：需求7.4, 7.5**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool Personnel_CrossLevelTransfer_MustReassignLevel(
        OrganizationalLevel originalLevel, 
        OrganizationalLevel newLevel)
    {
        // 如果转移到不同层级的单位，人员等级必须相应调整
        if (originalLevel != newLevel)
        {
            var originalPersonnelLevel = (PersonnelLevel)(int)originalLevel;
            var newPersonnelLevel = (PersonnelLevel)(int)newLevel;
            
            // 转移后的人员等级应该与新的审批单位层级一致
            return originalPersonnelLevel != newPersonnelLevel && 
                   (int)newPersonnelLevel == (int)newLevel;
        }
        
        // 同层级转移，等级可以保持不变
        return true;
    }

    /// <summary>
    /// 属性6扩展：人员等级层次结构必须与组织层级层次结构一致
    /// **验证需求：需求7.2, 7.3, 7.5**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool Personnel_LevelHierarchy_MustMatchOrganizationalHierarchy(
        PersonnelLevel level1, 
        PersonnelLevel level2)
    {
        var orgLevel1 = (OrganizationalLevel)(int)level1;
        var orgLevel2 = (OrganizationalLevel)(int)level2;
        
        // 人员等级的层次关系应该与组织层级的层次关系完全一致
        var personnelComparison = (int)level1.CompareTo(level2);
        var organizationalComparison = (int)orgLevel1.CompareTo(orgLevel2);
        
        return personnelComparison == organizationalComparison;
    }

    /// <summary>
    /// 获取更低一级的组织层级（用于创建下级单位）
    /// </summary>
    private static OrganizationalLevel GetLowerLevel(OrganizationalLevel level)
    {
        return level switch
        {
            OrganizationalLevel.Division => OrganizationalLevel.Regiment,
            OrganizationalLevel.Regiment => OrganizationalLevel.Battalion,
            OrganizationalLevel.Battalion => OrganizationalLevel.Company,
            OrganizationalLevel.Company => OrganizationalLevel.Company, // 连级没有下级，返回自己
            _ => OrganizationalLevel.Company
        };
    }
}