package org.dromara.system.service.impl;

import lombok.SneakyThrows;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.domain.dto.RoleDTO;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.domain.bo.FormalTeacherClassBo;
import org.dromara.system.domain.vo.CourseChangeVo;
import org.dromara.system.domain.vo.CourseTableTimeVo;
import org.dromara.system.domain.vo.FormalTeacherClassVo;
import org.dromara.system.mapper.CourseChangeMapper;
import org.dromara.system.mapper.CourseTableTimeMapper;
import org.dromara.system.service.IFormalTeacherClassService;
import org.springframework.data.redis.cache.RedisCache;
import org.springframework.stereotype.Service;
import org.dromara.system.domain.bo.CourseTableBo;
import org.dromara.system.domain.vo.CourseTableVo;
import org.dromara.system.domain.CourseTable;
import org.dromara.system.mapper.CourseTableMapper;
import org.dromara.system.service.ICourseTableService;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 课程Service业务层处理
 *
 * @author Lion Li
 * @date 2023-08-16
 */
@RequiredArgsConstructor
@Service
public class CourseTableServiceImpl implements ICourseTableService {

    private final CourseTableMapper baseMapper;

    private final CourseChangeMapper courseChangeMapper;

    private final CourseTableTimeMapper courseTableTimeMapper;

    private final IFormalTeacherClassService formalTeacherClassService;

    /**
     * 查询课程
     */
    @Override
    public CourseTableVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询课程列表
     */
    @SneakyThrows
    @Override
    public TableDataInfo<CourseTableVo> queryPageList(CourseTableBo bo, PageQuery pageQuery) {
        if(StringUtils.isEmpty(bo.getClassId()) || StringUtils.isEmpty(bo.getSchoolId())){
            return TableDataInfo.build(new ArrayList<>());
        }
        LambdaQueryWrapper<CourseTable> lqw = buildQueryWrapper(bo);
        Page<CourseTableVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        List<CourseTableVo> courseTableList = result.getRecords();


        //获取本周一和本周五的时间
        String fist = DateUtils.getTimeIntervalOne(new Date());
        String five = DateUtils.getTimeIntervalFive(fist);
        List<CourseChangeVo> courseChangeList = courseChangeMapper.selectCourseChangeListByEdit(bo.getClassId(), fist, five);
        if (courseChangeList != null && courseChangeList.size() >0){
            for (CourseTableVo table : courseTableList) {
                //将修改后的课程放入当前周课表
                changeCourseTable(table,courseChangeList,fist,five);
            }

            //如果当前角色是老师，获取老师的课程
            LoginUser user = LoginHelper.getLoginUser();
            Map<String, Object> params = bo.getParams();
            String ro = "";
            if (params != null && params.size() > 0) {
                ro = (String) params.get("role");
            }
            if(StringUtils.isNotEmpty(ro) && "teacher".equals(ro)){
                //查询老师当前班级所带的课
                FormalTeacherClassBo ftbo = new FormalTeacherClassBo();
                ftbo.setClassId(Long.valueOf(bo.getClassId()));
                ftbo.setTeacherId(user.getUserId());
                List<FormalTeacherClassVo> flVoList = formalTeacherClassService.queryList(ftbo);
                List<String> disciplineName = flVoList.stream().map(FormalTeacherClassVo::getDiscipline).collect(Collectors.toList());
                maekers(courseTableList, disciplineName);
            }
        }

        return TableDataInfo.build(result);
    }

