using Jiaowu.Api.Domain.Academic;

namespace Jiaowu.Api.Infrastructure.Grades;

public static class ExperimentGradeCalculator
{
    public static bool AreWeightsValid(
        decimal contributionWeight,
        decimal passScore,
        IEnumerable<ExperimentGradeItem> items)
    {
        var itemList = items.ToList();
        return contributionWeight is > 0 and <= 100 &&
               passScore is >= 0 and <= 100 &&
               itemList.Count > 0 &&
               itemList.All(item => item.Weight is > 0 and <= 100) &&
               itemList.Sum(item => item.Weight) == 100;
    }

    public static decimal? CalculateTotal(
        ExperimentGradeRecord record,
        IReadOnlyCollection<ExperimentGradeItem> items)
    {
        if (record.SafetyViolation ||
            record.ParticipationStatus == ExperimentParticipationStatus.Absent)
            return 0;
        if (record.ParticipationStatus is
            ExperimentParticipationStatus.Pending or
            ExperimentParticipationStatus.Excused or
            ExperimentParticipationStatus.Exempt)
            return null;

        var scores = record.ItemScores.ToDictionary(
            x => x.ExperimentGradeItemId);
        decimal total = 0;
        foreach (var item in items)
        {
            if (!scores.TryGetValue(item.Id, out var score) ||
                !score.Score.HasValue)
                return null;
            total += score.Score.Value * item.Weight / 100;
        }
        return Math.Round(total, 1, MidpointRounding.AwayFromZero);
    }
}
