package com.xhkjedu.suser.service.system;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xhkjedu.suser.config.ConfigKey;
import com.xhkjedu.suser.mapper.gradeclass.ClassMapper;
import com.xhkjedu.suser.mapper.gradeclass.ClassTeacherMapper;
import com.xhkjedu.suser.mapper.gradeclass.SchoolMapper;
import com.xhkjedu.suser.mapper.system.MsgMapper;
import com.xhkjedu.suser.mapper.system.UserComponentMapper;
import com.xhkjedu.suser.mapper.system.UserMapper;
import com.xhkjedu.suser.mapper.system.UserUsecretMapper;
import com.xhkjedu.suser.model.gradeclass.TClassTeacher;
import com.xhkjedu.suser.model.system.TMsg;
import com.xhkjedu.suser.model.system.TUser;
import com.xhkjedu.suser.model.system.TUserComponent;
import com.xhkjedu.suser.model.system.TUserUsecret;
import com.xhkjedu.suser.utils.PoiUtils;
import com.xhkjedu.suser.utils.SMSSender;
import com.xhkjedu.suser.utils.UserUtil;
import com.xhkjedu.suser.vo.assess.AssessParams;
import com.xhkjedu.suser.vo.system.ZtMsgVo;
import com.xhkjedu.utils.*;
import com.xhkjedu.vo.PageResult;
import com.xhkjedu.vo.ResultVo;
import com.xhkjedu.vo.system.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

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

/**
 * @ClassName UserService
 * Description
 * Author WN
 * Date 2020/5/29 16:31
 **/
@Service
@Slf4j
public class UserService extends JedisUtil {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserLogService userLogService;
    @Resource
    private MsgMapper msgMapper;
    @Resource
    private SchoolMapper schoolMapper;
    @Resource
    private ClassMapper classMapper;
    @Autowired
    private ClassTeacherMapper classTeacherMapper;
    @Resource
    private UserUsecretMapper userUsecretMapper;
    @Resource
    private UserComponentMapper userComponentMapper;

    /**
     * 添加用户信息
     *
     * @return com.xhkjedu.vo.ResultVo
     * @Param [user]
     * @Author ywx
     * @Date 2020/6/2 9:45
     **/
    @Transactional(rollbackFor = Exception.class)
    public ResultVo save(TUser user) {
        Integer schoolid = user.getSchoolid();
        Integer usernum = schoolMapper.getUserNumById(schoolid);
        if (usernum != null) {
            Integer usernum2 = userMapper.getUserNumBySchoolId(schoolid);
            usernum2 = usernum2 + 1;//学校账号数量+本次添加的人
            if (usernum.compareTo(usernum2) == -1) {
                return new ResultVo(1, "账号数量已超限，请联系管理员");
            }
        }
        user.setUserstate(1);
        user.setCreatetime(N_Utils.getSecondTimestamp());
        setLoginPwd(user);
        Integer bindphoned = 0;
        String userphone = user.getUserphone();
        if (N_Utils.isNotEmpty(userphone)) {
            //获取手机号绑定的其他用户数量
            Integer num = userMapper.getNumByUserPhone(0, userphone);
            if (num != 0) {//手机号被其他账号绑定，不保存返回提示信息
                return new ResultVo(1, "手机号【" + userphone + "】已被绑定");
            } else {//手机号未被其他账号绑定，设置已绑定手机号
                bindphoned = 1;
            }
        }
        user.setBindphoned(bindphoned);
        if (DatesUtil.dateNan(user.getUsertime())) {//有效期异常值置空
            user.setUsertime(null);
        }
        user.setBindsecret(0);
        user.setUserlock(0);
        user.setBindmac(0);
        user.setErrornum(0);
        user.setLoginname(N_Utils.strTrim(user.getLoginname()));
        userMapper.insertUseGeneratedKeys(user);
        Integer userid = user.getId();
        if(user.getUsertype() == 1){
            List<TUserComponent> initComponents = UserUtil.listInitComponents();
            List<TUserComponent> saveComponents = new ArrayList<>();
            Integer timestamp = N_Utils.getSecondTimestamp();
            for (TUserComponent userComponent : initComponents) {
                TUserComponent sc = new TUserComponent();
                sc.setUserid(userid);
                sc.setCcode(userComponent.getCcode());
                sc.setCwidth(userComponent.getCwidth());
                sc.setCheight(userComponent.getCheight());
                sc.setCorder(userComponent.getCorder());
                sc.setCreatetime(timestamp);
                saveComponents.add(sc);
            }
            userComponentMapper.insertList(saveComponents);
        }

        return new ResultVo(0, "保存成功", userid);
    }

