package com.magistr.app.service;

import com.magistr.app.model.AcademicCalendar;
import com.magistr.app.model.StudentGroup;
import com.magistr.app.model.StudentGroupCalendarAssignment;
import com.magistr.app.model.StudentGroupStudyState;
import com.magistr.app.repository.StudentGroupCalendarAssignmentRepository;
import org.junit.jupiter.api.Test;

import java.time.LocalDate;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

class StudentGroupLifecycleServiceTest {

    @Test
    void futureGroupIsSelectableButDoesNotHaveScheduleBeforeStudyStart() {
        StudentGroup group = group(1L, 2027);
        StudentGroupLifecycleService service = serviceWithAssignments(group, 4);
        LocalDate date = LocalDate.of(2026, 5, 1);

        assertThat(service.getStudyState(group, date)).isEqualTo(StudentGroupStudyState.NOT_STARTED);
        assertThat(service.isAvailableForSelection(group, date)).isTrue();
        assertThat(service.mayHaveScheduleInRange(group, date, date.plusDays(7))).isFalse();
    }

    @Test
    void groupAfterCalendarCourseLimitIsGraduatedAndUnavailableForSelection() {
        StudentGroup group = group(1L, 2020);
        StudentGroupLifecycleService service = serviceWithAssignments(group, 4);
        LocalDate date = LocalDate.of(2026, 5, 1);

        assertThat(service.getStudyState(group, date)).isEqualTo(StudentGroupStudyState.GRADUATED);
        assertThat(service.isAvailableForSelection(group, date)).isFalse();
        assertThat(service.mayHaveScheduleInRange(group, date, date.plusDays(7))).isFalse();
    }

    private StudentGroupLifecycleService serviceWithAssignments(StudentGroup group, int courseCount) {
        StudentGroupCalendarAssignmentRepository repository = mock(StudentGroupCalendarAssignmentRepository.class);
        when(repository.findByGroupIdWithDetails(group.getId()))
                .thenReturn(List.of(assignment(courseCount)));
        return new StudentGroupLifecycleService(repository);
    }

    private StudentGroup group(Long id, int yearStartStudy) {
        StudentGroup group = new StudentGroup();
        group.setId(id);
        group.setName("Группа");
        group.setYearStartStudy(yearStartStudy);
        return group;
    }

    private StudentGroupCalendarAssignment assignment(int courseCount) {
        AcademicCalendar calendar = new AcademicCalendar();
        calendar.setCourseCount(courseCount);
        StudentGroupCalendarAssignment assignment = new StudentGroupCalendarAssignment();
        assignment.setAcademicCalendar(calendar);
        return assignment;
    }
}
