using Jiaowu.Api.Domain.Academic;

namespace Jiaowu.Api.Infrastructure.Graduation;

public enum StudentCourseProgressStatus
{
    NotStarted = 1,
    InProgress = 2,
    Retaking = 3,
    Completed = 4,
    Failed = 5,
    Pending = 6
}

public sealed record StudentCourseAttemptSnapshot(
    decimal? TotalScore,
    GradeExamStatus ExamStatus);

public sealed record StudentCourseProgressEvaluation(
    StudentCourseProgressStatus Status,
    bool HasPassedAttempt,
    bool HasFailedAttempt);

public static class StudentCourseProgressRules
{
    public static StudentCourseProgressEvaluation Evaluate(
        IEnumerable<StudentCourseAttemptSnapshot> attempts,
        bool isInProgress)
    {
        var attemptList = attempts.ToList();
        var hasPassedAttempt = attemptList.Any(IsPassed);
        var hasFailedAttempt = attemptList.Any(IsFailed);
        var hasPendingAttempt = attemptList.Any(x =>
            !IsPassed(x) &&
            !IsFailed(x));

        var status = hasPassedAttempt
            ? StudentCourseProgressStatus.Completed
            : isInProgress && hasFailedAttempt
                ? StudentCourseProgressStatus.Retaking
                : isInProgress
                    ? StudentCourseProgressStatus.InProgress
                    : hasFailedAttempt
                        ? StudentCourseProgressStatus.Failed
                        : hasPendingAttempt
                            ? StudentCourseProgressStatus.Pending
                            : StudentCourseProgressStatus.NotStarted;

        return new StudentCourseProgressEvaluation(
            status,
            hasPassedAttempt,
            hasFailedAttempt);
    }

    public static bool IsPassed(StudentCourseAttemptSnapshot attempt) =>
        attempt.ExamStatus == GradeExamStatus.Exempt ||
        attempt.TotalScore is decimal score && score >= 60;

    public static bool IsFailed(StudentCourseAttemptSnapshot attempt) =>
        attempt.ExamStatus == GradeExamStatus.Absent ||
        attempt.TotalScore is decimal score && score < 60;
}