    /**
     * 修改用户信息
     *
     * @return com.xhkjedu.vo.ResultVo
     * @Param [user]
     * @Author ywx
     * @Date 2020/6/2 9:51
     **/
    public ResultVo update(TUser user) {
        if (N_Utils.isNotEmpty(user.getLoginpwd())) {
            setLoginPwd(user);
        }

        String loginname = user.getLoginname();
        if (N_Utils.isNotEmpty(loginname)) {
            loginname = N_Utils.strTrim(loginname);
            TUser user1 = getObjByLoginName(loginname);
            //登录账号改变并且和别的账号冲突
            if (user1 != null && !user1.getUserid().equals(user.getUserid())) {
                return new ResultVo(1, "此账号已存在，请更换！");
            }
        }
        Integer bindphoned = 0;
        String userphone = user.getUserphone();
        if (N_Utils.isEmpty(userphone) || userphone.contains("****")) {//手机号为空或带星号不修改手机号和是否绑定手机号
            bindphoned = null;
            user.setUserphone(null);
        } else if (N_Utils.isNotEmpty(userphone)) {
            //获取手机号绑定的其他用户数量
            Integer num = userMapper.getNumByUserPhone(user.getUserid(), userphone);
            if (num != 0) return new ResultVo(1, "此手机号已被绑定");
            bindphoned = 1;
        }
        user.setBindphoned(bindphoned);
        if (DatesUtil.dateNan(user.getUsertime())) {//有效期异常值置空
            user.setUsertime(null);
        }
        user.setCreatetime(N_Utils.getSecondTimestamp());
        userMapper.updateByPrimaryKeySelective(user);
        return new ResultVo(0, "修改成功");
    }

    private void setLoginPwd(TUser user) {
        MD5 m = new MD5();
        String loginpwd = m.getMD5ofStr(m.getMD5ofStr(m.getMD5ofStr(user.getLoginpwd())));
        user.setLoginpwd(loginpwd);
    }

    /**
     * 删除用户
     *
     * @return com.xhkjedu.vo.ResultVo
     * @Param [user]
     * @Author ywx
     * @Date 2020/6/2 9:59
     **/
    public ResultVo deleteById(TUser user) {
        user.setDeletetime(N_Utils.getSecondTimestamp());
        userMapper.deleteById(user);
        return new ResultVo(0, "删除成功");
    }

    /**
     * 获取用户列表
     *
     * @return com.xhkjedu.vo.ResultVo
     * @Param [user]
     * @Author ywx
     * @Date 2020/6/2 10:06
     **/
    public ResultVo findAll(TUser user) {
        PageHelper.startPage(user.getPage(), user.getPageSize());
        List<UserVo> list = userMapper.findAll(user);
        PageResult pageResult = PageUtil.getPageResult(new PageInfo<>(list));
        return new ResultVo(0, "获取列表成功", pageResult);
    }

    /**
     * 获取用户详情
     *
     * @return com.xhkjedu.vo.ResultVo
     * @Param [userid]
     * @Author ywx
     * @Date 2020/6/2 10:23
     **/
    public ResultVo findById(Integer userid, String ultype) {
        UserVo userVo = userMapper.findById(userid);
        if (userVo.getUsertype() == 1) {
            String key = userVo.getCloudcode() + "_" + userid;
            if (N_Utils.isEmpty(ultype)) {
                ultype = "_live_pc_t";
            } else {
                ultype = "_" + ultype;
            }
            key += ultype;
            String token = get(key);
            if (N_Utils.isEmpty(token)) {
                String ticketKey = UUID.randomUUID().toString().replace("-", "");
                token = DESUtils.encrypt(ticketKey, ConfigKey.secretKey);//加密
                Boolean redis_rtn = set(key, token, ConfigKey.redisdatatime);
                if (!redis_rtn) {
                    return new ResultVo(1, "加入缓存出错!");
                }
            }
            userVo.setToken_key(key);
            userVo.setToken_value(token);
        }
        return new ResultVo(0, "获取详情成功", userVo);
    }

    /**
     * 修改用户密码
     *
     * @return com.xhkjedu.vo.ResultVo
     * @Param [user]
     * @Author ywx
     * @Date 2020/6/2 10:30
     **/
    public ResultVo updatePwd(TUser user) {
        ResultVo pwdResultVo = UserUtil.checkhLoginPwd(user.getLoginpwd());
        if (pwdResultVo.getCode() == 0) {
            UserVo userVo = userMapper.findById(user.getUserid());
            String oldpwd = this.md5pwd(user.getOldpwd());
            if (userVo.getLoginpwd().equals(oldpwd)) {
                setLoginPwd(user);
                userMapper.updatePwd(user);
                return new ResultVo(0, "修改成功");
            } else {
                return new ResultVo(1, "原密码错误");
            }
        } else {
            return pwdResultVo;
        }
    }

