using Jiaowu.Api.Domain.Academic;

namespace Jiaowu.Api.Infrastructure.Teaching;

public static class TeachingTaskHours
{
    public static int Calculate(int startWeek, int endWeek, int weeklyHours) =>
        endWeek < startWeek ? 0 : (endWeek - startWeek + 1) * weeklyHours;

    public static int RegularScheduleHours(Course course) =>
        RegularScheduleHours(course.TotalHours, course.PracticeHours);

    public static int RegularScheduleHours(int totalHours, int practiceHours) =>
        Math.Max(0, totalHours - practiceHours);

    public static int TargetHours(
        Course course,
        TeachingTaskSchedulingMode schedulingMode) =>
        course.TotalHours;

    public static int TargetHours(Course course, ScheduleEntryKind kind) =>
        kind == ScheduleEntryKind.Experiment
            ? Math.Max(0, course.PracticeHours)
            : RegularScheduleHours(course);

    public static int ScheduledHours(ScheduleEntry entry) =>
        ScheduledHours(
            entry.StartWeek,
            entry.EndWeek,
            entry.WeekPattern,
            entry.PeriodCount);

    public static int ScheduledHours(
        int startWeek,
        int endWeek,
        WeekPattern weekPattern,
        int periodCount)
    {
        if (endWeek < startWeek || periodCount <= 0) return 0;
        var occurrences = Enumerable.Range(startWeek, endWeek - startWeek + 1)
            .Count(week =>
                weekPattern == WeekPattern.All ||
                weekPattern == WeekPattern.Odd && week % 2 == 1 ||
                weekPattern == WeekPattern.Even && week % 2 == 0);
        return occurrences * periodCount;
    }

    public static bool TryResolveRegularWeeklyHours(
        Course course,
        int startWeek,
        int endWeek,
        out int weeklyHours) =>
        TryResolveRegularWeeklyHours(
            course.TotalHours,
            course.PracticeHours,
            startWeek,
            endWeek,
            out weeklyHours);

    public static bool TryResolveRegularWeeklyHours(
        int totalHours,
        int practiceHours,
        int startWeek,
        int endWeek,
        out int weeklyHours)
    {
        weeklyHours = 0;
        var weekCount = endWeek - startWeek + 1;
        var regularHours = RegularScheduleHours(totalHours, practiceHours);
        if (weekCount <= 0 || regularHours % weekCount != 0) return false;

        weeklyHours = regularHours / weekCount;
        return true;
    }

    public static string? Validate(
        Course course,
        int startWeek,
        int endWeek,
        int weeklyHours,
        TeachingTaskSchedulingMode schedulingMode =
            TeachingTaskSchedulingMode.Standard)
    {
        var plannedHours = Calculate(startWeek, endWeek, weeklyHours);
        var targetHours = TargetHours(course, schedulingMode);
        if (plannedHours == targetHours) return null;

        if (schedulingMode == TeachingTaskSchedulingMode.Standard)
        {
            return $"课程“{course.Name}”总学时为 {course.TotalHours}，其中实践学时 " +
                   $"{course.PracticeHours}；理论课和实验课均应进入课表。当前第 " +
                   $"{startWeek}—{endWeek} 周、每周 {weeklyHours} 学时，共 " +
                   $"{plannedHours} 学时。请调整授课周次或周学时。";
        }

        return $"课程“{course.Name}”总学时为 {course.TotalHours}；当前第 " +
               $"{startWeek}—{endWeek} 周、每周 {weeklyHours} 学时，共 " +
               $"{plannedHours} 学时。请调整授课周次或周学时。";
    }
}
