using Core.Entities;

namespace Core.Calculation;

public class TeamSchedulerSolution(
    Team[][] timeSlots,
    Student[] students,
    string status)
{
    public string Status { get; } = status;

    public TeamScheduleTimeSlot[] TimeSlots { get; set; } 
        = timeSlots.Select( (teams,i) => 
            new TeamScheduleTimeSlot{
                Name = "Time Slot " + (i + 1), 
                Teams = teams,
                StudentOverlaps = GetStudentTeamOverlaps(teams), 
                UnscheduledStudents = GetStudentsNotInTimSlot(teams, students)
            }
        ).ToArray();

    public static int GetStudentTeamOverlapCount(Team[][] timeSlots)
    {
        return timeSlots.Sum(GetStudentTeamOverlapCount);
    }

    private static int GetStudentTeamOverlapCount(Team[] timeSlot)
    {
        return GetStudentTeamOverlaps(timeSlot).Count();
    }

    public static IEnumerable<Tuple<Student, IEnumerable<Team>>> GetStudentTeamOverlaps(Team[] timeSlot)
    {
        return
            from s in timeSlot.SelectMany(ts => ts.Students).Distinct()
            group s by timeSlot.Where(t => t.Students.Contains(s))
            into gs
            where gs.Key.Count() > 1
            select Tuple.Create(gs.First(), gs.Key);
    }

    public static Student[] GetStudentsNotInTimSlot(Team[] timeSlot, Student[] students)
    {
        var studentsInTimeSlot = timeSlot.SelectMany(ts => ts.Students).Distinct();
        return
            (from allStudent in students
                where studentsInTimeSlot.FirstOrDefault(e => e.Equals(allStudent)) == null
                select allStudent
            ).ToArray();
    }

    public Team[] StudentUnassignedTeams(Student student)
    {
        var meetingTeams = TimeSlots.SelectMany(t => t.Teams);
        return
            student.Teams.Where(e => !meetingTeams.Contains(e)).ToArray();
    }
}