using Jiaowu.Api.Domain.Academic;
using Jiaowu.Api.Infrastructure.Graduation;

namespace Jiaowu.Api.Tests;

public sealed class AcademicPlanningRulesTests
{
    private static readonly Guid AdvancedCourseId = Guid.NewGuid();
    private static readonly Guid PrerequisiteCourseId = Guid.NewGuid();

    private static readonly AcademicPlanningCourseSnapshot[] Courses =
    [
        new(
            PrerequisiteCourseId,
            "程序设计基础",
            4,
            1,
            CurriculumCourseType.Required,
            []),
        new(
            AdvancedCourseId,
            "数据结构",
            4,
            2,
            CurriculumCourseType.Required,
            [PrerequisiteCourseId])
    ];

    [Fact]
    public void Prerequisite_must_be_completed_or_planned_in_an_earlier_term()
    {
        var sameTerm = AcademicPlanningRules.FindPrerequisiteIssues(
            Courses,
            new HashSet<Guid>(),
            new HashSet<Guid>(),
            new Dictionary<Guid, int>
            {
                [PrerequisiteCourseId] = 3,
                [AdvancedCourseId] = 3
            });

        var correctOrder = AcademicPlanningRules.FindPrerequisiteIssues(
            Courses,
            new HashSet<Guid>(),
            new HashSet<Guid>(),
            new Dictionary<Guid, int>
            {
                [PrerequisiteCourseId] = 3,
                [AdvancedCourseId] = 4
            });

        Assert.Single(sameTerm);
        Assert.Empty(correctOrder);
    }

    [Fact]
    public void In_progress_prerequisite_unlocks_next_term_suggestion()
    {
        var suggestion = AcademicPlanningRules.SuggestNextSemester(
            Courses,
            new HashSet<Guid>(),
            new HashSet<Guid>([PrerequisiteCourseId]),
            2);

        Assert.Equal([AdvancedCourseId], suggestion);
    }

    [Theory]
    [InlineData(0, 0, 5, 4, 4)]
    [InlineData(25, 0, 5, 4, 6)]
    [InlineData(0, 7, 5, 4, 6)]
    public void Completion_estimate_uses_credit_and_requirement_capacity(
        decimal remainingCredits,
        int remainingRequirements,
        int nextSemester,
        int latestPlannedSemester,
        int expectedSemester)
    {
        Assert.Equal(
            expectedSemester,
            AcademicPlanningRules.EstimateCompletionSemester(
                nextSemester,
                latestPlannedSemester,
                remainingCredits,
                remainingRequirements));
    }
}
