package com.xhkjedu.sapi.service.system;

import com.xhkjedu.sapi.mapper.gradeclass.*;
import com.xhkjedu.sapi.mapper.system.*;
import com.xhkjedu.sapi.model.gradeclass.*;
import com.xhkjedu.sapi.model.system.*;
import com.xhkjedu.sapi.utils.ApiUtil;
import com.xhkjedu.sapi.vo.analyze.SchoolParams;
import com.xhkjedu.utils.MD5;
import com.xhkjedu.utils.N_Utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

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

/**
 * @author ywx
 * @classname TSchoolService
 * @description 
 * @date 2020/6/2 15:07
 **/
@Service
@Slf4j
public class SchoolService {
    @Resource
    private SchoolMapper schoolMapper;
    @Resource
    private ModuledefaultService moduledefaultService;
    @Resource
    private ModuleService moduleService;
    @Resource
    private ClassMapper classMapper;
    @Resource
    private ClassStudentMapper classStudentMapper;
    @Resource
    private ClassTeacherMapper classTeacherMapper;
    @Resource
    private GroupMapper groupMapper;
    @Resource
    private GroupStudentMapper groupStudentMapper;
    @Resource
    private UserMapper userMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private RoleModuleMapper roleModuleMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Resource
    private SchoolFriendMapper schoolFriendMapper;

