package com.xhkjedu.slive.service.liveplay;

import com.alibaba.fastjson.JSON;
import com.xhkjedu.slive.mapper.gradeclass.ClassMapper;
import com.xhkjedu.slive.mapper.gradeclass.ClassTeacherMapper;
import com.xhkjedu.slive.mapper.gradeclass.SchoolMapper;
import com.xhkjedu.slive.mapper.liveplay.CourseMapper;
import com.xhkjedu.slive.mapper.liveplay.CourseSectionMapper;
import com.xhkjedu.slive.mapper.recordserver.RecordserverMapper;
import com.xhkjedu.slive.mapper.system.UserMapper;
import com.xhkjedu.slive.model.gradeclass.TClass;
import com.xhkjedu.slive.model.gradeclass.TClassTeacher;
import com.xhkjedu.slive.model.liveplay.LCourse;
import com.xhkjedu.slive.model.liveplay.LCourseSection;
import com.xhkjedu.slive.model.liveplay.LCourseSectionStudent;
import com.xhkjedu.slive.vo.gradeclass.CStudentVo;
import com.xhkjedu.slive.vo.liveplay.*;
import com.xhkjedu.utils.N_Utils;
import com.xhkjedu.vo.ResultVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @author ywx
 * @classname CourseSectionService
 * @description 
 * @date 2021/1/15 12:33
 **/
@Service
@Slf4j
public class CourseSectionService {
    @Resource
    private CourseSectionMapper courseSectionMapper;
    @Resource
    private CourseMapper courseMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private ClassTeacherMapper classTeacherMapper;
    @Resource
    private ClassMapper classMapper;
    @Resource
    private SchoolMapper schoolMapper;
    @Resource
    private RecordserverMapper recordserverMapper;

