package rd.service.course;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import rd.dao.mapper.course.CourseTeacherMapper;
import rd.data.db.table.Course;
import rd.data.db.table.CourseTeacher;
import rd.data.db.table.TeacherInfo;
import rd.service.cache.GlobalCache;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Slf4j
@Service
public class CourseTeacherService {
    private final CourseTeacherMapper courseTeacherMapper;

    public CourseTeacherService(CourseTeacherMapper courseTeacherMapper) {
        this.courseTeacherMapper = courseTeacherMapper;
    }

    public List<Course> getCourseForTeacher(Long teacherId) {
        return courseTeacherMapper.getCourseForTeacher(teacherId);
    }

    public List<TeacherInfo> getCourseTeacherList(Long courseId) {
        return this.getCourseTeacherList(courseId, true);
    }

    public List<TeacherInfo> getCourseTeacherList(Long courseId, boolean readCache) {
        if (readCache) {
            return GlobalCache.courseAllTeacherCache.get(courseId, courseTeacherMapper::getCourseAllTeacherInfo);
        } else {
            var courseTeachers = courseTeacherMapper.getCourseAllTeacherInfo(courseId);
            GlobalCache.courseAllTeacherCache.put(courseId, courseTeachers);
            return courseTeachers;
        }
    }

    public List<TeacherInfo> addCourseTeacher(Long courseId, Long teacherId) {
        var exists = courseTeacherMapper.exists(new LambdaQueryWrapper<CourseTeacher>()
                .eq(CourseTeacher::getTeacher, teacherId)
                .eq(CourseTeacher::getCourse, courseId)
                .eq(CourseTeacher::getDeleted, false)
        );
        if (exists) {
            return this.getCourseTeacherList(courseId);
        }

        CourseTeacher courseTeacher = new CourseTeacher();
        courseTeacher.setTeacher(teacherId);
        courseTeacher.setCourse(courseId);
        courseTeacher.setCreateTime(LocalDateTime.now());
        courseTeacher.setEditTime(LocalDateTime.now());
        courseTeacher.setDeleted(false);

        courseTeacherMapper.insert(courseTeacher);

        return this.getCourseTeacherList(courseId, false);
    }

    public List<TeacherInfo> addCourseTeachers(Long courseId, List<Long> teacherIds) {
        if (teacherIds == null || teacherIds.isEmpty()) {
            return getCourseTeacherList(courseId);
        }

        var existsTeacherCourseList = courseTeacherMapper.selectList(new LambdaQueryWrapper<CourseTeacher>()
                .in(CourseTeacher::getTeacher, teacherIds)
                .eq(CourseTeacher::getCourse, courseId)
                .eq(CourseTeacher::getDeleted, false)
        );

        List<CourseTeacher> courseTeacherList;
        if (existsTeacherCourseList.isEmpty()) {
            courseTeacherList = teacherIds.stream()
                    .map(teacherId -> this.makeCourseTeacher(courseId, teacherId))
                    .toList();
        } else {
            Set<Long> filteredTeacherIds = new HashSet<>(teacherIds);
            for (CourseTeacher courseTeacher : existsTeacherCourseList) {
                filteredTeacherIds.remove(courseTeacher.getTeacher());
            }

            courseTeacherList = filteredTeacherIds.stream()
                    .map(teacherId -> this.makeCourseTeacher(courseId, teacherId))
                    .toList();
        }

        courseTeacherMapper.insertBatchSomeColumn(courseTeacherList);

        return this.getCourseTeacherList(courseId, false);
    }

    private CourseTeacher makeCourseTeacher(Long courseId, Long teacherId) {
        CourseTeacher courseTeacher = new CourseTeacher();
        courseTeacher.setTeacher(teacherId);
        courseTeacher.setCourse(courseId);
        courseTeacher.setCreateTime(LocalDateTime.now());
        courseTeacher.setEditTime(LocalDateTime.now());
        courseTeacher.setDeleted(false);
        return courseTeacher;
    }

    public List<TeacherInfo> removeCourseTeacher(Long courseId, Long teacherId) {
        courseTeacherMapper.delete(new LambdaQueryWrapper<CourseTeacher>()
                .eq(CourseTeacher::getCourse, courseId)
                .eq(CourseTeacher::getTeacher, teacherId)
        );

        return this.getCourseTeacherList(courseId, false);
    }

    @Transactional
    public List<TeacherInfo> updateCourseTeacherList(Long courseId, Set<Long> teacherIds) {
        var existCourseTeachers = this.getCourseTeacherList(courseId);
        Set<Long> removedTeacherIds = new HashSet<>();
        for (TeacherInfo courseTeacher : existCourseTeachers) {
            // 传入的teacherIds中已经存在，则在待添加的teacherIds中移除，teacherIds剩下的就是新添加的，
            // 如果已存在的teacher不在teacherIds中，则说明这个id是要被删除的
            if (teacherIds.contains(courseTeacher.getId())) {
                teacherIds.remove(courseTeacher.getId());
            } else {
                removedTeacherIds.add(courseTeacher.getId());
            }
        }

        if (!removedTeacherIds.isEmpty()) {
            courseTeacherMapper.delete(new LambdaQueryWrapper<CourseTeacher>()
                    .eq(CourseTeacher::getCourse, courseId)
                    .in(CourseTeacher::getTeacher, removedTeacherIds)
            );
        }

        if (!teacherIds.isEmpty()) {
            var courseTeacherEntityList = teacherIds.stream()
                    .map(teacherId -> this.makeCourseTeacher(courseId, teacherId))
                    .toList();

            courseTeacherMapper.insertBatchSomeColumn(courseTeacherEntityList);
        }

        return this.getCourseTeacherList(courseId, false);
    }
}