    /**
     * 修改用户头像
     *
     * @return com.xhkjedu.vo.ResultVo
     * @Param [user]
     * @Author ywx
     * @Date 2020/6/2 10:37
     **/
    public ResultVo updateHeadPic(TUser user) {
        user.setHeadtime(N_Utils.getSecondTimestamp());
        TUser vo = userMapper.getUserTypeAndHeadTime(user.getUserid(), user.getHeadtime());//获取用户类型和修改头像时间
        if (vo.getUsertype() == 2 && vo.getHeadtime() == 0) {
            return new ResultVo(1, "6个月内只能修改一次");
        }
        userMapper.updateHeadPic(user);
        return new ResultVo(0, "修改成功");
    }

    /**
     * 检查登录账号是否存在
     *
     * @return com.xhkjedu.vo.ResultVo
     * @Param [loginname]
     * @Author ywx
     * @Date 2020/6/2 10:44
     **/
    public ResultVo checkLoginName(String loginname) {
        Map num = userMapper.checkLoginName(loginname);
        if (num != null) {
            return new ResultVo(1, "此账号已存在，请更换", num);
        } else {
            return new ResultVo(0, "检查登录账号是否存在成功");
        }
    }

    /**
     * 根据登录账号获取用户详情
     *
     * @return com.xhkjedu.model.system.TUser
     * @Param [loginname]
     * @Author ywx
     * @Date 2020/6/3 9:33
     **/
    public TUser getObjByLoginName(String loginname) {
        return userMapper.getObjByLoginName(loginname);
    }

    /**
     * 批量添加
     *
     * @return void
     * @Param [users]
     * @Author ywx
     * @Date 2020/6/3 18:27
     **/
    public void batchSave(List<TUser> users) throws Exception {
        userMapper.insertList(users);
    }

    /**
     * 修改用户状态
     *
     * @return void
     * @Param [userid, userstate]
     * @Author ywx
     * @Date 2020/6/4 9:08
     **/
    public void updateState(Integer userid, int userstate) {
        userMapper.updateState(userid, userstate, N_Utils.getSecondTimestamp());
    }

