package rd.service.schedule;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.yitter.idgen.YitIdHelper;
import rd.dao.mapper.course.CourseSelectionMapper;
import rd.data.code.ServiceCode;
import rd.data.db.table.CourseSelection;
import rd.exception.ServiceException;

import rd.service.activity.ActivityService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

@Service
public class StudentCourseScheduleService {

    private final ActivityService activityService;
    private final CourseScheduleService courseScheduleService;
    private final CourseSelectionMapper courseSelectionMapper;

    public StudentCourseScheduleService(ActivityService activityService,
                                        CourseScheduleService courseScheduleService,
                                        CourseSelectionMapper courseSelectionMapper) {

        this.activityService = activityService;
        this.courseScheduleService = courseScheduleService;
        this.courseSelectionMapper = courseSelectionMapper;
    }

    public boolean isStudentSelected(Long studentUid, Long scheduleId) {
        return courseSelectionMapper.exists(new LambdaQueryWrapper<CourseSelection>()
                .eq(CourseSelection::getSchedule, scheduleId)
                .eq(CourseSelection::getStudent, studentUid)
                .eq(CourseSelection::getDeleted, false)
        );
    }

    @Transactional
    public void selectSchedule(Long uid, Long scheduleId, Long activityId) {
        var schedule = courseScheduleService.getSchedule(scheduleId);
        if (schedule == null) {
            throw ServiceException.error(ServiceCode.DataNotExists, "课堂id不存在：" + scheduleId);
        }

        var activity = activityService.getById(activityId);
        if (activity == null) {
            throw ServiceException.error(ServiceCode.DataNotExists, "选课活动id不存在：" + activityId);
        }

        var now = LocalDateTime.now();
        if (!activity.getStartTime().isBefore(now) || !activity.getEndTime().isAfter(now)) {
            var msg = String.format(
                    "当前的选课活动'%s'已结束：%s ~ %s",
                    activity.getName(), activity.getStartTime(), activity.getEndTime()
            );
            throw ServiceException.error(ServiceCode.ActivityEnded);
        }

        if (!schedule.getAcademicTerm().equals(activity.getTerm())) {
            var msg = String.format(
                    "学期不匹配：选定的课堂学期：%s，选课活动对应的学期：%s",
                    schedule.getAcademicTerm(), activity.getTerm()
            );
            throw ServiceException.error(ServiceCode.DataNotMatch, msg);
        }

        var exists = courseSelectionMapper.exists(new LambdaQueryWrapper<CourseSelection>()
                .eq(CourseSelection::getId, scheduleId)
                .eq(CourseSelection::getStudent, uid)
                .eq(CourseSelection::getDeleted, false)
        );
        if (exists) {
            return;
        }

        Long id = YitIdHelper.nextId();
        CourseSelection courseSelection = new CourseSelection();
        courseSelection.setId(id);
        courseSelection.setTerm(activity.getTerm());
        courseSelection.setStudent(uid);
        courseSelection.setSchedule(scheduleId);
        courseSelection.setActivity(activityId);
        courseSelection.setCreateTime(LocalDateTime.now());
        courseSelection.setEditTime(LocalDateTime.now());
        courseSelection.setDeleted(false);

        courseSelectionMapper.insert(courseSelection);
    }

    public void unselect(Long uid, Long scheduleId) {
        courseSelectionMapper.delete(new LambdaQueryWrapper<CourseSelection>()
                .eq(CourseSelection::getSchedule, scheduleId)
                .eq(CourseSelection::getStudent, uid)
                .eq(CourseSelection::getDeleted, false)
        );
    }

    @Transactional
    public void update(Long uid, Long oldSchedule, Long newSchedule, Long activityId) {
        CourseSelection courseSelection = new CourseSelection();
        courseSelection.setSchedule(newSchedule);
        courseSelection.setEditTime(LocalDateTime.now());
        courseSelectionMapper.update(courseSelection, new QueryWrapper<CourseSelection>()
                .eq("schedule", oldSchedule)
                .eq("activity", activityId)
                .eq("student", uid)
                .eq("deleted", false)
        );
    }
}
