package ru.mcs.diary.group;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.mcs.diary.common.exception.ResourceNotFoundException;
import ru.mcs.diary.group.dto.GroupCreateRequest;
import ru.mcs.diary.group.dto.GroupListDto;
import ru.mcs.diary.student.Student;
import ru.mcs.diary.student.StudentRepository;
import ru.mcs.diary.subject.Subject;
import ru.mcs.diary.subject.SubjectRepository;
import ru.mcs.diary.teacher.Teacher;
import ru.mcs.diary.teacher.TeacherRepository;
import java.util.List;
@Slf4j
@Service
@RequiredArgsConstructor
public class GroupService {
private final GroupRepository groupRepository;
private final SubjectRepository subjectRepository;
private final StudentRepository studentRepository;
private final TeacherRepository teacherRepository;
@Transactional(readOnly = true)
public List<GroupListDto> getAllGroups(Long teacherId) {
return groupRepository.findAllByTeacherIdWithSubject(teacherId)
.stream()
.map(this::toListDto)
.toList();
}
@Transactional(readOnly = true)
public StudyGroup getGroup(Long id, Long teacherId) {
return groupRepository.findByIdAndTeacherId(id, teacherId)
.orElseThrow(() -> new ResourceNotFoundException("Группа", id));
}
@Transactional(readOnly = true)
public StudyGroup getGroupWithStudents(Long id, Long teacherId) {
return groupRepository.findByIdWithStudents(id, teacherId)
.orElseThrow(() -> new ResourceNotFoundException("Группа", id));
}
@Transactional
public StudyGroup createGroup(GroupCreateRequest request, Long teacherId) {
log.info("Creating group: {}", request.getName());
Teacher teacher = teacherRepository.findById(teacherId)
.orElseThrow(() -> new ResourceNotFoundException("Преподаватель", teacherId));
Subject subject = subjectRepository.findByIdAndTeacherId(request.getSubjectId(), teacherId)
.orElseThrow(() -> new ResourceNotFoundException("Предмет", request.getSubjectId()));
StudyGroup group = StudyGroup.builder()
.name(request.getName().trim())
.subject(subject)
.pricePerLesson(request.getPricePerLesson())
.description(request.getDescription())
.teacher(teacher)
.build();
return groupRepository.save(group);
}
@Transactional
public StudyGroup updateGroup(Long id, GroupCreateRequest request, Long teacherId) {
log.info("Updating group: {}", id);
StudyGroup group = getGroup(id, teacherId);
Subject subject = subjectRepository.findByIdAndTeacherId(request.getSubjectId(), teacherId)
.orElseThrow(() -> new ResourceNotFoundException("Предмет", request.getSubjectId()));
group.setName(request.getName().trim());
group.setSubject(subject);
group.setPricePerLesson(request.getPricePerLesson());
group.setDescription(request.getDescription());
return groupRepository.save(group);
}
@Transactional
public void deleteGroup(Long id, Long teacherId) {
log.info("Deleting group: {}", id);
StudyGroup group = getGroup(id, teacherId);
groupRepository.delete(group);
}
@Transactional
public void addStudent(Long groupId, Long studentId, Long teacherId) {
StudyGroup group = getGroupWithStudents(groupId, teacherId);
Student student = studentRepository.findByIdAndTeacherId(studentId, teacherId)
.orElseThrow(() -> new ResourceNotFoundException("Ученик", studentId));
if (group.getStudents().contains(student)) {
throw new IllegalArgumentException("Ученик уже в группе");
}
group.getStudents().add(student);
groupRepository.save(group);
log.info("Added student {} to group {}", studentId, groupId);
}
@Transactional
public void removeStudent(Long groupId, Long studentId, Long teacherId) {
StudyGroup group = getGroupWithStudents(groupId, teacherId);
Student student = studentRepository.findByIdAndTeacherId(studentId, teacherId)
.orElseThrow(() -> new ResourceNotFoundException("Ученик", studentId));
group.getStudents().remove(student);
groupRepository.save(group);
log.info("Removed student {} from group {}", studentId, groupId);
}
public long countByTeacher(Long teacherId) {
return groupRepository.countByTeacherId(teacherId);
}
private GroupListDto toListDto(StudyGroup group) {
return GroupListDto.builder()
.id(group.getId())
.name(group.getName())
.subjectName(group.getSubject() != null ? group.getSubject().getName() : "—")
.studentCount(group.getStudents().size())
.pricePerLesson(group.getPricePerLesson())
.build();
}
}