    /**
     * 导入教师
     *
     * @return com.xhkjedu.vo.ResultVo
     * @Param [file, tUser]
     * @Author ywx
     * @Date 2020/6/5 8:47
     **/
    @Transactional(rollbackFor = Exception.class)
    public ResultVo importTeacher(MultipartFile file, TUser tUser) {
        Integer schoolid = tUser.getSchoolid();
        Integer createid = tUser.getCreateid();
        N_Utils.validation(new Object[]{schoolid, "学校id", 1, createid, "创建人id", 1});
        try {
            Map<Integer, Map<String, Integer>> gclasses = new HashMap<>();//年级下班级集合
            List<Map> classes = classMapper.listClass(schoolid, 1);
            Map<Integer, List<Map>> grades = classes.stream().collect(Collectors.groupingBy(c -> (Integer) c.get("gradeid")));
            for (Map.Entry<Integer, List<Map>> g : grades.entrySet()) {
                Map<String, Integer> cmap = new HashMap<>();
                List<Map> list = g.getValue();
                for (Map m : list) {
                    cmap.put(m.get("classname").toString(), (Integer) m.get("classid"));
                }
                gclasses.put(g.getKey(), cmap);
            }

            Map<String, Object> map = PoiUtils.readExcelTeacher(file, gclasses);
            List<TUser> teachers = (List<TUser>) map.get("users");
            Integer lnum = teachers.stream().distinct().map(TUser::getLoginname).collect(Collectors.toList()).size();
            Integer teachernum = teachers.size();
            if (teachernum.compareTo(lnum) != 0) {
                return new ResultVo(1, "有重复的登录名");
            }
            List<String> userphones = teachers.stream().filter(t -> N_Utils.isNotEmpty(t.getUserphone())).map(TUser::getUserphone).collect(Collectors.toList());
            Integer phonenum = userphones.stream().distinct().collect(Collectors.toList()).size();
            if (phonenum.compareTo(userphones.size()) != 0) {
                return new ResultVo(1, "有重复的手机号");
            }
            Integer usernum = schoolMapper.getUserNumById(schoolid);
            if (usernum != null) {
                Integer usernum2 = getUserNumBySchoolId(schoolid);
                usernum2 = usernum2 + teachernum;//学校账号数量+本次添加的人
                if (usernum.compareTo(usernum2) == -1) {
                    return new ResultVo(1, "账号数量已超限，请联系管理员");
                }
            }
            map.remove("users");//导入成功的教师信息不返回给前端
            Integer year = schoolMapper.getYearById(schoolid);

            List<TUser> teachersExisted = new ArrayList<>();//已存在教师列表
            List<TUser> studentsExisted = new ArrayList<>();//已存在学生列表
            List<TUser> usersExisted = new ArrayList<>();//已存在非本校账号列表
            List<TUser> delUsers = new ArrayList<>();//已删除教师列表

            List<Map> users = userMapper.listBindPhoneUser();//绑定手机号用户列表
            Map<String, String> phoneMap = new HashMap();
            for (Map user : users) {
                phoneMap.put(user.get("userphone").toString(), user.get("loginname").toString());
            }
            for (TUser user : teachers) {
                String loginname = user.getLoginname();
                String userphone = user.getUserphone();
                String phone = phoneMap.get(userphone);
                if (N_Utils.isNotEmpty(userphone) && N_Utils.isNotEmpty(phone) && !phone.equals(loginname)) {
                    //绑定的手机号和登录名不一致，则手机号被其他用户绑定
                    return new ResultVo(1, "手机号【" + userphone + "】已被绑定");
                }
            }
            List<Future> futureList = new ArrayList<>();//来记录任务的完成情况，完成线程间的通信
            for (TUser user : teachers) {
                String loginname = user.getLoginname();
                String userphone = user.getUserphone();
                Future<Boolean> future = importOneTeacher(schoolid, createid, year, teachersExisted
                        , studentsExisted, usersExisted, delUsers, user, loginname, userphone);
                futureList.add(future);
            }

            UserUtil.isAllDone(futureList);//线程是否执行完
            map.put("teachersExisted", teachersExisted);
            map.put("studentsExisted", studentsExisted);
            map.put("usersExisted", usersExisted);
            map.put("delUsers", delUsers);
            if (N_Utils.isListNotEmpty(teachersExisted) || N_Utils.isListNotEmpty(studentsExisted)
                    || N_Utils.isListNotEmpty(usersExisted) || N_Utils.isListNotEmpty(delUsers)) {
                map.put("code", 1);
            } else {
                map.put("code", 0);
            }
            return new ResultVo(0, "导入成功", map);
        } catch (Exception e) {
            log.error("导入失败 : " + e.getMessage());
            return new ResultVo(1, "导入失败 : " + e.getMessage());
        }
    }

    //单个教师导入
    @Async("asyncPoolTaskExecutor")
    public Future<Boolean> importOneTeacher(Integer schoolid, Integer createid, Integer year
            , List<TUser> teachersExisted, List<TUser> studentsExisted, List<TUser> usersExisted
            , List<TUser> delUsers, TUser user, String loginname, String userphone) {
        TUser u = getObjByLoginName(loginname);
        Integer userid = null;
        List<TClassTeacher> ctlst = new ArrayList<>();//班级教师集合
        if (null == u) {
            user.setSchoolid(schoolid);
            user.setCreateid(createid);
            user.setCreatetime(N_Utils.getSecondTimestamp());
            user.setUserstate(1);
            Integer bindphoned = 0;
            if (N_Utils.isNotEmpty(userphone)) {
                bindphoned = 1;
            }
            user.setBindphoned(bindphoned);
            setLoginPwd(user);
            user.setBindsecret(0);
            user.setUserlock(0);
            user.setErrornum(0);
            userMapper.insertUseGeneratedKeys(user);
            int timestamp = N_Utils.getSecondTimestamp();
            userid = user.getId();

            //初始化首页组件
            List<TUserComponent> initComponents = UserUtil.listInitComponents();
            List<TUserComponent> saveComponents = new ArrayList<>();
            for(TUserComponent userComponent : initComponents){
                TUserComponent sc = new TUserComponent();
                sc.setUserid(userid);
                sc.setCcode(userComponent.getCcode());
                sc.setCwidth(userComponent.getCwidth());
                sc.setCheight(userComponent.getCheight());
                sc.setCorder(userComponent.getCorder());
                sc.setCreatetime(timestamp);
                saveComponents.add(sc);
            }
            userComponentMapper.insertList(saveComponents);

            //处理用户班级
            Integer grageid = user.getGrageid();
            if (N_Utils.isEmptyInteger(grageid)) return new AsyncResult<>(true);
            List<Integer> classids = user.getClassids();
            if (N_Utils.isListEmpty(classids)) return new AsyncResult<>(true);


            for (Integer classid : classids) {
                TClassTeacher ct = new TClassTeacher();
                ct.setTeacherid(userid);
                ct.setClassid(classid);
                ct.setCreateid(createid);
                ct.setSchoolid(schoolid);
                ct.setCreatetime(timestamp);
                ctlst.add(ct);
            }

        } else {
            if (schoolid != u.getSchoolid()) {
                usersExisted.add(u);
                return new AsyncResult<>(true);
            } else if (1 != u.getUsertype()) {
                studentsExisted.add(u);
                return new AsyncResult<>(true);
            } else {
                if (u.getUserstate() != 1) {//本校已删除教师
                    delUsers.add(u);
                } else {//本校已存在教师
                    teachersExisted.add(u);
                }
                userid = u.getUserid();
                //teacherIds.add(userid);
                //处理用户班级
                Integer grageid = user.getGrageid();
                if (N_Utils.isEmptyInteger(grageid)) return new AsyncResult<>(true);
                List<Integer> classids = user.getClassids();
                if (N_Utils.isListEmpty(classids)) return new AsyncResult<>(true);

                int timestamp = N_Utils.getSecondTimestamp();
                for (Integer classid : classids) {
                    TClassTeacher ct = new TClassTeacher();
                    ct.setTeacherid(userid);
                    ct.setClassid(classid);
                    ct.setCreateid(createid);
                    ct.setSchoolid(schoolid);
                    ct.setCreatetime(timestamp);
                    ctlst.add(ct);
                }

                classTeacherMapper.deleteByUserid2(userid.toString(), year);//删除教师任教班级
            }
        }
        if (N_Utils.isListNotEmpty(ctlst)) classTeacherMapper.insertList(ctlst);//添加教师任教班级
        return new AsyncResult<>(true);
    }