    //添加
    @Transactional(rollbackFor = Exception.class)
    public ResultVo save(LCourseSection model) {
        LCourse c = courseMapper.selectByPrimaryKey(model.getCourseid());
        //20210622不再限制，管理员可以给教师添加的课程添加课节
        /*if (!model.getCreateid().equals(c.getCreateid())) {
            return new ResultVo(1, "没有添加课节权限");
        }*/
        model.setTotaltime(0);
        model.setCreatetime(N_Utils.getSecondTimestamp());
        try {
            courseSectionMapper.insertSelective(model);
            courseMapper.updateCourseNum(model.getCourseid());//更新课节数量
            updateCourseTeacher(model.getCourseid());//更新课程教师
            return new ResultVo(0, "保存成功");
        } catch (Exception e) {
            log.error("添加课节失败",e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new ResultVo(1, "保存失败");
        }
    }

    //删除
    public ResultVo deleteById(Integer sectionid, Integer courseid, Integer createid) {
        /*LCourseSection section = findById(sectionid);
        Integer usertype = userMapper.getUserTypeByUserId(createid);
        if(usertype!=0 && !createid.equals(section.getCreateid())){
            //只有学校管理员和自己创建的课节才可删除（没有删除课节权限）
            return new ResultVo(1,"没有删除课节权限");
        }*/
        courseSectionMapper.deleteByPrimaryKey(sectionid);
        courseMapper.updateCourseNum(courseid);//更新课节数量
        return new ResultVo(0,"删除成功");
    }

    //修改
    @Transactional(rollbackFor = Exception.class)
    public ResultVo update(LCourseSection model) {
        LCourseSection section = findById(model.getSectionid());
        /*Integer createid = model.getCreateid();
        Integer usertype = userMapper.getUserTypeByUserId(createid);
        if(usertype!=0 && !createid.equals(section.getCreateid())){
            //只有学校管理员和自己创建的课节才可修改（没有修改课节权限）
            return new ResultVo(1,"没有修改课节权限");
        }*/
        ResultVo result = isUpdateResultVo(section);
        if (result != null) return result;
        try {
            model.setSectionstate(null);
            courseSectionMapper.updateByPrimaryKeySelective(model);
            Integer teacherid = model.getTeacherid();
            if (!N_Utils.isEmptyInteger(teacherid) && !teacherid.equals(section.getTeacherid())) {
                Integer courseid = section.getCourseid();
                updateCourseTeacher(courseid);//更新课程教师
            }
            return new ResultVo(0, "修改成功");
        } catch (Exception e) {
            log.error("修改课节失败", e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new ResultVo(1, "修改失败");
        }
    }

    //课节是否可以修改
    private ResultVo isUpdateResultVo(LCourseSection section) {
        Integer sectionstate = section.getSectionstate();
        if (2 == sectionstate) {
            return new ResultVo(1, "进行中的课节禁止修改");
        } else if (3 == sectionstate) {
            return new ResultVo(1, "已结束的课节禁止修改");
        } else if (4 == sectionstate) {
            return new ResultVo(1, "已过期的课节禁止修改");
        }
        String sectiondate = section.getSectiondate();
        String planbegintime = section.getPlanbegintime();
        StringBuilder sb = new StringBuilder();
        sb.append(sectiondate).append(" ").append(planbegintime).append(":00");
        int time = N_Utils.getDataToTimestamp(sb.toString(), "yyyy-MM-dd HH:mm:ss");
        int timestamp = N_Utils.getSecondTimestamp();
        if ((time - timestamp) < 600) {
            return new ResultVo(1, "开播前10分钟禁止修改");
        }
        return null;
    }

    //更新课程教师
    private void updateCourseTeacher(Integer courseid) {
        Integer createid;
        List<Integer> teacherids = courseSectionMapper.listTeacherId(courseid);

        if (teacherids != null && teacherids.size() > 0) {
            LCourse course = courseMapper.selectByPrimaryKey(courseid);
            Integer classid = course.getClassid();
            createid = course.getCreateid();
            Integer schoolid = course.getSchoolid();
            classTeacherMapper.deleteByClassId(classid);
            List<TClassTeacher> teachers = new ArrayList<>();
            for (Integer tid : teacherids) {
                TClassTeacher ct = new TClassTeacher();
                ct.setClassid(classid);
                ct.setTeacherid(tid);
                ct.setCreateid(createid);
                ct.setCreatetime(N_Utils.getSecondTimestamp());
                ct.setSchoolid(schoolid);
                teachers.add(ct);
            }
            classTeacherMapper.insertList(teachers);
        }
    }

    //获取详情
    public LCourseSection findById(Integer sectionid) {
        return courseSectionMapper.selectByPrimaryKey(sectionid);
    }

    //巡课详情
    public Map xkDetail(Integer sectionid) {
        return courseSectionMapper.xkDetail(sectionid);
    }

    //获取课程课节列表
    public List <CourseSectionVo> listByCourseId(Integer courseid, Integer teacherid) {
        return courseSectionMapper.listByCourseId(courseid, teacherid);
    }

    //批量添加
    @Transactional(rollbackFor = Exception.class)
    public ResultVo batchSave(List<LCourseSection> sections) {
        sections.forEach(s->{
            s.setCreatetime(N_Utils.getSecondTimestamp());
            s.setTotaltime(0);
        });
        try {
            courseSectionMapper.insertList(sections);
            courseMapper.updateCourseNum(sections.get(0).getCourseid());//更新课节数量
            updateCourseTeacher(sections.get(0).getCourseid());//更新课程教师
            return new ResultVo(0,"批量添加课节成功");
        } catch (Exception e) {
            log.error("批量添加课节失败",e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new ResultVo(1,"添加失败");
        }
    }

    //修改课节状态
    public ResultVo updateState(LCourseSection section) {
        LCourseSection cs = courseSectionMapper.selectByPrimaryKey(section.getSectionid());
        LCourse course = courseMapper.selectByPrimaryKey(cs.getCourseid());
        if (course.getDeleted() == 10) return new ResultVo(1,"该课程已删除");
        courseSectionMapper.updateState(section);
        return new ResultVo(0,"开课成功");
    }

    public synchronized void updateSectionState2() {
        final ExecutorService exec = Executors.newFixedThreadPool(1);
        try {
            Callable<String> call = new Callable() {
                @Override
                public String call() throws IOException {
                    List<CourseSectionVo> sections = courseSectionMapper.listPendingSection();//获取要处理的课节
                    if (N_Utils.isListEmpty(sections)) return "执行成功";
                    List<Integer> sectionids = new ArrayList<>();
                    for (CourseSectionVo section : sections) {
                        Integer sectionstate = section.getSectionstate();
                        if (sectionstate == 2) {//进行中的课
                            sectionstate = 3;
                            section.setEndtime(section.getPlanendtime());
                            sectionids.add(section.getSectionid());
                        } else {//已过期的课
                            sectionstate = 4;
                        }
                        section.setSectionstate(sectionstate);
                    }
                    courseSectionMapper.updateSectionState(sections);//批量修改课节状态
                    if (N_Utils.isListEmpty(sectionids)) return "执行成功";
                    //更新课节学生在线状态为下线
                    Integer nowtime = N_Utils.getSecondTimestamp();
                    courseSectionMapper.updateStuOnLined(sectionids,nowtime);
                    stop(sectionids);
                    return "执行成功";
                }
            };
            Future<String> future = exec.submit(call);
            future.get(10, TimeUnit.SECONDS); //任务处理超过10s关闭
        } catch (TimeoutException e) {
            System.out.println("定时任务修改课节状态超时");
        } catch (Exception e) {
            System.out.println("定时任务修改课节状态失败:" + e.getMessage());
        }
        // 关闭线程池
        exec.shutdown();
    }

    @Async("asyncPoolTaskExecutor")
    //停止录制
    public void stop(List<Integer> sectionids) {
        List<CourseSectionPlaybackVo> list = courseSectionMapper.listPlayBackByIds(sectionids);
        for (CourseSectionPlaybackVo vo : list) {
            try {
                String rspath = vo.getRspath();
                if (N_Utils.isEmpty(rspath)) return;
                String param = JSON.toJSONString(vo);
                //停止录制
                N_Utils.sendJsonPost(rspath + "/recorder/v1/stop", param);
            } catch (Exception e) {
                log.error("停止录制失败", e.getMessage());
            }
        }
    }

    //课节统计
    public Map<String, Integer> analyze(Integer sectionid, Integer classid) {
        return courseSectionMapper.analyze(sectionid, classid);
    }

    //根据日期获取教师课节列表
    public List<CourseSectionVo> listByDate(LCourseSection section) {
        int timestamp = N_Utils.getSecondTimestamp();
        String strtime = N_Utils.getStrtimeTimestamp(timestamp, "yyyy-MM-dd HH:mm");
        section.setStrtime(strtime);
        return courseSectionMapper.listByDate(section);
    }

    //根据日期获取巡课课节列表
    public List<CourseSectionVo> listXkByDate(CourseParams p) {
        int timestamp = N_Utils.getSecondTimestamp();
        String strtime = N_Utils.getStrtimeTimestamp(timestamp, "yyyy-MM-dd HH:mm");
        p.setStrtime(strtime);
        return courseSectionMapper.listXkByDate(p);
    }

    //设置教师任教行政和提高班id
    public void setClassIds(CourseParams p) {
        if (p.getUsertype() == 1 && N_Utils.isEmptyInteger(p.getClassid())) {
            String classIds = classTeacherMapper.getClassIds(p.getTeacherid(),p.getSchoolid());//获取教师任教行政和提高班id
            p.setClassids(classIds);
        }
    }

    //修改教师上课时长
    public void updateTime(LCourseSection section) {
        courseSectionMapper.updateTime(section);
    }

    public Map getReport(Integer sectionid) {
        Map report = courseSectionMapper.getReport(sectionid);
        List<CStudentVo> students = (List<CStudentVo>) report.get("students");
        List<String> qqStu = new ArrayList<>();//缺勤名单
        List<String> sdStu = new ArrayList<>();//实到名单
        for (CStudentVo student : students) {
            String studentname = student.getStudentname();
            if (student.getStudentid() == null) {
                qqStu.add(studentname);
            } else {
                sdStu.add(studentname);
            }
        }
        report.put("sdStu",sdStu);
        report.put("qqStu",qqStu);
        report.remove("students");
        return report;
    }

    //教师app课节报告
    public Map getReport2(Integer sectionid) {
        Map report = courseSectionMapper.getReport(sectionid);
        List<CStudentVo> students = (List<CStudentVo>) report.get("students");
        List<Map> qqStu = new ArrayList<>();//缺勤名单
        List<Map> sdStu = new ArrayList<>();//实到名单
        for (CStudentVo student : students) {
            String studentname = student.getStudentname();
            String headpic = student.getHeadpic();
            if (student.getStudentid() == null) {
                Map qq = new HashMap();
                qq.put("studentname", studentname);
                qq.put("headpic", headpic);
                qqStu.add(qq);
            } else {
                Map sd = new HashMap();
                sd.put("studentname", studentname);
                sd.put("headpic", headpic);
                sdStu.add(sd);
            }
        }
        report.put("sdStu", sdStu);
        report.put("qqStu", qqStu);
        report.remove("students");
        return report;
    }

    //课程班级列表
    public List<Map> listClass(Integer courseid) {
        CourseVo course = courseMapper.getTypeClassGradeById(courseid);//获取直播类型、班级、年级
        return courseSectionMapper.listClass(course);
    }

    //课节观看列表
    public List<Map> listView2(LCourseSectionStudent section, Integer coursetype) {
        return courseSectionMapper.listView2(section, coursetype);
    }

    public CourseVo getCourseVo(LCourseSectionStudent section) {
        CourseVo course = courseSectionMapper.getTotalTime(section.getSectionid());
        return course;
    }

    //学生观看详情列表
    public List<CSVStudentVo> listStuView(LCourseSectionStudent section) {
        List<CSVStudentVo> list = courseSectionMapper.listStuView(section);
        Integer totaltime = list.stream().collect(Collectors.summingInt(s -> s.getTotaltime()));
        for (CSVStudentVo s : list) {
            s.setSeerate(N_Utils.getIntegerDivideAndMulitiply(s.getTotaltime(), totaltime));
        }
        return list;
    }

    //课节提问列表
    public List<Map> listAsk(Integer sectionid) {
        return courseSectionMapper.listAsk(sectionid);
    }

    //获取课节提问详情
    public List<Map> listAskStu(String satid) {
        return courseSectionMapper.listAskStu(satid);
    }

    //获取课节提问详情
    public Map listAskStu2(String satid) {
        return courseSectionMapper.listAskStu2(satid);
    }

    //我的月份下日期课节数量
    public List<Map> listMySectionDate(CourseParams params) {
        return courseSectionMapper.listMySectionDate(params);
    }

    //我的课程列表
    public List<Map> listMySection(CourseParams params) {
        int timestamp = N_Utils.getSecondTimestamp();
        String strtime = N_Utils.getStrtimeTimestamp(timestamp, "yyyy-MM-dd HH:mm");
        params.setStrtime(strtime);
        return courseSectionMapper.listMySection(params);
    }

    //修改课节、课程名称， 时间，日期
    public ResultVo myUpdate(LCourseSection section) {
        /*CourseVo course = courseSectionMapper.getCourseById(section.getSectionid());
        if (!section.getCreateid().equals(course.getCreateid()) || course.getSectionnum() != 1
                || course.getCoursestate() != 0) {
            return new ResultVo(1,"没有修改课节权限");
        }*/
        courseSectionMapper.myUpdate(section);
        return new ResultVo(0,"修改成功");
    }

    //删除课程
    public ResultVo deleteCourse(LCourseSection section) {
        CourseVo course = courseSectionMapper.getCourseById(section.getSectionid());
        /*if (!section.getCreateid().equals(course.getCreateid()) || course.getSectionnum() != 1) {
            return new ResultVo(1,"没有删除课节权限");
        }*/
        //标识课程为逻辑删除deleted=10
        courseMapper.updateCourseDeleted(course.getCourseid(),10);
        //标识班级状态为10
        classMapper.updateClassstateByClassid(course.getClassid(),10);
        return new ResultVo(0,"删除成功");
    }

    //根据班级id获取课程班级类型
    public Integer getCourseTypeByClassId(Integer classid) {
        return courseSectionMapper.getCourseTypeByClassId(classid);
    }

    //获取课程学生列表
    public List<Map> listStudent(CourseParams params) {
        List<Map> list = courseSectionMapper.listStudent(params);
        return list;
    }

    /**
     * 获取当前班级年份
     *
     * @param [classid]
     * @return java.lang.Integer
     * @author ywx
     * @date 2022/4/8 21:02
     */
    public Integer getYearByClassId(Integer classid) {
        return classMapper.getYearById(classid);
    }

    //学生课节日历
    public List<Map> listStuSectionDate(CourseParams params) {
        return courseSectionMapper.listStuSectionDate(params);
    }

    //学生课节列表
    public List<Map> listStuByDate(CourseParams params) {
        int timestamp = N_Utils.getSecondTimestamp();
        String strtime = N_Utils.getStrtimeTimestamp(timestamp, "yyyy-MM-dd HH:mm");
        params.setStrtime(strtime);
        return courseSectionMapper.listStuByDate(params);
    }

    //直播管理-月份下日期课节数量
    public List<Map> listDateForZbGl(CourseParams params) {
        return courseSectionMapper.listDateForZbGl(params);
    }

    //直播管理-课节列表
    public List<Map> listGlByDate(CourseParams params) {
        int timestamp = N_Utils.getSecondTimestamp();
        String strtime = N_Utils.getStrtimeTimestamp(timestamp, "yyyy-MM-dd HH:mm");
        params.setStrtime(strtime);
        return courseSectionMapper.listGlByDate(params);
    }

    //直播管理-课节详情
    public List<Map> listZbKj(Integer courseid) {
        return courseSectionMapper.listZbKj(courseid);
    }

    //直播管理-学生列表
    public List<Map> listZbXs(CourseParams params) {
        List<Map> list = courseSectionMapper.listZbXs(params);
        return list;
    }

    //获取班级信息
    public TClass getClassById(Integer classid) {
        return classMapper.selectByPrimaryKey(classid);
    }

    //获取课程年份和班级ids
    public CourseParams getCourseParamByCid(Integer classid) {
        return courseSectionMapper.getCourseParamByCid(classid);
    }

    //教师巡课-学生列表
    public List<Map> listXkXs(CourseParams params) {
        return courseSectionMapper.listXkXs(params);
    }

    //获取课节主讲人
    public List<Map> getZjr(Integer sectionid) {
        return courseSectionMapper.getZjr(sectionid);
    }

    //课节是否可以修改
    public ResultVo isUpdate(Integer sectionid) {
        LCourseSection section = findById(sectionid);
        ResultVo result = isUpdateResultVo(section);
        if (result != null) {
            return result;
        } else {
            return new ResultVo(0, "可以修改");
        }
    }
}