    //添加
    @Transactional(rollbackFor = Exception.class)
    public Integer save(TSchool model) throws Exception {
        //添加学校信息
        model.setSchoolstate(1);
        model.setCreatetime(N_Utils.getSecondTimestamp());
        Integer schoolid = null;
        try {
            schoolMapper.insertUseGeneratedKeys(model);
            schoolid = model.getId();

            //添加管理员信息
            Integer userid = saveUser(model, schoolid);

            //添加角色信息
            Integer roleid = saveRole(schoolid, userid);

            //添加用户角色
            saveUserRole(userid, roleid);

            //添加模块信息
            List<TRoleModule> roleModules = new ArrayList<>();
            List<TModule> moduleList = new ArrayList<>();
            List<TModule> modules = moduledefaultService.listModulesTree(null, null);//给学校网页复制模块
            for (TModule module : modules) {
                saveModuleSetRoleModule(schoolid, userid, roleid, roleModules, moduleList, module);
            }
            moduleService.batchSave(moduleList);//批量保存模块信息

            //添加角色模块
            roleModuleMapper.insertList(roleModules);
        } catch (DuplicateKeyException e) {
            log.error("添加学校失败",e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new Exception("该管理员账号已存在");
        } catch (Exception e) {
            log.error("添加学校失败",e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new Exception("添加学校失败");
        }

        return schoolid;
    }

    /**
     * 添加用户角色
     * @Param [userid, roleid]
     * @Author ywx
     * @Date 2020/7/2 11:52
     * @return java.lang.Integer
     **/
    private Integer saveUserRole(Integer userid, Integer roleid) {
        TUserRole userRole = new TUserRole();
        userRole.setUserid(userid);
        userRole.setRoleid(roleid);
        userRole.setCreateid(userid);
        userRole.setCreatetime(N_Utils.getSecondTimestamp());
        userRoleMapper.insertUseGeneratedKeys(userRole);
        return userRole.getId();
    }

    /**
     * 添加角色信息
     * @Param [schoolid, userid]
     * @Author ywx
     * @Date 2020/7/2 11:51
     * @return java.lang.Integer
     **/
    private Integer saveRole(Integer schoolid, Integer userid) {
        TRole role = new TRole();
        role.setRolename("管理员");
        role.setComm("拥有高权限");
        role.setCreateid(userid);
        role.setCreatetime(N_Utils.getSecondTimestamp());
        role.setSchoolid(schoolid);
        roleMapper.insertUseGeneratedKeys(role);
        return role.getId();
    }

    /**
     * 添加管理员信息
     * @Param [model, schoolid]
     * @Author ywx
     * @Date 2020/7/2 11:49
     * @return java.lang.Integer
     **/
    private Integer saveUser(TSchool model, Integer schoolid) {
        TUser user = new TUser();
        user.setLoginname(model.getLoginname());
        user.setUsername("管理员");
        user.setUsersex(1);
        MD5 m = new MD5();
        String loginpwd = m.getMD5ofStr(m.getMD5ofStr(m.getMD5ofStr("123456")));
        user.setLoginpwd(loginpwd);
        user.setUsertype(0);
        user.setUserstate(1);
        user.setCreateid(model.getCreateid());
        user.setCreatetime(N_Utils.getSecondTimestamp());
        user.setSchoolid(schoolid);
        userMapper.insertUseGeneratedKeys(user);
        return user.getId();
    }

    /**
     * 保存子模块信息并设置角色模块信息
     *
     * @return void
     * @Param [schoolid, userid, roleid, roleModules, module]
     * @Author ywx
     * @Date 2020/7/2 11:47
     **/
    private void saveModuleSetRoleModule(Integer schoolid, Integer userid, Integer roleid, List<TRoleModule> roleModules, List<TModule> moduleList, TModule module) {
        module.setCreateid(userid);
        module.setCreatetime(N_Utils.getSecondTimestamp());
        module.setSchoolid(schoolid);
        module.setDefaultid(module.getModuleid());
        String moduleid = ApiUtil.getId();
        module.setModuleid(moduleid);
        moduleList.add(module);
        saveModuleChild(schoolid, userid, module, roleModules, moduleList, roleid);

        if (module.getModuletype() == 1) {
            //角色模块信息
            TRoleModule roleModule = new TRoleModule();
            roleModule.setRoleid(roleid);
            roleModule.setModuleid(moduleid);
            roleModule.setCreateid(userid);
            roleModule.setCreatetime(N_Utils.getSecondTimestamp());
            roleModule.setSchoolid(schoolid);
            roleModules.add(roleModule);
        }
    }

    /**
     * 保存子模块信息
     *
     * @return void
     * @Param [schoolid, userid, module, roleModules, roleid]
     * @Author ywx
     * @Date 2020/7/2 11:46
     **/
    private void saveModuleChild(Integer schoolid, Integer userid, TModule module, List<TRoleModule> roleModules, List<TModule> moduleList, Integer roleid) {
        String moduleid = module.getModuleid();
        List<TModule> modulechilds = module.getModulechilds();
        if (N_Utils.isListNotEmpty(modulechilds)) {
            for (TModule modulechild : modulechilds) {
                modulechild.setModulepid(moduleid);
                saveModuleSetRoleModule(schoolid, userid, roleid, roleModules, moduleList, modulechild);
            }
        }
    }

    //删除
    public Integer deleteById(Integer schoolid) {
        //删除系统学校
        return schoolMapper.deleteById(schoolid);
    }

    //修改
    @Transactional(rollbackFor = Exception.class)
    public Integer update(TSchool model) {
        Integer bindmac = model.getBindmac();
        TSchool school = finById(model.getSchoolid());
        if (bindmac != null && !bindmac.equals(school.getBindmac())) {
            userMapper.delBindmac(model.getSchoolid());//删除学生绑定信息
        }
        return schoolMapper.updateById(model);
    }

    //获取列表
    public List <Map> findAll() {
        return schoolMapper.findAll();
    }

    /**
     * 学年升级
     * @Param [schoolid, year]
     * @Author ywx
     * @Date 2020/6/12 13:50
     * @return void
     **/
    @Transactional(rollbackFor = Exception.class)
    public void upgrade(Integer schoolid, Integer year) throws Exception {
        try {
            List<TClass> classes = classMapper.listClassBySchoolId(schoolid, year);//要升级的班级列表
            if (N_Utils.isListNotEmpty(classes)) {
                String classIds = classMapper.listClassIdBySchoolId(schoolid, year);
                List<TClassStudent> cStudents = classMapper.listStudentByClassIds(classIds);//要升级的学生列表
                List<TClassTeacher> cTeachers = classMapper.listTeacherByClassIds(classIds);//要升级的教师列表

                List<TGroup> groups = classMapper.listGroupByClassIds(classIds);//要升级的全体分组列表
                StringBuilder sb = new StringBuilder();
                groups.forEach(g -> {
                    sb.append(g.getGroupid()).append(",");
                });
                String groupIds = sb.toString().substring(0, sb.toString().length() - 1);
                List<TGroupStudent> gStudents = classMapper.listStudentByGroupIds(groupIds);//要升级的学生列表

                List<TClassStudent> classStudents = new ArrayList<>();//升级后的班级学生
                List<TClassTeacher> classTeachers = new ArrayList<>();//升级后的班级教师
                List<TGroupStudent> groupStudents = new ArrayList<>();//升级后的分组学生
                for (TClass c : classes) {
                    //复制班级信息
                    c.setYear(c.getYear() + 1);
                    c.setGradeid(c.getGradeid() + 1);
                    c.setClassstate(1);
                    c.setCreatetime(N_Utils.getSecondTimestamp());
                }
                classMapper.insertList(classes);//保存升级后的班级信息
                for (TClass c : classes) {
                    //复制班级信息
                    Integer oldClassId = c.getClassid();
                    Integer classid = c.getId();

                    //复制班级学生信息
                    boolean rtn = false;
                    for (TClassStudent s : cStudents) {
                        if (oldClassId.equals(s.getClassid())) {
                            s.setClassid(classid);
                            s.setCreatetime(N_Utils.getSecondTimestamp());
                            classStudents.add(s);
                            rtn = true;
                        } else if (!oldClassId.equals(s.getClassid()) && rtn) {
                            break;
                        }
                    }

                    //复制班级教师信息
                    rtn = false;
                    for (TClassTeacher t : cTeachers) {
                        if (oldClassId.equals(t.getClassid())){
                            t.setClassid(classid);
                            t.setCreatetime(N_Utils.getSecondTimestamp());
                            classTeachers.add(t);
                            rtn = true;
                        } else if (!oldClassId.equals(t.getClassid()) && rtn){
                            break;
                        }
                    }

                    for (TGroup g : groups) {
                        if (oldClassId.equals(g.getClassid())) {
                            //复制班级分组信息
                            g.setClassid(classid);
                            g.setCreatetime(N_Utils.getSecondTimestamp());
                            break;
                        }
                    }
                }
                groupMapper.insertList(groups);//保存升级后的班级分组信息
                for (TGroup g : groups) {
                    Integer classid = g.getClassid();
                    Integer oldGroupId = g.getGroupid();
                    Integer groupid = g.getId();
                    //复制分组学生信息
                    boolean rtn = false;
                    for (TGroupStudent s : gStudents) {
                        if (oldGroupId.equals(s.getGroupid())) {
                            s.setClassid(classid);
                            s.setGroupid(groupid);
                            s.setCreatetime(N_Utils.getSecondTimestamp());
                            groupStudents.add(s);
                            rtn = true;
                        } else if (!oldGroupId.equals(s.getGroupid()) && rtn) {
                            break;
                        }
                    }
                }
                classStudentMapper.insertList(classStudents);//保存升级后的班级学生信息
                classTeacherMapper.insertList(classTeachers);//保存升级后的班级教师信息
                groupStudentMapper.insertList(groupStudents);//保存升级后的分组学生信息
            }

            //不需要升级，需要标识毕业的班级，学生
            List<TClass> biyeclass = classMapper.listClassBiyeBySchoolId(schoolid,year,1);


            if(N_Utils.isListNotEmpty(biyeclass)){
                String byclassIds = "";
                for(int i=0;i<biyeclass.size();i++){
                    TClass c = biyeclass.get(i);
                    if(i>0){
                        byclassIds = byclassIds + "," + c.getClassid();
                    }else{
                        byclassIds = c.getClassid().toString();
                    }
                }

                List<TClassStudent> bystudents = classMapper.listStudentByClassIds(byclassIds);//要毕业的学生列表

                if (N_Utils.isNotEmpty(byclassIds)) {
                    classMapper.updateClassState(3, byclassIds);//修改班级状态
                }
                if (N_Utils.isListNotEmpty(bystudents)) {
                    userMapper.batchUpdateState(bystudents, 3);   //修改学生状态为已毕业状态
                }
            }

            schoolMapper.upgrade(schoolid);//学校年份升级
        }catch (Exception e){
            log.error("学年升级失败：" + e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new Exception("学年升级失败");
        }
    }

    /**
     * 学年降级
     * @Param [schoolid, year]
     * @Author ywx
     * @Date 2020/6/16 13:51
     * @return void
     **/
    public void downgrade(Integer schoolid, Integer year) {

        schoolMapper.downgrade(schoolid, year);
        //之前已毕业的班级进行恢复
        List<TClass> biyeclass = classMapper.listClassBiyeBySchoolId(schoolid,year,3);

        if(N_Utils.isListNotEmpty(biyeclass)){
            String byclassIds = "";
            for(int i=0;i<biyeclass.size();i++){
                TClass c = biyeclass.get(i);
                if(i>0){
                    byclassIds = "," + c.getClassid();
                }else{
                    byclassIds = c.getClassid().toString();
                }
            }

            List<TClassStudent> bystudents = classMapper.listStudentByClassIds(byclassIds);//要毕业的学生列表

            classMapper.updateClassState(1,byclassIds);//修改班级状态
            userMapper.batchUpdateState(bystudents,1);   //修改学生状态
        }
    }

    /**
     * 获取学校详情
     * @Param [schoolid]
     * @Author ywx
     * @Date 2020/9/21 16:12
     * @return com.xhkjedu.model.gradeclass.TSchool
     **/
    public TSchool finById(Integer schoolid) {
        return schoolMapper.selectByPrimaryKey(schoolid);
    }

    //学校选择列表
    public List<Map> listForSel(String schoolname) {
        return schoolMapper.listForSel(schoolname);
    }

    //根据学校名称查找学校数量
    public Integer countBySchoolName(String schoolname) {
        return schoolMapper.countBySchoolName(schoolname);
    }

    //获取学校当前年份
    public Integer getYearById(Integer schoolid) {
        return schoolMapper.getYearById(schoolid);
    }

    //获取准考证号长度限制
    public Integer getLimiteNoLen(Integer schoolid) {
        return schoolMapper.getLimiteNoLen(schoolid);
    }

    //保存学校关联附属学校
    @Transactional(rollbackFor = Exception.class)
    public void saveSchoolFriend(SchoolParams params){
        //先移除学校关联学校
        schoolFriendMapper.deleteBySchoolid(params.getSchoolid());

        List<TSchoolFriend> schoolfriends = new ArrayList<>();
        List<Integer> schoolids  = params.getSchoolids();
        int timestemp = N_Utils.getSecondTimestamp();
        for(Integer shid : schoolids){
            if(!params.getSchoolid().equals(shid)){
                TSchoolFriend sf = new TSchoolFriend();
                sf.setSchoolid(params.getSchoolid());
                sf.setFschoolid(shid);
                sf.setCreateid(params.getCreateid());
                sf.setCreatetime(timestemp);
                schoolfriends.add(sf);
            }
        }
        if(N_Utils.isListNotEmpty(schoolfriends)){
            schoolFriendMapper.insertList(schoolfriends);
        }
    }

    //获取学校附属学校
    public List<Map> listFSchoolidsBySchoolid(Integer schoolid){
        return schoolFriendMapper.listFSchoolidsBySchoolid(schoolid);
    }

    //获取学校及附属学校班级
    public List<Map> listSchoolAndFriendSchools(Integer schoolid){
        List<Map> rtnlist = new ArrayList<>();
        List<Map> schools = schoolFriendMapper.listSchoolClass(schoolid);
        setSchoolGradeSclass(rtnlist,schools);
        List<Map> fschools = schoolFriendMapper.listFriendSchoolClass(schoolid);
        setFriendSchoolGradeSclass(rtnlist,fschools);
        return rtnlist;
    }

    private void setSchoolGradeSclass(List<Map> rtnlist,List<Map> schools){
        //处理学校
        Map schoolsmap = schools.get(0);
        Map schoolm = new LinkedHashMap();
        schoolm.put("schoolid",Integer.parseInt(schoolsmap.get("schoolid").toString()));
        schoolm.put("schoolname",schoolsmap.get("schoolname").toString());

        List<Map> gradelist = new ArrayList<>();
        //根据年级进行分组
        Map<String,List<Map>> grademap =  schools.stream().collect(Collectors.groupingBy(s -> s.get("gradeid").toString(), Collectors.toList()));
        for(Map.Entry<String, List<Map>> entry : grademap.entrySet()){
            Map gmap = new LinkedHashMap();
            gmap.put("gradeid",Integer.parseInt(entry.getKey()));
            List<Map> classlist = entry.getValue();
            for(Map cmap : classlist){
                cmap.remove("schoolid");
                cmap.remove("schoolname");
                cmap.remove("gradeid");
            }
            gmap.put("classes",classlist);
            gradelist.add(gmap);
        }
        schoolm.put("grades",gradelist);
        rtnlist.add(schoolm);
    }

    private void setFriendSchoolGradeSclass(List<Map> rtnlist,List<Map> schools){
        Map<String,List<Map>> schoolmap =  schools.stream().collect(Collectors.groupingBy(s -> s.get("schoolid").toString(), Collectors.toList()));
        for(Map.Entry<String, List<Map>> entry : schoolmap.entrySet()){
            Map schoolm = new LinkedHashMap();
            schoolm.put("schoolid",Integer.parseInt(entry.getKey()));
            Map schoolm2 = entry.getValue().get(0);
            schoolm.put("schoolname",schoolm2.get("schoolname").toString());
            List<Map> gradelist = entry.getValue();
            List<Map> savegradelist = new ArrayList<>();
            //根据年级进行分组
            Map<String,List<Map>> grademap =  gradelist.stream().collect(Collectors.groupingBy(s -> s.get("gradeid").toString(), Collectors.toList()));
            for(Map.Entry<String, List<Map>> entryg : grademap.entrySet()){
                Map gmap = new LinkedHashMap();
                gmap.put("gradeid",Integer.parseInt(entryg.getKey()));
                List<Map> classlist = entryg.getValue();
                for(Map cmap : classlist){
                    cmap.remove("schoolid");
                    cmap.remove("schoolname");
                    cmap.remove("gradeid");
                }
                gmap.put("classes",classlist);
                savegradelist.add(gmap);
            }
            schoolm.put("grades",savegradelist);

            rtnlist.add(schoolm);
        }
    }

    //获取学年列表
    public List<Integer> listYear(Integer schoolid) {
        return schoolMapper.listYear(schoolid);
    }
}