    private String md5pwd(String pwd) {
        MD5 m = new MD5();
        String loginpwd = m.getMD5ofStr(m.getMD5ofStr(m.getMD5ofStr(pwd)));
        return loginpwd;
    }

    /**
     * 功能描述 修改操作密码
     *
     * @param * @param user
     * @return void
     * @author WN
     * @date 2020/6/17
     */
    public void updateOpepasswordByUserId(TUser user) {
        String pwd = md5pwd(user.getOpepassword());
        userMapper.updateOpepasswordByUserId(user.getUserid(), pwd);
    }

    /**
     * 功能描述 验证用户操作密码
     *
     * @param * @param user
     * @return java.lang.Integer
     * @author WN
     * @date 2020/6/17
     */
    public Integer getUserIdByOpepassword(TUser user) {
        String pwd = md5pwd(user.getOpepassword());
        return userMapper.getUserIdByOpepassword(user.getUserid(), pwd);
    }

    /**
     * 教师基本信息
     *
     * @return com.xhkjedu.suser.vo.system.TeacherVo
     * @Param [userid]
     * @Author ywx
     * @Date 2020/6/29 16:23
     **/
    public Map getTeacherInfo(Integer schoolid, Integer userid, Integer classtype) {
        Integer year = schoolMapper.getYearById(schoolid);
        return userMapper.getTeacherInfo(userid, classtype, year);
    }

    /**
     * 重置密码
     *
     * @return com.xhkjedu.vo.ResultVo
     * @Param [user]
     * @Author ywx
     * @Date 2020/7/30 14:25
     **/
    public ResultVo resetPwd(TUser user) {
        ResultVo pwdResultVo = UserUtil.checkhLoginPwd(user.getLoginpwd());
        if (pwdResultVo.getCode() == 0) {//密码验证通过
            setLoginPwd(user);
            userMapper.updatePwd(user);
            return new ResultVo(0, "重置密码成功");
        } else {
            return pwdResultVo;
        }
    }

    /**
     * 解除mac绑定
     *
     * @return void
     * @Param [studentid]
     * @Author ywx
     * @Date 2020/9/18 11:56
     **/
    public void removeBind(Integer studentid) {
        UserVo user = new UserVo();
        user.setUserid(studentid);
        user.setBindmac(0);
        user.setMac(null);
        userMapper.updateBindMac(user);
    }

    /**
     * 生成修改码
     *
     * @return com.xhkjedu.vo.ResultVo
     * @Param [userphone]
     * @Author ywx
     * @Date 2020/10/13 15:08
     **/
    public ResultVo updateCode(String userphone) {
        Integer bindNum = userMapper.getBindNumByUserPhone(userphone);
        if (bindNum == 0) return new ResultVo(1, "手机号码未绑定");
        String templateCode = "xgmm";
        if (generateCode(userphone, templateCode)) return new ResultVo(1, "请输入验证码或者在1分钟之后重新点击");
        return new ResultVo(0, "生成修改码成功");
    }

