package com.xhkjedu.slive.service.xz;

import com.xhkjedu.exception.MissingParametersException;
import com.xhkjedu.slive.mapper.gradeclass.*;
import com.xhkjedu.slive.mapper.liveplay.CourseClassMapper;
import com.xhkjedu.slive.mapper.liveplay.CourseMapper;
import com.xhkjedu.slive.mapper.liveplay.CourseSectionMapper;
import com.xhkjedu.slive.mapper.xz.XzKjMapper;
import com.xhkjedu.slive.mapper.xz.XzMapper;
import com.xhkjedu.slive.model.gradeclass.*;
import com.xhkjedu.slive.model.liveplay.LCourse;
import com.xhkjedu.slive.model.liveplay.LCourseClass;
import com.xhkjedu.slive.model.liveplay.LCourseSection;
import com.xhkjedu.slive.model.xz.LXz;
import com.xhkjedu.slive.model.xz.LXzKj;
import com.xhkjedu.slive.service.gradeclass.ClassService;
import com.xhkjedu.slive.utils.LiveUtil;
import com.xhkjedu.slive.utils.PoiUtils;
import com.xhkjedu.slive.vo.gradeclass.CStudentVo;
import com.xhkjedu.slive.vo.gradeclass.CTeacherVo;
import com.xhkjedu.slive.vo.liveplay.CourseVo;
import com.xhkjedu.slive.vo.xz.*;
import com.xhkjedu.utils.N_Utils;
import com.xhkjedu.vo.ResultVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 行政直播概要
 * @Author WN
 * Date 2022/3/30 13:42
 **/
@Service
@Slf4j
public class XzService {
    @Resource
    private XzMapper xzMapper;
    @Resource
    private XzKjMapper xzKjMapper;
    @Resource
    private CourseMapper courseMapper;
    @Resource
    private CourseSectionMapper courseSectionMapper;
    @Resource
    private CourseClassMapper courseClassMapper;
    @Resource
    private SchoolMapper schoolMapper;
    @Resource
    private ClassService classService;
    @Resource
    private ClassTeacherMapper classTeacherMapper;
    @Resource
    private ClassMapper classMapper;
    @Resource
    private ClassStudentMapper classStudentMapper;
    @Resource
    private GroupMapper groupMapper;
    @Resource
    private GroupStudentMapper groupStudentMapper;

    @Autowired
    ApplicationContext applicationContext;

    /**
     * @Description 行政直播列表
     * @Param [schoolid]
     * @Return java.util.List<java.util.Map>
     * @Author wn
     * @Date 2022/3/30 14:03
     **/
    public List<Map> listXzs(LXz xz) {
        return xzMapper.listXzs(xz);
    }