    @SneakyThrows
    @Override
    public TableDataInfo<CourseTableVo> queryPagePcList(CourseTableBo bo, PageQuery pageQuery) {
        if(StringUtils.isEmpty(bo.getClassId()) || StringUtils.isEmpty(bo.getSchoolId())){
            return TableDataInfo.build(new ArrayList<>());
        }
        LambdaQueryWrapper<CourseTable> lqw = buildQueryWrapper(bo);
        Page<CourseTableVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        List<CourseTableVo> courseTableList = result.getRecords();

        //获取本周一和本周五的时间
        String fist = DateUtils.getTimeIntervalOne(new Date());
        String five = DateUtils.getTimeIntervalFive(fist);
        List<CourseChangeVo> courseChangeList = courseChangeMapper.selectCourseChangeListByEdit(bo.getClassId(), fist, five);
        if (courseChangeList != null && courseChangeList.size() >0){
            for (CourseTableVo table : courseTableList) {
                //将修改后的课程放入当前周课表
                changeCourseTable(table,courseChangeList,fist,five);
            }

            //如果当前角色是老师，获取老师的课程
            LoginUser user = LoginHelper.getLoginUser();
            List<RoleDTO> roles = user.getRoles();
            boolean bl = false;
            for (RoleDTO role : roles) {
                if ("teacher".equals(role.getRoleKey())) {
                    bl = true;
                    break;
                }
            }
            if (bl) {
                //查询老师当前班级所带的课
                FormalTeacherClassBo ftbo = new FormalTeacherClassBo();
                ftbo.setClassId(Long.valueOf(bo.getClassId()));
                ftbo.setTeacherId(user.getUserId());
                List<FormalTeacherClassVo> flVoList = formalTeacherClassService.queryList(ftbo);
                List<String> disciplineName = flVoList.stream().map(FormalTeacherClassVo::getDiscipline).collect(Collectors.toList());

                maekers(courseTableList, disciplineName);
            }
        }

        return TableDataInfo.build(result);
    }


    private void maekers(List<CourseTableVo> courseTableList, List<String> disciplineName) {
        //判断老师所带的课程
        for (CourseTableVo table : courseTableList) {
            table.setTeacherClassName(disciplineName);
            Set<Long> teacherClassNum = new HashSet<>();
            if(disciplineName.contains(table.getOneClass())){
                teacherClassNum.add(1L);
            }
            if(disciplineName.contains(table.getTwoClass())){
                teacherClassNum.add(2L);
            }
            if(disciplineName.contains(table.getThreeClass())){
                teacherClassNum.add(3L);
            }
            if(disciplineName.contains(table.getFourClass())){
                teacherClassNum.add(4L);
            }
            if(disciplineName.contains(table.getFiveClass())){
                teacherClassNum.add(5L);
            }
            if(disciplineName.contains(table.getSixClass())){
                teacherClassNum.add(6L);
            }
            if(disciplineName.contains(table.getSevenClass())){
                teacherClassNum.add(7L);
            }
            if(disciplineName.contains(table.getEightClass())){
                teacherClassNum.add(8L);
            }
            table.setTeacherClassNum(teacherClassNum);
        }
    }