    /**
     * 生成验证码
     *
     * @return boolean
     * @Param [userphone, templateCode]
     * @Author ywx
     * @Date 2020/5/8 10:04
     **/
    private boolean generateCode(String userphone, String templateCode) {
        Integer msgNum = msgMapper.getMsgNumByUserPhone(userphone, N_Utils.getSecondTimestamp());//1分钟内发送短信次数
        if (msgNum != 0) return true;

        Integer messageCode = N_Utils.messageCode();
        String msgtxt = "";
        if ("yhzc".equals(templateCode)) {//用户注册验证码
            msgtxt += "验证码" + messageCode + "，您正在注册成为新用户，感谢您的支持！";
        } else if ("xgmm".equals(templateCode)) {//修改密码验证码
            msgtxt += "验证码" + messageCode + "，您正在尝试修改登录密码，请妥善保管账号信息。";
        } else if ("dlqr".equals(templateCode)) {//登录确认验证码
            msgtxt += "验证码" + messageCode + "，您正在登录，若非本人操作，请勿泄露。";
        } else if ("bdsj".equals(templateCode)) {//绑定手机验证码
            msgtxt += "验证码" + messageCode + "，您正在绑定手机号，若非本人操作，请勿泄露。";
        }
        ZtMsgVo m = new ZtMsgVo();
        m.setMobile(userphone);
        m.setContent(msgtxt);
        SMSSender.sendSms(m);

        //添加短信信息
        TMsg msg = new TMsg();
        msg.setUserphone(userphone);
        msg.setMsgcode(messageCode);
        msg.setMsgtxt(msgtxt);
        msg.setCreatetime(N_Utils.getSecondTimestamp());
        msgMapper.insertSelective(msg);
        return false;
    }

    /**
     * 通过短信修改密码
     *
     * @return com.xhkjedu.vo.ResultVo
     * @Param [user]
     * @Author ywx
     * @Date 2020/10/13 15:17
     **/
    public ResultVo updatePwdByCode(TUser user) {
        ResultVo pwdResultVo = UserUtil.checkhLoginPwd(user.getLoginpwd());
        if (pwdResultVo.getCode() == 0) {
            setLoginPwd(user);
            ResultVo x = getCodeResultVo(user.getUserphone(), user.getMsgcode());
            if (x != null) return x;
            userMapper.updatePwdByCode(user);
            return new ResultVo(0, "修改成功");
        } else {
            return pwdResultVo;
        }
    }

    /**
     * 判断验证码是否有效
     *
     * @return com.xhkjedu.model.baseinfo.ResultVo
     * @Param [userphone, messageCode]
     * @Author ywx
     * @Date 2020/5/8 10:21
     **/
    private ResultVo getCodeResultVo(String userphone, String messageCode) {
        TMsg msg = msgMapper.findByUserPhoneAndCode(userphone, messageCode);//根据手机号和验证码获取短信信息
        if (msg == null) return new ResultVo(1, "验证码有误");
        int secondTimestamp = N_Utils.getSecondTimestamp() - 300;//验证码有效时间为5分钟
        if (msg.getCreatetime() < secondTimestamp) return new ResultVo(1, "验证码失效");
        return null;
    }

    /**
     * 生成登录确认码
     *
     * @return com.xhkjedu.vo.ResultVo
     * @Param [userphone]
     * @Author ywx
     * @Date 2020/10/13 15:19
     **/
    public ResultVo loginCode(String userphone) {
        UserVo userVo = userMapper.getUserByUserPhone(userphone);
        if (userVo == null || userVo.getBindphoned() == 0) return new ResultVo(1, "手机号码未绑定");
        //判断学校状态
        Integer usertype = userVo.getUsertype();
        if (usertype != 999 && userVo.getSchoolstate() != 1) {
            return new ResultVo(1, "此学校已锁定，禁止登录");
        }
        String roleName;
        if (usertype == 2) {
            roleName = "老师";
        } else {
            roleName = "管理员";
        }
        //判断用户状态
        if (userVo.getUserstate() != 1) {
            return new ResultVo(1, "此账号无权访问，请联系" + roleName);
        }
        //判断用户是否锁定
        if (userVo.getUserlock() == 1) {
            return new ResultVo(1, "此账号已锁定，禁止登录");
        }
        //判断用户是否过期
        String usertime = userVo.getUsertime();
        String dayBegin = DatesUtil.getDayBegin();
        if (N_Utils.isNotEmpty(usertime) && usertime.compareTo(dayBegin) < 0) {
            return new ResultVo(1, "账号已过有效期，请联系" + roleName);
        }

        //进行角色判断
        if (usertype == 2) {
            Integer stuweb = userVo.getStuweb();
            if (stuweb != null && stuweb != 1) return new ResultVo(1, "学生账号无法登录");
        }
        String templateCode = "dlqr";
        if (generateCode(userphone, templateCode)) return new ResultVo(1, "请输入验证码或者在1分钟之后重新点击");
        return new ResultVo(0, "生成登录确认码成功");
    }