    /**
     * @Description 保存行政直播
     * @Param [xz]
     * @Return void
     * @Author wn
     * @Date 2022/3/30 14:07
     **/
    @Transactional(rollbackFor = Exception.class)
    public ResultVo saveXz(LXz xz) {
        try {
            Integer timestamp = N_Utils.getSecondTimestamp();
            xz.setCreatetime(timestamp);
            xz.setDeleted(1);
            xz.setCurstep(2);
            xz.setSavestate(0);
            xzMapper.insertUseGeneratedKeys(xz);//保存行政直播信息
            Integer xzid = xz.getId();
            //保存对应的课节信息
            List<LXzKj> kjlst = new ArrayList<>();
            for (int i = 0; i < xz.getDaynum(); i++) {
                LXzKj kj = new LXzKj();
                kj.setXzid(xzid);
                String kjname = LiveUtil.getChineStrByNum(i);
                kj.setKjname("第" + kjname + "节");
                kj.setKjorder(i + 1);
                kj.setCreateid(xz.getCreateid());
                kj.setCreatetime(timestamp);

                kjlst.add(kj);
            }
            //批量保存行政直播对应的课节
            xzKjMapper.insertList(kjlst);
            return new ResultVo(0, "保存行政直播成功", xzid);
        } catch (Exception e) {
            log.error("保存行政直播出错：" + e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new ResultVo(1, "保存行政直播成功失败");
        }
    }

    /**
     * @Description 校验学校当前年份指定年级下是否有行政班和提高班
     * @Param [schoolid, gradeid]
     * @Author ywx
     * @Date 2023/6/1 15:45
     * @return void
     **/
    public void checkClass(Integer schoolid, Integer gradeid) {
        List<XzClassVo> list = classMapper.listClassByXzid(schoolid, gradeid);
        if (N_Utils.isListEmpty(list)) {
            throw new MissingParametersException("该年级下没有班级，请添加班级后再进行下一步");
        }
    }

    /**
     * @Description 修改行政直播
     * @Param [xz]
     * @Return void
     * @Author wn
     * @Date 2022/3/30 14:16
     **/
    public void updateXz(LXz xz) {
        LXz lXz = xzMapper.selectByPrimaryKey(xz.getXzid());
        checkClass(lXz.getSchoolid(), lXz.getGradeid());
        xzMapper.updateByPrimaryKeySelective(xz);
    }

    //获取行政直播课下进行中或者已结束的直播课数量
    public Integer getXzSectionKsNum(Integer xzid) {
        Integer num = xzMapper.getXzSectionKsNum(xzid);
        if (num == null) {
            num = 0;
        }
        return num;
    }


    /**
     * @Description 根据行政直播id获取信息
     * @Param [xzid]
     * @Return java.util.Map
     * @Author wn
     * @Date 2022/4/2 10:41
     **/
    public Map getXzByXzid(Integer xzid) {
        return xzMapper.getXzByXzid(xzid);
    }

    /**
     * @Description 删除行政直播
     * @Param [xzid]
     * @Return void
     * @Author wn
     * @Date 2022/3/30 15:24
     **/
    @Transactional(rollbackFor = Exception.class)
    public void deleteXz(Integer xzid) {
        try {
            Integer savestate = xzMapper.getSaveStateById(xzid);
            if (savestate != 0) throw new Exception("有课表在保存中禁止操作");
            //如果行政直播下所有的课都未开始，则可以直接删除，
            //如果有直播课已经开始则进行逻辑删除，并删除所有未开始上的直播课
            Integer sectionnum = xzMapper.getXzSectionKsNum(xzid);
            if (sectionnum != null && sectionnum > 0) {
                //说明直播下有开始或结束的课节，只能删除未开始的直播和直播班级信息
                xzMapper.deleteCourseClassKjByXzid(xzid);
                //修改行政直播的状态未已删除
                xzMapper.updateXzDeleted(10, xzid);
            } else {
                //说明该行政直播课程可以直接删除
                xzMapper.deleteCourseClassByXzid(xzid);
                xzMapper.deleteXzAndKjByXzid(xzid);
            }
        } catch (Exception e) {
            log.error("删除行政直播出错：" + e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new MissingParametersException(e.getMessage());
        }
    }

    /**
     * @Description 保存行政直播课程表
     * @Param [xzDatelst]
     * @Return com.xhkjedu.vo.ResultVo
     * @Author wn
     * @Date 2022/3/31 21:46
     **/
    public ResultVo saveXzCourse(LXz xz) {
        Integer xzid = xz.getXzid();
        try {
            //保存行政直播课程表,参数层级为日期--课节--班级和教师
            //根据同一个课节下根据班级和教师确认是否是同一个直播课，保存进course,section（单课节课程）
            LXz x = xzMapper.selectByPrimaryKey(xzid);//行政直播课程
            if (x.getSavestate() != 0) return new ResultVo(1, "有课表在保存中禁止操作");
            xzMapper.updateSaveState(xzid, 1);//修改保存状态
            List<XzDateVo> xzDatelst = xz.getXzdatas();
            if (xzDatelst == null || xzDatelst.size() == 0) {
                return new ResultVo(1, "未设置课节信息");
            } else {
                //日期转为map,先处理所有日期的数据
                TreeMap<String, TreeMap<Integer, List<XzDateKjTeaVo>>> datemap = listDateKjForSave(xzDatelst, x);
                Map<Integer, XzDateKjVo> kjVoMap = setKjMap(xzid);

                //开始保存
                for (Map.Entry<String, TreeMap<Integer, List<XzDateKjTeaVo>>> entry : datemap.entrySet()) {
                    TreeMap<Integer, List<XzDateKjTeaVo>> kjmap = entry.getValue();
                    String seldate = entry.getKey();
                    String datazhou = LiveUtil.getDateZhou(seldate);//要保存日期对应的周

                    for (Map.Entry<Integer, List<XzDateKjTeaVo>> entrykj : kjmap.entrySet()) {
                        Integer kjid = entrykj.getKey();
                        XzDateKjVo kjVo = kjVoMap.get(kjid);
                        List<XzDateKjTeaVo> xjTealst = entrykj.getValue();

                        //处理成教师下班级形式，生成课程
                        Map<Integer, List<XzDateKjTeaVo>> map = listChangeTeacherClass(xjTealst);

                        LCourse course = new LCourse();
                        course.setGradeid(x.getGradeid());
                        course.setBegindate(seldate);
                        course.setEnddate(seldate);
                        course.setCoursenum(1);
                        course.setCoursetype(1);
                        course.setCourseclass(1);
                        course.setCoursestate(0);
                        course.setDeleted(1);
                        course.setCourseselected(0);
                        course.setCreateid(xz.getCreateid());
                        course.setCreatetime(N_Utils.getSecondTimestamp());
                        course.setSchoolid(x.getSchoolid());

                        for (Map.Entry<Integer, List<XzDateKjTeaVo>> entrytea : map.entrySet()) {
                            List<XzDateKjTeaVo> xjTeas = entrytea.getValue();
                            String teachername = xjTeas.get(0).getTeachername();
                            //单个教师课程信息
                            String coursename = datazhou + kjVo.getKjname() + xjTeas.get(0).getSubjectname() + "(" + teachername + ")";

                            course.setCoursename(coursename);
                            course.setSubjectid(xjTeas.get(0).getSubjectid());
                            course.setTeacherid(entrytea.getKey());
                            course.setBegintime(kjVo.getBegintime());
                            course.setEndtime(kjVo.getEndtime());
                            course.setKjid(kjVo.getKjid());

                            //获取集合中所有的班级id
                            List classidlst = xjTeas.stream().map(XzDateKjTeaVo::getClassid).collect(Collectors.toList());
                            List<Map> users = courseMapper.listUid(classidlst);//获取课班级下学生
                            //只有当班级下有学生时进行保存
                            if(users!=null && users.size() > 0){
                                //保存行政直播课程表,该方式解决事务不生效问题
                                ((XzService)applicationContext.getBean("xzService")).saveCourseAll(xjTeas, course,users);
                            }
                        }
                    }
                }

                //保存完课程表之后修改当前步骤
                xzMapper.updateCurstepByXzid(3, xzid);

                return new ResultVo(0, "保存成功");
            }
        } catch (Exception e) {
            log.error("保存行政直播课程表出错：" + e.getMessage());
            xzMapper.updateSaveState(xzid, 0);//修改保存状态
            return new ResultVo(1,"保存失败");
        }


    }

    //指定天某天某节课下的教师班级层级关系
    private Map<Integer, List<XzDateKjTeaVo>> listChangeTeacherClass(List<XzDateKjTeaVo> xjTealst) {
        Map<Integer, List<XzDateKjTeaVo>> map = new HashMap<>();

        for (int i = 0; i < xjTealst.size(); i++) {
            XzDateKjTeaVo xzDateXjTeaVo = xjTealst.get(i);
            if (!N_Utils.isEmptyInteger(xzDateXjTeaVo.getTeacherid())) {
                if (map.containsKey(xzDateXjTeaVo.getTeacherid())) {
                    map.get(xzDateXjTeaVo.getTeacherid()).add(xzDateXjTeaVo);
                } else {
                    List<XzDateKjTeaVo> classlst = new ArrayList<>();
                    classlst.add(xzDateXjTeaVo);
                    map.put(xzDateXjTeaVo.getTeacherid(), classlst);
                }
            }
        }
        return map;
    }

    //转换日期下课节为map
    private TreeMap<String, TreeMap<Integer,List<XzDateKjTeaVo>>> listDateKjForSave(List<XzDateVo> xzDatelst, LXz x) {
        TreeMap<String, TreeMap<Integer,List<XzDateKjTeaVo>>> datemap = new TreeMap<>();
        for (int i = 0; i < xzDatelst.size(); i++) {
            XzDateVo xzdate = xzDatelst.get(i);
            List<XzDateKjVo> kjlst = xzdate.getKjs();
            if(kjlst!=null && kjlst.size()>0){
                TreeMap<Integer,List<XzDateKjTeaVo>> kjmap = new TreeMap<>();
                for(int j=0;j<kjlst.size();j++){
                    XzDateKjVo kjvo = kjlst.get(j);
                    if(kjvo.getKjteas()!=null && kjvo.getKjteas().size()>0){
                        kjmap.put(kjvo.getKjid(),kjvo.getKjteas());
                    }
                }
                datemap.put(xzdate.getSelectdate(),kjmap);
            }
        }

        TreeMap<String, TreeMap<Integer,List<XzDateKjTeaVo>>> rtnmap = new TreeMap<>();
        rtnmap.putAll(datemap);

        //开始处理所有日期的课程
        for (Map.Entry<String, TreeMap<Integer,List<XzDateKjTeaVo>>> entry : datemap.entrySet()){
            String datestr = entry.getKey();//日期
            TreeMap<Integer,List<XzDateKjTeaVo>> kjmap = entry.getValue();
            //遍历当前天的课节，判断是否有需要后续同步的
            for (Map.Entry<Integer,List<XzDateKjTeaVo>> entrykj : kjmap.entrySet()){
                List<XzDateKjTeaVo> kjTeaVolst = entrykj.getValue();
                for (int i = 0; i < kjTeaVolst.size(); i++) {
                    XzDateKjTeaVo xtvo = kjTeaVolst.get(i);
                    if(!N_Utils.isEmptyInteger(xtvo.getKfollow())){
                        //说明需要同步到后续日期(结束时间之前所有当前天所属的周几)
                        List<String> dates  = LiveUtil.getDaysForMeetDates(datestr,x.getEnddate());
                        if(dates!=null && dates.size()>1){
                            //说明直接有日期（不包含当前天），复制数据,处理时舍弃当前天
                            isSavechangeMapKj(dates,entrykj.getKey(),xtvo,rtnmap);
                        }
                    }
                }
            }
        }

        return rtnmap;
    }

    //保存整体数据
    private void isSavechangeMapKj( List<String> dates,Integer kjid,XzDateKjTeaVo xtvo,TreeMap<String, TreeMap<Integer,List<XzDateKjTeaVo>>> datemap){
        //说明直接有日期（不包含当前天），复制数据,处理时舍弃当前天
        for (int i = 1; i < dates.size(); i++) {
            String dateobj = dates.get(i);
            if(datemap.containsKey(dateobj)){
                //说明该日期数据已存在
                TreeMap<Integer,List<XzDateKjTeaVo>> kjmap = datemap.get(dateobj);
                if(kjmap.containsKey(kjid)){
                    kjmap.get(kjid).add(xtvo);
                }else{
                    List<XzDateKjTeaVo> kjTeaVos = new ArrayList<>();
                    kjTeaVos.add(xtvo);
                    kjmap.put(kjid,kjTeaVos);
                }
            }else{
                //新添加
                TreeMap<Integer,List<XzDateKjTeaVo>> kjmap = new TreeMap<>();
                List<XzDateKjTeaVo> kjTeaVos = new ArrayList<>();
                kjTeaVos.add(xtvo);
                kjmap.put(kjid,kjTeaVos);

                datemap.put(dateobj,kjmap);
            }
        }
    }

    //处理课节格式
    private Map<Integer,XzDateKjVo> setKjMap(Integer xzid){
        List<XzDateKjVo> lst = xzKjMapper.listXzKjsByXzid(xzid);
        Map<Integer, XzDateKjVo> map = new HashMap<>();

        for (int i = 0; i < lst.size(); i++) {
            XzDateKjVo kj = lst.get(i);
            map.put(kj.getKjid(), kj);
        }
        return map;
    }



    //保存行政直播课程表
    @Transactional(rollbackFor = Exception.class)
    public Integer saveCourseAll(List<XzDateKjTeaVo> xjTeas, LCourse course,List<Map> users) {
        Integer courseid = 0;
        try {
            List classidlst = xjTeas.stream().map(XzDateKjTeaVo::getClassid).collect(Collectors.toList());

            //新生成直播班班级信息
            TClass c = new TClass();
            c.setClassname(course.getCoursename() + "班");
            c.setCreateid(course.getCreateid());
            c.setSchoolid(course.getSchoolid());
            Integer year = schoolMapper.getYearById(course.getSchoolid());
            c.setSchoolyear(year);
            c.setYear(year);
            c.setClassorder(999);
            c.setGradeid(course.getGradeid());
            c.setClasstype(99);//已直播班级

            Integer classid = classService.save(c);//新生成直播班id
            course.setClassid(classid);

            //设置班级对应教师
            //班级教师
            TClassTeacher teacher = new TClassTeacher();
            teacher.setClassid(classid);
            teacher.setTeacherid(course.getTeacherid());
            teacher.setCreateid(course.getCreateid());
            teacher.setCreatetime(N_Utils.getSecondTimestamp());
            teacher.setSchoolid(course.getSchoolid());
            classTeacherMapper.insertSelective(teacher);

            //保存课程信息
            course.setCourseschool(0);
            courseMapper.insertUseGeneratedKeys(course);
            courseid = course.getId();//课程id

            List<Integer> studentids = new ArrayList<>();
            users.forEach(userVo -> {
                studentids.add((Integer) userVo.get("userid"));
            });

            classService.batchSaveStu(course.getCreateid(), course.getSchoolid(), classid, studentids);//批量添加报名学生
            courseMapper.updateStuNum(courseid);//更新已报学生数量

            //保存直播关联班级
            List<LCourseClass> cclist = new ArrayList<>();
            for (int i = 0; i < classidlst.size(); i++) {
                Integer cid = Integer.parseInt(classidlst.get(i).toString());
                LCourseClass cc = new LCourseClass();
                cc.setCourseid(courseid);
                cc.setClassid(cid);
                cc.setCreateid(course.getCreateid());
                cc.setCreatetime(course.getCreatetime());
                cclist.add(cc);
            }
            courseClassMapper.insertList(cclist);//保存原班级和直播的关联关系

            //保存课程课节关联关系
            LCourseSection cs = new LCourseSection();
            cs.setCourseid(courseid);
            cs.setTeacherid(course.getTeacherid());
            cs.setSectionname(course.getCoursename());
            cs.setSectionorder(1);
            cs.setSectiondate(course.getBegindate());
            cs.setPlanbegintime(course.getBegintime());
            cs.setPlanendtime(course.getEndtime());
            cs.setStunum(0);
            cs.setSectionstate(0);
            cs.setCreateid(course.getCreateid());
            cs.setCreatetime(course.getCreatetime());
            courseSectionMapper.insertUseGeneratedKeys(cs);//保存课程课节信息

        } catch (Exception e) {
            log.info("保存行政直播课程表出错：" + e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new MissingParametersException(e.getMessage());
        }
        return courseid;
    }

    /**
     * @Description 获取行政直播课程表
     * @Param [xz]
     * @Return java.util.Map
     * @Author wn
     * @Date 2022/4/1 13:59
     **/
    public Map getXzKjDetail(LXz xz) {
        //获取行政直播信息
        LXz xzobj = xzMapper.selectByPrimaryKey(xz.getXzid());
        xz.setEnddate(xzobj.getEnddate());//放入行政直播实际结束的时间，

        Map map = new HashMap();
        List<XzDateKjVo> kjs = xzKjMapper.listXzKjsByXzid(xz.getXzid());
        map.put("kjs", kjs);//保存所有课节信息

        //根据行政直播id获取该学校当前年份指定年级下的行政班和提高班
        List<XzClassVo> classlst = classMapper.listClassByXzid(xzobj.getSchoolid(), xzobj.getGradeid());
        //先获取选择要看的有效日期，不能超出行政直播结束的日期 2022-05-06更改为获取选中日期的课节信息
//        List<String> seldates = LiveUtil.listDateAfterDates(xz.getBegindate(), xz.getEnddate(), 7);

        for (int i = 0; i < classlst.size(); i++) {
            XzClassVo classVo = classlst.get(i);
            List<XzDateVo> datelst = new ArrayList<>();//保存指定日期
            List<Map> kjlst = xzMapper.listXzDateKjDetail(xz.getBegindate(), xz.getXzid(), classVo.getClassid());//获取课节详情
            XzDateVo dateVo = new XzDateVo();
            dateVo.setSelectdate(xz.getBegindate());
            dateVo.setKjsmap(kjlst);
            datelst.add(dateVo);

            /*for (int j = 0; j < seldates.size(); j++) {
                List<Map> kjlst = xzMapper.listXzDateKjDetail(seldates.get(j), xz.getXzid(), classVo.getClassid());//获取课节详情
                XzDateVo dateVo = new XzDateVo();
                dateVo.setSelectdate(seldates.get(j));
                dateVo.setKjsmap(kjlst);
                datelst.add(dateVo);
            }*/
            classVo.setDates(datelst);
        }

        map.put("xzdates", classlst);
        return map;
    }

    /**
     * @Description 删除单个单元格
     * @Param [kjTeaVo]
     * @Return com.xhkjedu.vo.ResultVo
     * @Author wn
     * @Date 2022/4/1 17:42
     **/
    public ResultVo delXzkjDyg(XzDateKjTeaVo kjTeaVo) {
        try {
            Integer savestate = xzMapper.getSaveStateById(kjTeaVo.getXzid());
            if (savestate != 0) return new ResultVo(1, "有课表在保存中禁止操作");
            //判断课程的状态，如果已经开始上课则不能删除
            LCourse course = courseMapper.selectByPrimaryKey(kjTeaVo.getCourseid());
            Integer kjid = course.getKjid();
            Integer classid = kjTeaVo.getClassid();//行政班id
            if (course.getCoursestate() > 0) {
                return new ResultVo(1, "选择的课程已经开始上课，不允许删除");
            } else {
                //先判断是删除当前课程还是后续日期的课
                if (N_Utils.isEmptyInteger(kjTeaVo.getKfollow())) {
                    //kfollow为0或者空，则只需要删除当前选中的课程
                    ((XzService) applicationContext.getBean("xzService")).delXzkjDygForDetail(kjTeaVo, course.getClassid());
                } else {
                    //需要删除后续和当前日期相同的星期相同课节的课程
                    //获取已生成课程从所选删除课程开始日期到结束日期内所有日期
                    List<String> alldates = xzMapper.getAllDatesForKj(kjid, classid, course.getBegindate());
                    if (alldates != null && alldates.size() > 0) {
                        //已经成课程中符合周的需要删除的日期
                        List<String> deldates = LiveUtil.getMeetDayOfDates(alldates, course.getBegindate());
                        if (deldates != null && deldates.size() > 0) {
                            for (int i = 0; i < deldates.size(); i++) {
                                //先获取指定日期对应的课程
                                CourseVo courseVo = courseMapper.getCourseByKjidAndClassid(kjid, classid, deldates.get(i));
                                kjTeaVo.setCourseid(courseVo.getCourseid());
                                ((XzService) applicationContext.getBean("xzService")).delXzkjDygForDetail(kjTeaVo, courseVo.getClassid());
                            }
                        }
                    }
                }
                return new ResultVo(0, "删除成功");
            }
        } catch (Exception e) {
            log.error("删除课程表单个课程出错：" + e.getMessage());
            return new ResultVo(1, "删除失败");
        }
    }

    //删除单个课程表
    @Transactional(rollbackFor = Exception.class)
    public void delXzkjDygForDetail(XzDateKjTeaVo kjTeaVo, Integer zbclassid) {
        try {
            //删除单个单元格中设置的教师信息，先判断该单元格对应的课程是否有其他班级
            Integer coursenum = courseClassMapper.getOtherClassnumByCourseid(kjTeaVo.getCourseid(), kjTeaVo.getClassid());
            if (coursenum == 0) {
                //说明该课程仅关联一个班级,直接删除该课程以及该课程对应的直播班
                courseMapper.deleteCourseClassByCourseid(kjTeaVo.getCourseid());
            } else {
                //说明关联的还有其他班级,删除该班级在直播班级中的学生，
                courseClassMapper.deleteByCourseidAndClassid(kjTeaVo.getCourseid(), kjTeaVo.getClassid());
                //处理对应直播班级中学生
                classMapper.deleteClassstu(zbclassid, kjTeaVo.getClassid());
                classMapper.updateNum2(zbclassid);//更改班级以及班级分组人数
                courseMapper.updateStuNum(kjTeaVo.getCourseid());//更新直播课学生数量
            }
        } catch (Exception e) {
            log.error("删除单个课程出错：" + e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new MissingParametersException(e.getMessage());
        }
    }

    /**
     * @Description 保存单个单元格（单元格）
     * @Param [kjTeaVo]
     * @Return com.xhkjedu.vo.ResultVo
     * @Author wn
     * @Date 2022/4/2 15:19
     **/
    public ResultVo saveOneXzKjDyg(XzDateKjTeaVo kjTeaVo) {
        LXz xz = xzMapper.getXzByXzkjid(kjTeaVo.getKjid());
        Integer xzid = xz.getXzid();
        try {
            if (xz.getSavestate() != 0) return new ResultVo(1, "有课表在保存中禁止操作");
            xzMapper.updateSaveState(xzid, 1);//修改保存状态
            kjTeaVo.setGradeid(xz.getGradeid());
            kjTeaVo.setSchoolid(xz.getSchoolid());

            Integer courseid = 0;//存放新添加课程id

            //先判断是保存当前课程还是后续日期的课
            if (N_Utils.isEmptyInteger(kjTeaVo.getKfollow())) {
                //kfollow为0或者空，则只需要保存当前选中的课程
                courseid = saveOneXzkjDygForDetail(kjTeaVo);
            } else {
                //需要保存后续和当前日期相同的星期相同课节的课程，判断后续日期是否有课程，如果有则提示先删除后再添加
                //获取已生成课程的往后日期
                List<String> alldates = xzMapper.getAllDatesForKj(kjTeaVo.getKjid(), kjTeaVo.getClassid(), kjTeaVo.getSeldate());
                if (alldates != null && alldates.size() > 0) {
                    //去匹配是否包含在当前选中日期后续周对应的日期，主要是为了判断是否有已生成的课
                    List<String> afterlst = LiveUtil.getMeetDayOfDates(alldates, kjTeaVo.getSeldate());
                    if (afterlst != null && afterlst.size() > 0) {
                        return new ResultVo(1, "同日期同班级同课节有数据，不能保存");
                    }
                }

                //说明当前日期（包含当前日期）往后都没有课，则直接处理
                //获取seldate至结束日期时端内符合条件的日期
                List<String> savedates = LiveUtil.getDaysForMeetDates(kjTeaVo.getSeldate(), xz.getEnddate());
                for (int i = 0; i < savedates.size(); i++) {
                    kjTeaVo.setSeldate(savedates.get(i));

                    Integer rtnid = saveOneXzkjDygForDetail(kjTeaVo);
                    if(i==0){
                        courseid = rtnid;
                    }

                }
            }
            return new ResultVo(0, "保存成功", courseid);
        } catch (Exception e) {
            log.error("保存课程表单个课程出错：" + e.getMessage());
            if (e.getMessage().equals("所选班级无学生")) {
                return new ResultVo(1, "保存失败：所选班级无学生");
            } else {
                return new ResultVo(1, "保存失败");
            }
        } finally {
            xzMapper.updateSaveState(xzid, 0);//修改保存状态
        }
    }

    //判断单个课程是否存在如果存在只需要合并班级不存在保存单个课程
    private Integer saveOneXzkjDygForDetail(XzDateKjTeaVo kjTeaVo) throws Exception{
        Integer courseid = 0;
        //先看新选择的教师情况，先判断选中的同一日期课节教师是否还有其他直播课
        CourseVo courseVo = courseMapper.getCourseByDateKjTeacher(kjTeaVo);
        if (courseVo == null) {
            //说明该老师之前没有直播课，则直接保存为新的课程
            LCourse course = new LCourse();
            course.setGradeid(kjTeaVo.getGradeid());
            course.setBegindate(kjTeaVo.getSeldate());
            course.setEnddate(kjTeaVo.getSeldate());
            course.setCoursenum(1);
            course.setCoursetype(1);
            course.setCourseclass(1);
            course.setCoursestate(0);
            course.setDeleted(1);
            course.setCourseselected(0);
            course.setCreateid(kjTeaVo.getCreateid());
            course.setCreatetime(N_Utils.getSecondTimestamp());
            course.setSchoolid(kjTeaVo.getSchoolid());

            String datezhou = LiveUtil.getDateZhou(kjTeaVo.getSeldate());
            LXzKj kj = xzKjMapper.selectByPrimaryKey(kjTeaVo.getKjid());//课节详情

            //单个教师课程信息
            String coursename = datezhou + kj.getKjname() + kjTeaVo.getSubjectname() + "(" + kjTeaVo.getTeachername() + ")";

            course.setCoursename(coursename);
            course.setSubjectid(kjTeaVo.getSubjectid());
            course.setTeacherid(kjTeaVo.getTeacherid());
            course.setBegintime(kj.getBegintime());
            course.setEndtime(kj.getEndtime());
            course.setKjid(kjTeaVo.getKjid());
            //保存行政直播课程表,调用保存整个课表时的方法
            List<XzDateKjTeaVo> lst = new ArrayList<>();
            lst.add(kjTeaVo);

            //获取集合中所有的班级id
            List classidlst = lst.stream().map(XzDateKjTeaVo::getClassid).collect(Collectors.toList());
            List<Map> users = courseMapper.listUid(classidlst);//获取课班级下学生
            //如果所选班级无学生，则抛出异常 提示
            if(users==null || users.size()==0){
                throw new Exception("所选班级无学生");
            }
            courseid = ((XzService) applicationContext.getBean("xzService")).saveCourseAll(lst, course,users);
        } else {
            courseid = courseVo.getCourseid();
            ((XzService) applicationContext.getBean("xzService")).saveOneXzkjDygForDetailExist(kjTeaVo,courseVo);
        }
        return courseid;
    }

    //保存单个表格时同日期同课节教师合并成一个直播课
    @Transactional(rollbackFor = Exception.class)
    public void saveOneXzkjDygForDetailExist(XzDateKjTeaVo kjTeaVo, CourseVo courseVo){
        try {

            //保存直播关联班级
            int timestamp = N_Utils.getSecondTimestamp();
            LCourseClass courseClass = new LCourseClass();
            courseClass.setCourseid(courseVo.getCourseid());
            courseClass.setClassid(kjTeaVo.getClassid());
            courseClass.setCreateid(kjTeaVo.getTeacherid());
            courseClass.setCreatetime(timestamp);
            courseClassMapper.insertUseGeneratedKeys(courseClass);

            //说明该教师当前有其他直播课，则把班级加入课程，完成直播课学生数量
            TClassStudent cs = new TClassStudent();
            cs.setSchoolid(kjTeaVo.getSchoolid());
            cs.setClassid(kjTeaVo.getClassid());
            cs.setCreateid(kjTeaVo.getCreateid());
            cs.setCreatetime(timestamp);
            classStudentMapper.saveAllClassStu(cs, courseVo.getClassid());
            //获取直播班对应全班学生分组id
            Integer groupid = groupMapper.getGroupIdByClassid(courseVo.getClassid());
            groupMapper.saveAllClassGroupStu(cs, courseVo.getClassid(), groupid);
            classMapper.updateNum2(courseVo.getClassid());//更改直播班级以及班级分组人数
            courseMapper.updateStuNum(courseVo.getCourseid());//更新直播课学生数量
        } catch (Exception e) {
            log.error("保存单个课程(课程已存在合并班级)出错：" + e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new MissingParametersException(e.getMessage());
        }
    }

    /**
     * 课表导入
     *
     * @return com.xhkjedu.vo.ResultVo
     * @Param [file, xzid, createid]
     * @Author ywx
     * @Date 2022/6/22 11:42
     **/
    @Transactional(rollbackFor = Exception.class)
    public ResultVo importKb(MultipartFile file, Integer xzid, Integer createid) {
        try {
            //获取行政直播信息
            LXz xz = xzMapper.selectByPrimaryKey(xzid);
            if (xz.getSavestate() != 0) return new ResultVo(1, "有课表在保存中禁止操作");
            xzMapper.updateSaveState(xzid, 1);//修改保存状态
            List<XzKjVo> kjs = xzKjMapper.listXzKjByXzId(xzid);//获取行政直播课节详情
            Integer noTimeKjNum = kjs.stream().filter(k -> k.getBegintime() == null).collect(Collectors.toList()).size();
            if (noTimeKjNum != 0) {
                xzMapper.updateSaveState(xzid, 0);
                return new ResultVo(1, "请设置课节时间");
            }

            //根据行政直播id获取该学校当前年份指定年级下的行政班和提高班
            Integer gradeid = xz.getGradeid();
            Integer schoolid = xz.getSchoolid();
            Integer year = schoolMapper.getYearById(schoolid);
            List<XzClassVo> classlst = classMapper.listClassByXzid(schoolid, gradeid);
            String classids = classlst.stream().map((XzClassVo::getClassid)).map(String::valueOf).collect(Collectors.joining(","
            ));
            List<CTeacherVo> teachers = classTeacherMapper.listTeacherByClassIds(classids);//获取班级教师
            if (!N_Utils.isListNotEmpty(teachers)) {
                xzMapper.updateSaveState(xzid, 0);
                return new ResultVo(1, "请设置班级任教老师");
            }

            String teacherids =
                    teachers.stream().map((CTeacherVo::getTeacherid)).map(String::valueOf).collect(Collectors.joining(","));
            List<CTeacherVo> subjects = classTeacherMapper.listSubjectByTeacherIds(teacherids);//获取教师科目
            String subjectids = subjects.stream().map(CTeacherVo::getSubjectid).distinct().collect(Collectors.joining("','"));
            List<CTeacherVo> subjects2 = classTeacherMapper.listSubjectBySubjectIds(subjectids);
            Map<String, String> subjectNameMap = subjects2.stream().collect(Collectors.toMap(CTeacherVo::getSubjectid,
                    CTeacherVo::getSubjectname));
            Map<Integer, String> subjectMap = subjects.stream().collect(Collectors.toMap(CTeacherVo::getTeacherid,
                    CTeacherVo::getSubjectid));
            Map<Integer, String> classMap = classlst.stream().collect(Collectors.toMap(XzClassVo::getClassid,
                    XzClassVo::getClassname));
            List<CTeacherVo> users = classTeacherMapper.listTeacherBySchoolId(schoolid);//获取学校所有教师
            Set<String> userNameSet = users.stream().map(CTeacherVo::getUsername).collect(Collectors.toCollection(TreeSet::new));
            Map<String, CTeacherVo> classTeacherMap = new HashMap<>();//班级教师map
            for (CTeacherVo teacher : teachers) {
                CTeacherVo vo =
                        users.stream().filter(u -> u.getTeacherid().equals(teacher.getTeacherid())).findFirst().orElse(null);
                if (vo != null) teacher.setUsername(vo.getUsername());
                teacher.setClassname(classMap.get(teacher.getClassid()));
                teacher.setSubjectid(subjectMap.get(teacher.getTeacherid()));
                teacher.setSubjectname(subjectNameMap.get(teacher.getSubjectid()));
                classTeacherMap.put(teacher.getClassname() + "_" + teacher.getUsername(), teacher);
            }

            Map<String, Object> map = PoiUtils.readKb(file, xz, classTeacherMap, userNameSet, kjs);
            Integer code = (Integer) map.get("code");
            if (code != 0) {
                xzMapper.updateSaveState(xzid, 0);
                return new ResultVo(1, map.get("msg").toString());
            }
            LinkedHashMap<String, List<String>> errMsg = (LinkedHashMap<String, List<String>>) map.get("errMsg");
            if (errMsg.size() != 0) {
                xzMapper.updateSaveState(xzid, 0);
                return new ResultVo(1, null, errMsg);
            }

            List<LCourse> kjTeas = (List<LCourse>) map.get("kjTeas");
            if (N_Utils.isListEmpty(kjTeas)) return new ResultVo(0, "导入课表成功");
            List<Integer> delCourseIds = (List<Integer>) map.get("delCourseIds");
            if (N_Utils.isListNotEmpty(delCourseIds)) {
                courseMapper.batchDelCourse(delCourseIds);//批量删除课程
            }

            classids = kjTeas.stream().map(LCourse::getClassid).distinct().map(String::valueOf).collect(Collectors.joining(","));
            List<CStudentVo> cStudents = classStudentMapper.listByClassIds(classids);//班级学生列表

            Map<String, List<LCourse>> courseMap =
                    kjTeas.stream().collect(Collectors.groupingBy(l -> l.getCoursename() + "_" + l.getBegindate()));

            new Thread(() -> {
                for (Map.Entry<String, List<LCourse>> entry : courseMap.entrySet()) {
                    importOneCourse(createid, gradeid, schoolid, year, cStudents, entry);//导入单个课
                }
                //导入成功修改当前步骤为3设置完成
                xzMapper.updateCurstepByXzid(3, xzid);
            }).start();
            return new ResultVo(0, "导入课表成功");
        } catch (Exception e) {
            log.error("导入课表出错：" + e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            xzMapper.updateSaveState(xzid, 0);//修改保存状态
            throw new MissingParametersException(e.getMessage());
        }
    }

    //导入单个课
    @Async("asyncPoolTaskExecutor")
    public void importOneCourse(Integer createid, Integer gradeid, Integer schoolid, Integer year
            , List<CStudentVo> cStudents, Map.Entry<String, List<LCourse>> entry) {
        List<LCourse> courses = entry.getValue();
        List<Integer> cids = courses.stream().map(LCourse::getClassid).collect(Collectors.toList());
        Set<Integer> studentids = new HashSet<>();
        cids.forEach(c -> studentids.addAll(cStudents.stream().filter(s -> s.getClassid().equals(c))
                .map(CStudentVo::getStudentid).collect(Collectors.toList())));
        int stunum = studentids.size();//学生数量
        LCourse course = courses.get(0);
        int createtime = N_Utils.getSecondTimestamp();
        String coursename = course.getCoursename();
        //新生成直播班班级信息
        TClass c = new TClass();
        c.setClassname(coursename + "班");
        c.setCreateid(createid);
        c.setSchoolid(schoolid);
        c.setSchoolyear(year);
        c.setYear(year);
        c.setClassorder(999);
        c.setGradeid(gradeid);
        c.setClasstype(99);//已直播班级
        c.setCreatetime(createtime);
        c.setClassnum(stunum);
        c.setClassstate(1);
        classMapper.insertUseGeneratedKeys(c);
        Integer classid = c.getId();

        course.setClassid(classid);
        course.setClassids(cids);
        course.setGradeid(gradeid);
        course.setCoursenum(1);
        course.setCoursetype(1);
        course.setCourseclass(1);
        course.setCoursestate(0);
        course.setDeleted(1);
        course.setCourseselected(0);
        course.setCreateid(createid);
        course.setCreatetime(createtime);
        course.setSchoolid(schoolid);
        course.setStunum(stunum);
        courseMapper.insertUseGeneratedKeys(course);
        Integer teacherid = course.getTeacherid();
        Integer courseid = course.getId();

        //课节
        LCourseSection cs = new LCourseSection();
        cs.setSectionname(coursename);
        cs.setTeacherid(teacherid);
        cs.setSectionorder(1);
        cs.setSectiondate(course.getBegindate());
        cs.setPlanbegintime(course.getBegintime());
        cs.setPlanendtime(course.getEndtime());
        cs.setStunum(0);
        cs.setSectionstate(0);
        cs.setCreateid(createid);
        cs.setCreatetime(createtime);
        cs.setCourseid(courseid);
        courseSectionMapper.insertSelective(cs);

        TClassTeacher ct = new TClassTeacher();
        ct.setTeacherid(teacherid);
        ct.setCreateid(createid);
        ct.setCreatetime(createtime);
        ct.setSchoolid(schoolid);
        ct.setClassid(classid);
        classTeacherMapper.insertSelective(ct);

        //创建全体分组
        TGroup group = new TGroup();
        group.setGroupname("全班学生");
        group.setGrouptype(1);
        group.setCreateid(createid);
        group.setSchoolid(schoolid);
        group.setCreatetime(createtime);
        group.setClassid(classid);
        group.setGroupnum(stunum);
        groupMapper.insertUseGeneratedKeys(group);
        Integer groupid = group.getId();

        List<LCourseClass> courseClassList = new ArrayList<>();//课程关联班级集合
        List<TClassStudent> classStudentList = new ArrayList<>();//课程班级学生集合
        List<TGroupStudent> groupStudentList = new ArrayList<>();//课程班级分组学生集合

        for (Integer cid : cids) {
            LCourseClass cc = new LCourseClass();
            cc.setCourseid(courseid);
            cc.setClassid(cid);
            cc.setCreateid(createid);
            cc.setCreatetime(createtime);
            courseClassList.add(cc);
        }
        for (Integer studentid : studentids) {
            //班级学生
            TClassStudent student = new TClassStudent();
            student.setClassid(classid);
            student.setStudentid(studentid);
            student.setXzed(0);//是否是直播行政班学生0是1否（加入的非直播班级学生）
            student.setCreateid(createid);
            student.setCreatetime(createtime);
            student.setSchoolid(schoolid);
            classStudentList.add(student);

            //分组学生
            TGroupStudent gs = new TGroupStudent();
            gs.setClassid(classid);
            gs.setGroupid(groupid);
            gs.setStudentid(studentid);
            gs.setXzed(0);//是否是直播行政班学生0是1否（加入的非直播班级学生）
            gs.setCreateid(createid);
            gs.setCreatetime(createtime);
            gs.setSchoolid(schoolid);
            groupStudentList.add(gs);
        }

        courseClassMapper.insertList(courseClassList);//批量保存课程关联班级
        classStudentMapper.insertList(classStudentList);//批量保存课程班级学生
        groupStudentMapper.insertList(groupStudentList);//批量保存课程分组学生
    }

    //获取保存状态
    public Integer getSaveStateById(Integer xzid) {
        return xzMapper.getSaveStateById(xzid);
    }
}