    @SneakyThrows
    private void changeCourseTable(CourseTableVo table, List<CourseChangeVo> courseChangeList, String fist, String five) {
        String format = "yyyy-MM-dd";
        Set<Long> classNum = new HashSet<>();
        for (CourseChangeVo courseChange : courseChangeList) {
            //调课的时间是否在本周
            if(DateUtils.isClass(fist,five,DateUtils.dateTime(courseChange.getSubjectTime()),format)){
                if(StringUtils.equals(courseChange.getSubjectWeek(),table.getWeek())){
                    classNum.add(Long.valueOf(courseChange.getIsNum()));
                    //第几节课
                    if(StringUtils.equals("1",courseChange.getIsNum())){
                        table.setOneClass(courseChange.getBeSubject());
                        table.setOneTeacher(courseChange.getBePersonnel());
                    }else if(StringUtils.equals("2",courseChange.getIsNum())){
                        table.setTwoClass(courseChange.getBeSubject());
                        table.setTwoTeacher(courseChange.getBePersonnel());
                    }else if(StringUtils.equals("3",courseChange.getIsNum())){
                        table.setThreeClass(courseChange.getBeSubject());
                        table.setThreeTeacher(courseChange.getBePersonnel());
                    }else if(StringUtils.equals("4",courseChange.getIsNum())){
                        table.setFourClass(courseChange.getBeSubject());
                        table.setFourTeacher(courseChange.getBePersonnel());
                    }else if(StringUtils.equals("5",courseChange.getIsNum())){
                        table.setFiveClass(courseChange.getBeSubject());
                        table.setFiveTeacher(courseChange.getBePersonnel());
                    }else if(StringUtils.equals("6",courseChange.getIsNum())){
                        table.setSixClass(courseChange.getBeSubject());
                        table.setSixTeacher(courseChange.getBePersonnel());
                    }else if(StringUtils.equals("7",courseChange.getIsNum())){
                        table.setSevenClass(courseChange.getBeSubject());
                        table.setSevenTeacher(courseChange.getBePersonnel());
                    }else if(StringUtils.equals("8",courseChange.getIsNum())){
                        table.setEightClass(courseChange.getBeSubject());
                        table.setEightTeacher(courseChange.getBePersonnel());
                    }
                }
            }
            //被调课是否在本周
            if(DateUtils.isClass(fist,five,DateUtils.dateTime(courseChange.getBeSubjectTime()),format)) {
                if(StringUtils.equals(courseChange.getWeek(),table.getWeek())){
                    classNum.add(Long.valueOf(courseChange.getBeIsNum()));
                    //第几节课
                    if(StringUtils.equals("1",courseChange.getBeIsNum())){
                        table.setOneClass(courseChange.getSubject());
                        table.setOneTeacher(courseChange.getApplyName());
                    }else if(StringUtils.equals("2",courseChange.getBeIsNum())){
                        table.setTwoClass(courseChange.getSubject());
                        table.setTwoTeacher(courseChange.getApplyName());
                    }else if(StringUtils.equals("3",courseChange.getBeIsNum())){
                        table.setThreeClass(courseChange.getSubject());
                        table.setThreeTeacher(courseChange.getApplyName());
                    }else if(StringUtils.equals("4",courseChange.getBeIsNum())){
                        table.setFourClass(courseChange.getSubject());
                        table.setFourTeacher(courseChange.getApplyName());
                    }else if(StringUtils.equals("5",courseChange.getBeIsNum())){
                        table.setFiveClass(courseChange.getSubject());
                        table.setFiveTeacher(courseChange.getApplyName());
                    }else if(StringUtils.equals("6",courseChange.getBeIsNum())){
                        table.setSixClass(courseChange.getSubject());
                        table.setSixTeacher(courseChange.getApplyName());
                    }else if(StringUtils.equals("7",courseChange.getBeIsNum())){
                        table.setSevenClass(courseChange.getSubject());
                        table.setSevenTeacher(courseChange.getApplyName());
                    }else if(StringUtils.equals("8",courseChange.getBeIsNum())){
                        table.setEightClass(courseChange.getSubject());
                        table.setEightTeacher(courseChange.getApplyName());
                    }
                }
            }
        }
        table.setClassNum(classNum);
    }