    public ResultVo batchUpdatePwd(TUser user) {
        setLoginPwd(user);
        userMapper.batchUpdatePwd(user);
        return new ResultVo(0, "修改成功");
    }

    public ResultVo checkLogin(Integer userid, String loginpwd, String device) {
        Map map = new HashMap();
        boolean needLogin = false;
        boolean needPhone = false;
        UserVo user = userMapper.getUserSchoolByUserid(userid);
        String usertime = user.getUsertime();
        String dayBegin = DatesUtil.getDayBegin();
        String msg = "账号信息正常";
        if (!loginpwd.equals(user.getLoginpwd())) {
            needLogin = true;
            msg = "密码已修改，请重新登录";
        }
        //判断学校状态
        Integer usertype = user.getUsertype();
        String roleName;
        if (usertype == 2) {//学生
            roleName = "老师";
        } else {
            roleName = "管理员";
        }
        if (!needLogin && usertype != 999 && user.getSchoolstate() != 1) {
            needLogin = true;
            msg = "学校已锁定，请联系" + roleName;
        }
        //判断用户状态
        if (!needLogin && user.getUserstate() != 1) {
            needLogin = true;
            msg = "此账号无权访问，请联系" + roleName;
        }
        if (!needLogin && N_Utils.isNotEmpty(usertime) && usertime.compareTo(dayBegin) < 0) {
            needLogin = true;
            msg = "账号已过有效期，请联系" + roleName;
        }
        if (!needLogin && user.getUserlock() == 1) {
            needLogin = true;
            msg = "账号已锁定，请联系" + roleName;
        }
        if (usertype == 2) {
            needPhone = userMapper.checkUserPhone(userid);
            if (!needLogin && needPhone) msg = "未绑定手机号";

            if (device != null && "pad".equals(device)) {
                //当是设备不为空并且是pad时，进行验证
                if (user.getSbindmac() == 1 && user.getBindmac() != 1) {
                    needLogin = true;
                    msg = "未绑定设备";
                }
            }
        }
        map.put("needLogin", needLogin);
        map.put("needPhone", needPhone);
        return new ResultVo(0, msg, map);
    }

    //用户选择列表
    public List<Map> listForSel(AssessParams user) {
        Integer year = schoolMapper.getYearById(user.getSchoolid());
        return userMapper.listForSel(user, year);
    }

    /**
     * 获取头像是否可以修改
     *
     * @return java.lang.Integer
     * @Param [userid]
     * @Author ywx
     * @Date 2022/3/14 9:58
     **/
    public Integer getHeadTime(Integer userid) {
        return userMapper.getHeadTime(userid, N_Utils.getSecondTimestamp());
    }

    /**
     * 绑定密保
     *
     * @param usecrets
     * @return void
     * @author ywx
     * @date 2022/3/30 12:47
     */
    @Transactional(rollbackFor = Exception.class)
    public void bindUseCert(List<TUserUsecret> usecrets) {
        Integer userid = usecrets.get(0).getUserid();
        //先删除原来的密保问题
        userUsecretMapper.deleteByUserId(userid);
        usecrets.forEach(uu -> uu.setCreatetime(N_Utils.getSecondTimestamp()));
        userUsecretMapper.insertList(usecrets);
        userMapper.bindUseCert(userid);
    }

    /**
     * 绑定手机
     *
     * @param userid, userphone, msgcode
     * @return com.xhkjedu.vo.ResultVo
     * @author ywx
     * @date 2022/3/30 13:05
     */
    public ResultVo bindUserPhone(Integer userid, String userphone, String msgcode) {
        ResultVo resultVo = getCodeResultVo(userphone, msgcode);
        if (resultVo != null) return resultVo;
        //获取手机号绑定的其他用户数量
        Integer num = userMapper.getNumByUserPhone(userid, userphone);
        if (num != 0) return new ResultVo(1, "此手机号已被绑定");
        userMapper.bindUserPhone(userid, userphone);
        return new ResultVo(0, "绑定手机成功");
    }

    /**
     * 验证身份
     *
     * @param loginname, username
     * @return com.xhkjedu.vo.ResultVo
     * @author ywx
     * @date 2022/3/30 13:59
     */
    public ResultVo checkUser(String loginname, String username) {
        Map map = userMapper.getBindByName(loginname);
        if (N_Utils.isEmpty(map)) {
            return new ResultVo(1, "此账号不存在");
        }
        String username1 = map.get("username").toString();
        if (!username.equals(username1)) {
            return new ResultVo(1, "此账号和姓名不匹配");
        }
        return new ResultVo(0, "验证身份成功", map);
    }

    /**
     * 根据用户id获取关联密保
     *
     * @param userid
     * @return java.util.List<java.util.Map>
     * @author ywx
     * @date 2022/3/30 14:24
     */
    public List<Map> listUsecret(Integer userid) {
        return userUsecretMapper.listUsecret(userid);
    }

    /**
     * 根据用户id获取绑定方式
     *
     * @param userid
     * @return java.util.Map
     * @author ywx
     * @date 2022/3/30 14:57
     */
    public Map getBind(Integer userid) {
        return userMapper.getBindById(userid);
    }

    /**
     * 生成绑定手机码
     *
     * @param userphone
     * @return com.xhkjedu.vo.ResultVo
     * @author ywx
     * @date 2022/3/30 16:34
     */
    public ResultVo bindCode(String userphone) {
        Integer bindNum = userMapper.getBindNumByUserPhone(userphone);
        if (bindNum != 0) return new ResultVo(1, "手机号码已绑定");
        String templateCode = "bdsj";
        if (generateCode(userphone, templateCode)) return new ResultVo(1, "请输入验证码或者在1分钟之后重新点击");
        return new ResultVo(0, "生成绑定手机码成功");
    }

    /**
     * 校验用户密保答案
     *
     * @param userid, usid, usanswer
     * @return com.xhkjedu.vo.ResultVo
     * @author ywx
     * @date 2022/4/7 16:15
     */
    public ResultVo checkUsecret(Integer userid, Integer usid, String usanswer) {
        //获取用户密保答案
        String answer = userUsecretMapper.getAnswerById(userid, usid);
        if (!usanswer.equals(answer)) return new ResultVo(1, "输入答案有误");
        return new ResultVo(0, "校验密保答案成功");
    }

    /**
     * 校验用户密码
     *
     * @param user
     * @return com.xhkjedu.vo.ResultVo
     * @author ywx
     * @date 2022/4/8 15:05
     */
    public ResultVo checkPwd(TUser user) {
        String pwd = userMapper.getPwdByUserId(user.getUserid());
        setLoginPwd(user);
        String loginpwd = user.getLoginpwd();
        if (!loginpwd.equals(pwd)) return new ResultVo(1, "密码不正确");
        return new ResultVo(0, "密码正确");
    }

    /**
     * 锁定用户
     *
     * @param userid
     * @return void
     * @author ywx
     * @date 2022/4/26 16:31
     */
    public void lock(Integer userid) {
        userMapper.updateUserLock(userid, 1);
    }

    /**
     * 解锁用户
     *
     * @param userid
     * @return void
     * @author ywx
     * @date 2022/4/26 16:35
     */
    public void unLock(Integer userid) {
        userMapper.updateUserLockAndClearErrornum(userid);
    }

    /**
     * 获取学校账号数量
     *
     * @param schoolid
     * @return java.lang.Integer
     * @author ywx
     * @date 2022/5/6 11:31
     */
    public Integer getUserNumBySchoolId(Integer schoolid) {
        return userMapper.getUserNumBySchoolId(schoolid);
    }

    //获取用户类型和修改头像时间
    public TUser getUserTypeAndHeadTime(Integer userid) {
        return userMapper.getUserTypeAndHeadTime(userid, N_Utils.getSecondTimestamp());
    }

    //根据id更新用户信息
    public void updateByPrimaryKeySelective(TUser user) {
        userMapper.updateByPrimaryKeySelective(user);
    }

    /**
     * 批量修改密码
     *
     * @param [loginpwd, userids]
     * @return void
     * @author ywx
     * @date 2022/5/20 11:18
     */
    public void batchUpdatePwd2(String loginpwd, List<Integer> userids) {
        loginpwd = N_Utils.getMD5Pwd(loginpwd);
        userMapper.batchUpdatePwd2(loginpwd, userids);
    }

    /**
     * 批量修改有效期
     *
     * @param [usertime, userids]
     * @return void
     * @author ywx
     * @date 2022/5/20 11:22
     */
    public void batchUpdateTime(String usertime, List<Integer> userids) {
        userMapper.batchUpdateTime(usertime, userids);
    }

    /**
     * 批量激活
     *
     * @return void
     * @Param [userids]
     * @Author ywx
     * @Date 2022/6/8 17:10
     **/
    public void batchActivate(List<Integer> userids) {
        userMapper.batchUpdateUserState(1, userids, N_Utils.getSecondTimestamp());
    }
}