    /**
     * 查询课程列表
     */
    @Override
    public List<CourseTableVo> queryList(CourseTableBo bo) {
        LambdaQueryWrapper<CourseTable> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<CourseTable> buildQueryWrapper(CourseTableBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<CourseTable> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getSchoolId()), CourseTable::getSchoolId, bo.getSchoolId());
        lqw.like(StringUtils.isNotBlank(bo.getSchoolName()), CourseTable::getSchoolName, bo.getSchoolName());
        lqw.eq(StringUtils.isNotBlank(bo.getClassId()), CourseTable::getClassId, bo.getClassId());
        lqw.like(StringUtils.isNotBlank(bo.getClassName()), CourseTable::getClassName, bo.getClassName());
        lqw.eq(StringUtils.isNotBlank(bo.getWeek()), CourseTable::getWeek, bo.getWeek());
        lqw.eq(StringUtils.isNotBlank(bo.getOneClass()), CourseTable::getOneClass, bo.getOneClass());
        lqw.eq(StringUtils.isNotBlank(bo.getOneTeacher()), CourseTable::getOneTeacher, bo.getOneTeacher());
        lqw.eq(StringUtils.isNotBlank(bo.getTwoClass()), CourseTable::getTwoClass, bo.getTwoClass());
        lqw.eq(StringUtils.isNotBlank(bo.getTwoTeacher()), CourseTable::getTwoTeacher, bo.getTwoTeacher());
        lqw.eq(StringUtils.isNotBlank(bo.getThreeClass()), CourseTable::getThreeClass, bo.getThreeClass());
        lqw.eq(StringUtils.isNotBlank(bo.getThreeTeacher()), CourseTable::getThreeTeacher, bo.getThreeTeacher());
        lqw.eq(StringUtils.isNotBlank(bo.getFourClass()), CourseTable::getFourClass, bo.getFourClass());
        lqw.eq(StringUtils.isNotBlank(bo.getFourTeacher()), CourseTable::getFourTeacher, bo.getFourTeacher());
        lqw.eq(StringUtils.isNotBlank(bo.getFiveClass()), CourseTable::getFiveClass, bo.getFiveClass());
        lqw.eq(StringUtils.isNotBlank(bo.getFiveTeacher()), CourseTable::getFiveTeacher, bo.getFiveTeacher());
        lqw.eq(StringUtils.isNotBlank(bo.getSixClass()), CourseTable::getSixClass, bo.getSixClass());
        lqw.eq(StringUtils.isNotBlank(bo.getSixTeacher()), CourseTable::getSixTeacher, bo.getSixTeacher());
        lqw.eq(StringUtils.isNotBlank(bo.getSevenClass()), CourseTable::getSevenClass, bo.getSevenClass());
        lqw.eq(StringUtils.isNotBlank(bo.getSevenTeacher()), CourseTable::getSevenTeacher, bo.getSevenTeacher());
        lqw.eq(StringUtils.isNotBlank(bo.getEightClass()), CourseTable::getEightClass, bo.getEightClass());
        lqw.eq(StringUtils.isNotBlank(bo.getEightTeacher()), CourseTable::getEightTeacher, bo.getEightTeacher());
        return lqw;
    }

    /**
     * 新增课程
     */
    @Override
    public R<Void> insertByBo(CourseTableBo bo) {

        CourseTableBo table = new CourseTableBo();
        table.setSchoolId(bo.getSchoolId());
        table.setClassId(bo.getClassId());
        table.setWeek(bo.getWeek());
        LambdaQueryWrapper<CourseTable> lqw = buildQueryWrapper(table);
        List<CourseTableVo> courseTableList = baseMapper.selectVoList(lqw);
        if(courseTableList!=null && courseTableList.size()>0){
            return R.fail("当前课表已存在，请前去修改");
        }
        bo.setCreateTime(DateUtils.getNowDate());
        CourseTable add = MapstructUtils.convert(bo, CourseTable.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
            return R.ok();
        }
        return R.fail();
    }

    /**
     * 修改课程
     */
    @Override
    public Boolean updateByBo(CourseTableBo bo) {
        bo.setUpdateTime(DateUtils.getNowDate());
        CourseTable update = MapstructUtils.convert(bo, CourseTable.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(CourseTable entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除课程
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @SneakyThrows
    @Override
    public R<Map<String, Object>> now(Long schoolId, Long classId) {
        //SysUser user = SecurityUtils.getLoginUser().getUser();
        Map<String, Object> map = new HashMap<>();
        map.put("teacher", "");
        map.put("subject", "");
        //家长端查询下课时间
        String key =DateUtils.getDate() + ":" + schoolId + ":" + classId;
        //key = 学校id:班级id
        //Redis根据key键，查询对应的值
        String xiakeTime = "";
        String value = RedisUtils.getCacheObject(key);
        if (StringUtils.isNotEmpty(value)) {
            //延迟放学
            String[] split = value.split(":");
            if(!"time".equals(split[1])){
                //下课时间
                xiakeTime = split[1] + ":" + split[2] + ":" + split[3];
            }

        }
        map.put("time", xiakeTime);
        //获取当前时间
        String nowTime = DateUtils.getTime();
        //判断当天是周几
        int dayForWeek = DateUtils.dayForWeek(nowTime);
        if (dayForWeek == 6 || dayForWeek == 7) {
            return R.ok(map);
        }
        //获取当前账号所属学校时间表
        CourseTableTimeVo courseTableTime = courseTableTimeMapper.selectCourseTableTimeBySchoolId(schoolId);
        if (courseTableTime == null) {
            return R.ok(map);
        }
        //判断当前时间是第几节课
        int index = isClass(courseTableTime);
        if (index == 0) {
            return R.ok(map);
        }
        //获取当前班级课程
        CourseTableVo courseTable = baseMapper.selectCourseTableByClassIdAndWeek(classId, dayForWeek);
        if (courseTable == null) {
            return R.ok(map);
        }
        if (index == 1) {
            map.put("teacher", courseTable.getOneTeacher());
            map.put("subject", courseTable.getOneClass());
        } else if (index == 2) {
            map.put("teacher", courseTable.getTwoTeacher());
            map.put("subject", courseTable.getTwoClass());
        } else if (index == 3) {
            map.put("teacher", courseTable.getThreeTeacher());
            map.put("subject", courseTable.getThreeClass());
        } else if (index == 4) {
            map.put("teacher", courseTable.getFourTeacher());
            map.put("subject", courseTable.getFourClass());
        } else if (index == 5) {
            map.put("teacher", courseTable.getFiveTeacher());
            map.put("subject", courseTable.getFiveClass());
        } else if (index == 6) {
            map.put("teacher", courseTable.getSixTeacher());
            map.put("subject", courseTable.getSixClass());
        } else if (index == 7) {
            map.put("teacher", courseTable.getSevenTeacher());
            map.put("subject", courseTable.getSevenClass());
        } else if (index == 8) {
            map.put("teacher", courseTable.getEightTeacher());
            map.put("subject", courseTable.getEightClass());
        }

        return R.ok(map);
    }


    @SneakyThrows
    private int isClass(CourseTableTimeVo courseTableTime) {
        //获取当前时间
        String nowTime = DateUtils.getNowTime();
        int index = 0;
        if (StringUtils.isNotEmpty(courseTableTime.getOneStartTime()) && DateUtils.isClass(courseTableTime.getOneStartTime(), courseTableTime.getOneEndTime(), nowTime, "HH:mm")) {
            index = 1;
        } else if (StringUtils.isNotEmpty(courseTableTime.getTwoStartTime()) && DateUtils.isClass(courseTableTime.getTwoStartTime(), courseTableTime.getTwoEndTime(), nowTime, "HH:mm")) {
            index = 2;
        } else if (StringUtils.isNotEmpty(courseTableTime.getThreeStartTime()) && DateUtils.isClass(courseTableTime.getThreeStartTime(), courseTableTime.getThreeEndTime(), nowTime, "HH:mm")) {
            index = 3;
        } else if (StringUtils.isNotEmpty(courseTableTime.getFourStartTime()) && DateUtils.isClass(courseTableTime.getFourStartTime(), courseTableTime.getFourEndTime(), nowTime, "HH:mm")) {
            index = 4;
        } else if (StringUtils.isNotEmpty(courseTableTime.getFiveStartTime()) && DateUtils.isClass(courseTableTime.getFiveStartTime(), courseTableTime.getFiveEndTime(), nowTime, "HH:mm")) {
            index = 5;
        } else if (StringUtils.isNotEmpty(courseTableTime.getSixStartTime()) && DateUtils.isClass(courseTableTime.getSixStartTime(), courseTableTime.getSixEndTime(), nowTime, "HH:mm")) {
            index = 6;
        } else if (StringUtils.isNotEmpty(courseTableTime.getSevenStartTime()) && DateUtils.isClass(courseTableTime.getSevenStartTime(), courseTableTime.getSevenEndTime(), nowTime, "HH:mm")) {
            index = 7;
        } else if (StringUtils.isNotEmpty(courseTableTime.getEightStartTime()) && DateUtils.isClass(courseTableTime.getEightStartTime(), courseTableTime.getEightEndTime(), nowTime, "HH:mm")) {
            index = 8;
        }
        return index;
    }
}
