package com.qmth.themis.admin.api;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qmth.themis.business.annotation.ApiJsonObject;
import com.qmth.themis.business.annotation.ApiJsonProperty;
import com.qmth.themis.business.constant.SystemConstant;
import com.qmth.themis.business.dto.AuthDto;
import com.qmth.themis.business.dto.ExpireTimeDTO;
import com.qmth.themis.business.dto.MqDto;
import com.qmth.themis.business.dto.response.TBUserDto;
import com.qmth.themis.business.entity.TBOrg;
import com.qmth.themis.business.entity.TBSession;
import com.qmth.themis.business.entity.TBUser;
import com.qmth.themis.business.entity.TBUserRole;
import com.qmth.themis.business.enums.FieldUniqueEnum;
import com.qmth.themis.business.enums.MqTagEnum;
import com.qmth.themis.business.enums.RoleEnum;
import com.qmth.themis.business.enums.SystemOperationEnum;
import com.qmth.themis.business.service.*;
import com.qmth.themis.business.util.*;
import com.qmth.themis.common.enums.ExceptionResultEnum;
import com.qmth.themis.common.enums.Platform;
import com.qmth.themis.common.enums.Source;
import com.qmth.themis.common.exception.BusinessException;
import com.qmth.themis.common.util.GsonUtil;
import com.qmth.themis.common.util.Result;
import com.qmth.themis.common.util.ResultUtil;
import io.swagger.annotations.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * @Description: 用户 前端控制器
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2020/6/25
 */
@Api(tags = "用户Controller")
@RestController
@RequestMapping(SystemConstant.PREFIX_URL_ADMIN + "/user")
@Validated
public class TBUserController {

    private final static Logger log = LoggerFactory.getLogger(TBUserController.class);

    @Resource
    TBUserService tbUserService;

    @Resource
    ThemisCacheService themisCacheService;

    @Resource
    RedisUtil redisUtil;

    @Resource
    MqDtoService mqDtoService;

    @Resource
    TBUserRoleService tbUserRoleService;

    @Resource
    UidUtil uidUtil;

    @Resource
    MqUtil mqUtil;

    @Resource
    TBSessionService tbSessionService;

    @ApiOperation(value = "用户登录接口")
    @RequestMapping(value = "/login/account", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "用户信息", response = TBUser.class)})
    public Result login(
            @ApiJsonObject(name = "loginAccount", value = {@ApiJsonProperty(key = "loginName", description = "登录名"),
                    @ApiJsonProperty(key = "password", description = "密码"),
                    @ApiJsonProperty(key = "code", description = "机构代码")}) @ApiParam(value = "用户信息", required = true) @RequestBody Map<String, Object> mapParameter)
            throws NoSuchAlgorithmException, UnsupportedEncodingException {
        if (Objects.isNull(mapParameter)) {
            throw new BusinessException(ExceptionResultEnum.USER_INFO_IS_NULL);
        }
        if (Objects.isNull(mapParameter.get("loginName")) || Objects.equals(mapParameter.get("loginName"), "")) {
            throw new BusinessException(ExceptionResultEnum.LOGIN_NAME_IS_NULL);
        }
        if (Objects.isNull(mapParameter.get("password")) || Objects.equals(mapParameter.get("password"), "")) {
            throw new BusinessException(ExceptionResultEnum.PASSWORD_IS_NULL);
        }
        if (Objects.isNull(mapParameter.get("code")) || Objects.equals(mapParameter.get("code"), "")) {
            throw new BusinessException(ExceptionResultEnum.ORG_CODE_IS_NULL);
        }
        String loginName = String.valueOf(mapParameter.get("loginName"));
        String password = String.valueOf(mapParameter.get("password"));
        String orgCode = String.valueOf(mapParameter.get("code"));
        TBOrg tbOrg = null;
        if (!Objects.equals(orgCode.toUpperCase(), SystemConstant.ADMIN)) {
            tbOrg = themisCacheService.addOrgCodeCache(orgCode);
            if (Objects.isNull(tbOrg)) {
                throw new BusinessException(ExceptionResultEnum.ORG_NO);
            }
            if (Objects.nonNull(tbOrg.getEnable()) && tbOrg.getEnable().intValue() == 0) {
                throw new BusinessException(ExceptionResultEnum.ORG_ENABLE);
            }
        }
        QueryWrapper<TBUser> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(TBUser::getLoginName, loginName);
        if (!Objects.equals(orgCode.toUpperCase(), SystemConstant.ADMIN)) {
            wrapper.lambda().eq(TBUser::getOrgId, tbOrg.getId());
        }
        List<TBUser> userList = tbUserService.list(wrapper);
        //用户不存在
        if (Objects.isNull(userList) || userList.size() == 0) {
            throw new BusinessException(ExceptionResultEnum.USER_NO);
        }
        if (Objects.equals(orgCode.toUpperCase(), SystemConstant.ADMIN)) {
            userList.forEach(s -> {
                if (!Objects.equals(s.getRemark(), SystemConstant.SYSADMIN)) {
                    throw new BusinessException("机构代码为admin只允许超级管理员登录");
                }
            });
        }
        if (userList.size() > 1) {
            throw new BusinessException("查询的用户有多条");
        }
        TBUser user = userList.get(0);
        if (Objects.nonNull(user.getOrgId()) && user.getOrgId().longValue() != tbOrg.getId().longValue()) {
            throw new BusinessException("用户机构不匹配");
        }
//        String loginPassword = new String(Base64Util.decode(password), Constants.CHARSET_NAME);
//        密码错误
//        String base64Password = new String(Base64Util.decode(user.getPassword()), Constants.CHARSET_NAME);
        if (!Objects.equals(password, user.getPassword())) {
            throw new BusinessException(ExceptionResultEnum.PASSWORD_ERROR);
        }
        return userLoginCommon(user);
    }

    @ApiOperation(value = "短信验证码登陆接口")
    @RequestMapping(value = "/login/verifyCode", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "用户信息", response = TBUser.class)})
    public Result verifyCode(@ApiParam(value = "用户信息", required = true) @RequestBody Map<String, Object> mapParameter)
            throws NoSuchAlgorithmException {
        if (Objects.isNull(mapParameter.get("loginName")) || Objects.equals(mapParameter.get("loginName"), "")) {
            throw new BusinessException(ExceptionResultEnum.LOGIN_NAME_IS_NULL);
        }
        if (Objects.isNull(mapParameter.get("verifyCode")) || Objects.equals(mapParameter.get("verifyCode"), "")) {
            throw new BusinessException(ExceptionResultEnum.VERIFYCODE_IS_NULL);
        }
        String loginName = String.valueOf(mapParameter.get("loginName"));
        String verifyCode = String.valueOf(mapParameter.get("verifyCode"));

        QueryWrapper<TBUser> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(TBUser::getLoginName, loginName);
        TBUser user = tbUserService.getOne(wrapper);
        //用户不存在
        if (Objects.isNull(user)) {
            throw new BusinessException(ExceptionResultEnum.USER_NO);
        }
        return userLoginCommon(user);
    }

    /**
     * 用户登录公用
     *
     * @param user
     * @return
     * @throws NoSuchAlgorithmException
     */
    private Result userLoginCommon(TBUser user) throws NoSuchAlgorithmException {
        //停用
        if (user.getEnable().intValue() == 0) {
            throw new BusinessException(ExceptionResultEnum.USER_ENABLE);
        }
        Platform platform = ServletUtil.getRequestPlatform();
        String deviceId = ServletUtil.getRequestDeviceId();
        //添加用户鉴权缓存
        AuthDto authDto = themisCacheService.addAccountAuthCache(user.getId());
        //生成token
        String token = SystemConstant.getNanoId();
        themisCacheService.addAccountCache(user.getId());
        Source source = null;
        if (Platform.WIN == platform || Platform.MAC == platform) {
            source = Source.ADMIN_CLIENT;
        } else if (Platform.WEB == platform) {
            source = Source.ADMIN_WEB;
        } else {
            throw new BusinessException(ExceptionResultEnum.PLATFORM_INVALID);
        }
        //添加用户会话缓存
        String sessionId = SessionUtil
                .digest(user.getId(), Math.abs(authDto.getRoleCodes().toString().hashCode()), source);

        ExpireTimeDTO expireTime = SystemConstant.getExpireTime(source, platform);
        TBSession tbSession = new TBSession(user.getOrgId(), sessionId, String.valueOf(user.getId()), authDto.getRoleCodes().toString(),
                source.name(), platform.name(), deviceId, ServletUtil.getRequest().getLocalAddr(), token,
                expireTime.getDate().getTime());
        redisUtil.setUserSession(sessionId, tbSession, expireTime.getExpireSeconds());
        //mq发送消息start
        MqDto mqDto = new MqDto(mqUtil.getTopic(), platform.name(), SystemOperationEnum.SESSION, sessionId);
        mqDtoService.assembleSendAsyncMsg(mqDto);
        MqDto mqDtoLog = new MqDto(mqUtil.getTopic(), MqTagEnum.USER.name(), SystemOperationEnum.LOGIN,
                MqTagEnum.USER, String.valueOf(user.getId()), user.getLoginName());
        mqDtoService.assembleSendAsyncMsg(mqDtoLog);
        //mq发送消息end
        //测试
//        String test = SignatureInfo.build(SignatureType.TOKEN, sessionId, token);
        Map<String, Object> map = new HashMap<>();
        map.put(SystemConstant.ACCESS_TOKEN, token);
//        map.put(SystemConstant.ACCESS_TOKEN, test);
        map.put(SystemConstant.ACCOUNT, user);
        map.put(SystemConstant.SESSION_ID, sessionId);
        map.put("roleCodes", authDto.getRoleCodes());
        map.put(SystemConstant.VERSION, SystemConstant.VERSION_VALUE);
        if (Objects.nonNull(authDto.getTbOrg())) {
            Map orgMap = new HashMap();
            orgMap.put(SystemConstant.NAME, authDto.getTbOrg().getName());
            orgMap.put("logo", authDto.getTbOrg().getLogo());
            orgMap.put("enableMonitorRecord", authDto.getTbOrg().getEnableMonitorRecord());
            map.put(SystemConstant.ORG_INFO, orgMap);
            themisCacheService.addOrgCache(authDto.getTbOrg().getId());
        }
        return ResultUtil.ok(map);
    }

    //    @ApiOperation(value = "es查询接口")
    //    @RequestMapping(value = "/websocketPush", method = RequestMethod.POST)
    //    public Result websocketPush(@RequestBody String message) throws IOException {
    //        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount(request);
    //        WebSocketServer.sendInfo(message, String.valueOf(tbUser.getId()));
    //        return ResultUtil.ok(SystemConstant.SUCCESS);
    //    }

    //    @Resource
    //    TEExamActivityService teExamActivityService;
    //
    //    @Resource
    //    TEExamService teExamService;
    //
    //    @Resource
    //    TEStudentService teStudentService;
    //
    //    @Resource
    //    TEExamStudentService teExamStudentService;
    //
    //    @Resource
    //    TEExamCourseService teExamCourseService;
    //
    //    @Resource
    //    TEExamPaperService teExamPaperService;
    //
    //    @Value("${db.name}")
    //    String dbName;
    //
    //    @Resource
    //    MongoTemplate mongoTemplate;
    //
    //    @Resource
    //    ETEStudentService eteStudentService;
    //
    //    @Resource
    //    ETEStudentRepo eteStudentRepo;

    //    @ApiOperation(value = "es查询接口")
    //    @RequestMapping(value = "/es/list", method = RequestMethod.POST)
    //    @Transactional
    //    public Result esList() {
    ////        eteStudentService.createIndex();
    ////        List<ETEStudentEntity> list = new ArrayList<>();
    ////        for (int i = 0; i < 10; i++) {
    ////            //学生档案
    ////            ETEStudentEntity eteStudentEntity = new ETEStudentEntity();
    ////            eteStudentEntity.setId(Constants.idGen.next());
    ////            eteStudentEntity.setOrgId(1L);
    ////            eteStudentEntity.setIdentity("test" + i);
    ////            eteStudentEntity.setPassword("123456");
    ////            eteStudentEntity.setIdcardNumber(RandomStringUtils.randomAlphanumeric(18));
    ////            eteStudentEntity.setMobileNumber(RandomStringUtils.randomNumeric(11));
    ////            eteStudentEntity.setName("java" + i + RandomStringUtils.randomAlphanumeric(30));
    ////            eteStudentEntity.setGender(1);
    ////            eteStudentEntity.setBasePhotoPath("http://11111");
    ////            eteStudentEntity.setCreateTime(new Date());
    ////            list.add(eteStudentEntity);
    ////        }
    ////        eteStudentService.saveAll(list);
    //////        Iterator<ETEStudentEntity> iterator = eteStudentService.findAll();
    ////        org.springframework.data.domain.Page<ETEStudentEntity> eteStudentEntityPage1 = (org.springframework.data.domain.Page<ETEStudentEntity>) eteStudentService.queryName("2");
    //////        List<ETEStudentEntity> eteStudentEntityList = eteStudentService.findByNameLike("java");
    ////        org.springframework.data.domain.Page<ETEStudentEntity> eteStudentEntityPage2 = (org.springframework.data.domain.Page<ETEStudentEntity>) eteStudentService.queryMobileNumber("2");
    //////        Optional<ETEStudentEntity> eteStudentEntity = eteStudentRepo.findById(eteStudentEntityPage.getContent().get(0).getId());
    ////        Map map = new HashMap();
    ////        map.put(SystemConstant.RECORDS, eteStudentEntityPage1);
    ////        map.put(SystemConstant.RECORDS + 2, eteStudentEntityPage2);
    //////        map.put("bean", eteStudentEntity.get());
    ////        return ResultUtil.ok(map);
    //
    ////        for (int i = 0; i < 5; i++) {
    //
    ////        mqDtoService.assembleSendOneWayMsg("imTopic", "teacher", "老师发送的一条消息1", MqEnum.MESSAGE_LOG.name(), "1", "2");
    ////        mqDtoService.assembleSendOneWayMsg("imTopic", "user", "用户发送的一条消息2", MqEnum.MESSAGE_LOG.name(), "1", "2");
    ////        mqDtoService.assembleSendOneWayMsg("imTopic", "user", "学生发送的一条消息3", MqEnum.MESSAGE_LOG.name(), "1", "2");
    //        Map map = new HashMap();
    //        map.put("sendUserId", "10");
    //        map.put("toUserId", "20");
    //        map.put("model", MessageModel.BROADCASTING);
    ////        map.put("model", MessageModel.CLUSTERING);
    //        MqDto mqDto = new MqDto("websocketImTopic", "im", "学生发送的一条消息4", MqEnum.MESSAGE_LOG, "1", map, "2");
    ////        mqDtoService.assembleSendOneWayMsg("imTopic", "user", "学生发送的一条消息3", MqEnum.MESSAGE_LOG.name(), "1", "2");
    //        mqDtoService.assembleSendOneWayMsg(mqDto);
    //        //        }
    //        return ResultUtil.ok(SystemConstant.SUCCESS);
    //    }

    //    @ApiOperation(value = "用户查询接口")
    //    @RequestMapping(value = "/list", method = RequestMethod.POST)
    //    @Transactional
    //    public Result list() {
    //        String tableName = "t_e_exam_activity_test1";
    //        Integer count = teExamActivityService.existTable(tableName, dbName);
    //        log.info("count:{}", count);
    //        if (count == 0) {
    //            teExamActivityService.createNewTable(tableName);
    //        }
    //        //学生档案
    //        TEStudent teStudent = new TEStudent();
    //        teStudent.setId(Constants.idGen.next());
    //        teStudent.setOrgId(1L);
    //        teStudent.setIdentity(RandomStringUtils.randomAlphanumeric(30));
    //        teStudent.setPassword("123456");
    //        teStudent.setIdcardNumber(RandomStringUtils.randomAlphanumeric(18));
    //        teStudent.setMobileNumber(RandomStringUtils.randomNumeric(11));
    //        teStudent.setName("aaa");
    //        teStudent.setGender(1);
    //        teStudent.setBasePhotoPath("http://11111");
    //        teStudent.setEnable(1);
    //        teStudentService.save(teStudent);
    //
    //        //考试批次
    //        TEExam teExam = new TEExam();
    //        teExam.setId(Constants.idGen.next());
    //        teExam.setOrgId(1L);
    //        teExam.setCode(RandomStringUtils.randomAlphanumeric(20));
    //        teExam.setName("123");
    //        teExam.setTag("test1");
    //        teExam.setStartTime(new Date());
    //        teExam.setEndTime(new Date());
    //        teExam.setStatus(0);
    //        teExam.setShortCode("123456");
    //        teExam.setPrepareSeconds(30);
    //        teExam.setMinDurationSeconds(30);
    //        teExam.setPreNotice("99999");
    //        teExam.setPreNoticeStaySeconds(30);
    //        teExam.setPostNotice("88888");
    //        teExam.setExamCount(5);
    //        teExam.setBreakResumeCount(3);
    //        teExam.setBreakExpireSeconds(30);
    //        teExam.setCameraPhotoUpload(1);
    //        teExam.setReexamAuditing(1);
    //        teExam.setShowObjectiveScore(1);
    //        teExam.setMode(0);
    //        teExam.setEnable(1);
    //        teExam.setArchived(0);
    //        teExam.setOpeningSeconds(30);
    //        teExam.setMaxDurationSeconds(30);
    //        teExam.setForceFinish(1);
    //        teExam.setEntryAuthenticationPolicy(1);
    //        teExam.setInProcessFaceVerify(1);
    //        teExam.setInProcessFaceStrangerIgnore(1);
    //        teExam.setInProcessLivenessVerify(1);
    //        teExam.setInProcessLivenessIntervalSeconds(30);
    //        teExam.setInProcessLivenessJudgePolicy(1);
    //        teExam.setRecordSelectStrategy(1);
    //        teExam.setEnableIpLimit(1);
    //        teExam.setIpAllow("1");
    //        teExam.setScoreStatus(1);
    //        teExamService.save(teExam);
    //
    //        //考试场次
    //        TEExamActivity teExamActivity = new TEExamActivity();
    //        teExamActivity.setId(Constants.idGen.next());
    //        teExamActivity.setExamId(teExam.getId());
    //        teExamActivity.setCode(RandomStringUtils.randomAlphanumeric(20));
    //        teExamActivity.setPrepareSeconds(30);
    //        teExamActivity.setMaxDurationSeconds(30);
    //        teExamActivity.setEnable(1);
    //        teExamActivity.setOpeningSeconds(30);
    //        teExamActivity.setStartTime(new Date());
    //        teExamActivity.setFinishTime(new Date());
    //        teExamActivity.setCreateTime(new Date());
    //        teExamActivityService.insertInfo(tableName, teExamActivity);
    //
    //        //考试科目
    //        TEExamCourse teExamCourse = new TEExamCourse();
    //        teExamCourse.setId(Constants.idGen.next());
    //        teExamCourse.setExamId(teExam.getId());
    //        teExamCourse.setCourseCode(RandomStringUtils.randomAlphanumeric(5));
    //        teExamCourse.setCourseName("测试科目1");
    //        teExamCourse.setObjectiveShuffle(1);
    //        teExamCourse.setOptionShuffle(1);
    //        teExamCourse.setPaperCount(1);
    //        teExamCourse.setHasAnswer(1);
    //        teExamCourse.setAudioPlayCount(1);
    //        teExamCourseService.save(teExamCourse);
    //
    //        //考试试卷
    //        TEExamPaper teExamPaper = new TEExamPaper();
    //        teExamPaper.setId(Constants.idGen.next());
    //        teExamPaper.setName("test1");
    //        teExamPaper.setTotalScore(100D);
    //        teExamPaper.setPaperPath("123");
    //        teExamPaper.setDecryptSecret("345");
    //        teExamPaper.setEncryptMode(1);
    //        teExamPaper.setNeedVoiceAnswer(1);
    //        teExamPaper.setExamId(teExam.getId());
    //        teExamPaper.setCode("test1");
    //        teExamPaper.setCourseCode(teExamCourse.getCourseCode());
    //        teExamPaper.setAnswerPath("123");
    //        teExamPaper.setHasAudio(1);
    //        teExamPaper.setWeight(1D);
    //        teExamPaper.setAudioPlayCount(1);
    //        teExamPaperService.save(teExamPaper);
    //
    //        //考生
    //        TEExamStudent teExamStudent = new TEExamStudent();
    //        teExamStudent.setId(Constants.idGen.next());
    //        teExamStudent.setExamId(teExam.getId());
    //        teExamStudent.setExamActivityId(teExamActivity.getId());
    //        teExamStudent.setStudentId(teStudent.getId());
    //        teExamStudent.setCourseCode(teExamCourse.getCourseCode());
    //        teExamStudent.setRoomCode("1");
    //        teExamStudent.setIdentity(RandomStringUtils.randomAlphanumeric(20));
    //        teExamStudent.setName("132");
    //        Map stuMap = new HashMap();
    //        stuMap.put("examTest1", "aaa");
    //        stuMap.put("examTest2", "bbb");
    //        teExamStudent.setParameter(JacksonUtil.parseJson(stuMap));
    //        teExamStudent.setLeftExamCount(1);
    //        teExamStudent.setRoomName("test1");
    //        teExamStudent.setEnable(1);
    //        teExamStudentService.save(teExamStudent);
    //
    ////        MTEStudentEntity mteStudentEntity = gson.fromJson(gson.toJson(teStudent), MTEStudentEntity.class);
    ////        MTEExamEntity mteExamEntity = gson.fromJson(gson.toJson(teExam), MTEExamEntity.class);
    ////        MTEExamActivityEntity mteExamActivityEntity = gson.fromJson(gson.toJson(teExamActivity), MTEExamActivityEntity.class);
    ////        MTEExamPaperEntity mteExamPaperEntity = gson.fromJson(gson.toJson(teExamPaper), MTEExamPaperEntity.class);
    ////        MTEExamCourseEntity mteExamCourseEntity = gson.fromJson(gson.toJson(teExamCourse), MTEExamCourseEntity.class);
    ////        MTEExamStudentEntity mteExamStudentEntity = gson.fromJson(gson.toJson(teExamStudent), MTEExamStudentEntity.class);
    //
    ////        List list = Arrays.asList(mteExamPaperEntity);
    ////        mteExamCourseEntity.setMteExamPaperEntityList(list);
    //
    ////        list = Arrays.asList(mteExamActivityEntity);
    ////        mteExamEntity.setMteExamActivityEntityList(list);
    //
    ////        list = Arrays.asList(mteExamCourseEntity);
    ////        mteExamStudentEntity.setMteExamEntity(mteExamEntity);
    ////        mteExamStudentEntity.setMteExamActivityEntity(mteExamActivityEntity);
    ////        mteExamStudentEntity.setMteStudentEntity(mteStudentEntity);
    ////        mteExamStudentEntity.setMteExamCourseEntityList(list);
    //
    ////        mongoTemplate.save(mteStudentEntity);
    ////        mongoTemplate.save(mteExamEntity);
    ////        mongoTemplate.save(mteExamActivityEntity);
    ////        mongoTemplate.save(mteExamPaperEntity);
    ////        mongoTemplate.save(mteExamCourseEntity);
    ////        mongoTemplate.save(mteExamStudentEntity);
    ////
    ////        IPage<TEExamActivity> map = teExamActivityService.selectListPage(new Page<>(0, 10), tableName);
    ////        log.info("mysql map:{}", JacksonUtil.parseJson(map));
    ////
    ////        Query query = new Query();
    //////        query.addCriteria(Criteria.where("questionId").in(setQuestionId).andOperator(Criteria.where("examRecordDataId").is(examSessionInfo.getExamRecordDataId())));
    ////        query.skip((1 - 1) * 10).limit(10);//设置起始数和查询条数
    ////        List<MTEStudentEntity> mteStudentEntityList = mongoTemplate.find(query, MTEStudentEntity.class);
    ////        log.info("mongodb mteStudentEntityList:{}", JacksonUtil.parseJson(mteStudentEntityList));
    //////        List<MTEStudentEntity> mteStudentEntityList = mongoTemplate.findAll(MTEStudentEntity.class);
    //////        log.info("mongodb mteStudentEntityList:{}", JacksonUtil.parseJson(mteStudentEntityList));
    ////
    ////        List<MTEExamEntity> mteExamEntityList = mongoTemplate.findAll(MTEExamEntity.class);
    ////        log.info("mongodb mteExamEntityList:{}", JacksonUtil.parseJson(mteExamEntityList));
    ////
    ////        List<MTEExamActivityEntity> mteExamActivityEntityList = mongoTemplate.findAll(MTEExamActivityEntity.class);
    ////        log.info("mongodb mteExamActivityEntityList:{}", JacksonUtil.parseJson(mteExamActivityEntityList));
    //////        List<TEExamActivity> ps = new ArrayList<>();
    //////        mteExamActivityEntityList.forEach(s -> {
    //////            TEExamActivity t = gson.fromJson(gson.toJson(s), TEExamActivity.class);
    //////            ps.add(t);
    //////        });
    ////////      List<TEExamActivity> ps = gson.fromJson(JacksonUtil.parseJson(mteExamActivityEntityList), new TypeToken<List<TEExamActivity>>(){}.getType());
    //////        map.setRecords(ps);
    ////
    ////        List<MTEExamPaperEntity> mteExamPaperEntityList = mongoTemplate.findAll(MTEExamPaperEntity.class);
    ////        log.info("mongodb mteExamPaperEntityList:{}", JacksonUtil.parseJson(mteExamPaperEntityList));
    ////
    ////        List<MTEExamCourseEntity> mteExamCourseEntityList = mongoTemplate.findAll(MTEExamCourseEntity.class);
    ////        log.info("mongodb mteExamCourseEntityList:{}", JacksonUtil.parseJson(mteExamCourseEntityList));
    ////
    ////        List<MTEExamStudentEntity> mteExamStudentEntityList = mongoTemplate.findAll(MTEExamStudentEntity.class);
    ////        log.info("mongodb mteExamStudentEntityList:{}", JacksonUtil.parseJson(mteExamStudentEntityList));
    ////        List<TEExamStudent> ps = new ArrayList<>();
    ////        mteExamStudentEntityList.forEach(s -> {
    ////            TEExamStudent t = gson.fromJson(gson.toJson(s), TEExamStudent.class);
    ////            ps.add(t);
    ////        });
    ////        List<MTEExamStudentEntity> ps1 = new ArrayList<>();
    ////        List<TEExamStudent> list1 = teExamStudentService.list();
    ////        list1.forEach(s -> {
    ////            MTEExamStudentEntity t = gson.fromJson(gson.toJson(s), MTEExamStudentEntity.class);
    ////            ps1.add(t);
    ////        });
    ////        teExamActivityService.dropTable(tableName);
    //        return ResultUtil.ok(SystemConstant.SUCCESS);
    //    }

    @ApiOperation(value = "登出接口")
    @RequestMapping(value = "/logout", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
    public Result logout() throws NoSuchAlgorithmException {
        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
        TBSession tbSession = (TBSession) ServletUtil.getRequestSession();
        AuthDto authDto = themisCacheService.addAccountAuthCache(tbUser.getId());
        if (Objects.isNull(tbSession)) {
            throw new BusinessException(ExceptionResultEnum.LOGIN_NO);
        }
        redisUtil.deleteUserSession(tbSession.getId());
        //循环检查该用户下其他平台是否存在session,不存在则删除用户缓存和鉴权缓存
        boolean delete = true;
        for (Source s : Source.values()) {
            String sessionId = SessionUtil
                    .digest(tbUser.getId(), Math.abs(authDto.getRoleCodes().toString().hashCode()), s.name());
            if (Objects.nonNull(redisUtil.getUserSession(sessionId))) {
                delete = false;
                break;
            }
        }
        if (delete) {
            themisCacheService.removeAccountCache(tbUser.getId());
            themisCacheService.removeAccountAuthCache(tbUser.getId());
        }
        //mq发送消息start
        MqDto mqDto = new MqDto(mqUtil.getTopic(), MqTagEnum.USER.name(), SystemOperationEnum.LOGOUT,
                MqTagEnum.USER, String.valueOf(tbUser.getId()), tbSession.getId());
        mqDtoService.assembleSendAsyncMsg(mqDto);
        //mq发送消息end
        return ResultUtil.ok(true);
    }

    @ApiOperation(value = "用户查询接口")
    @RequestMapping(value = "/query", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "用户信息", response = TBUserDto.class)})
    public Result query(@ApiParam(value = "用户id", required = false) @RequestParam(required = false) Long id,
                        @ApiParam(value = "登录名", required = false) @RequestParam(required = false) String loginName,
                        @ApiParam(value = "姓名", required = false) @RequestParam(required = false) String name,
                        @ApiParam(value = "角色", required = false) @RequestParam(required = false) String roleCode,
                        @ApiParam(value = "是否启用", required = false) @RequestParam(required = false) Integer enable,
                        @ApiParam(value = "机构id", required = false) @RequestParam(required = false) String orgId,
                        @ApiParam(value = "分页页码", required = true) @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) int pageNumber,
                        @ApiParam(value = "分页数", required = true) @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) int pageSize) {
        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
        AuthDto authDto = themisCacheService.addAccountAuthCache(tbUser.getId());
        if (authDto.getRoleCodes().toString().contains(RoleEnum.SUPER_ADMIN.name())) {
            roleCode = Objects.isNull(roleCode) ? RoleEnum.ADMIN.name() : roleCode;
        }
        Long orgIdNew = null;
        if (Objects.isNull(orgId)) {
            orgIdNew = tbUser.getOrgId();
        } else {
            orgIdNew = Long.parseLong(orgId);
        }
        IPage<TBUserDto> tbUserIPage = tbUserService.userQuery(new Page<>(pageNumber, pageSize), id, loginName, name, roleCode, enable, orgIdNew);
        tbUserIPage.getRecords().forEach(s -> {
            if (Objects.nonNull(s.getRoleNameStr())) {
                s.setRoleName(Arrays.asList(s.getRoleNameStr().split(",")));
            }
            if (Objects.nonNull(s.getRoleCodeStr())) {
                s.setRoleCode(Arrays.asList(s.getRoleCodeStr().split(",")));
            }
        });
        return ResultUtil.ok(tbUserIPage);
    }

    //    @CacheEvict(value = "user_cache", key = "'userCacheQuery'")
    @ApiOperation(value = "用户新增/编辑接口")
    @RequestMapping(value = "/save", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
    @Transactional
    public Result save(@ApiJsonObject(name = "userSave", value = {
            @ApiJsonProperty(key = "id", type = "long", example = "1", description = "新增不需要主键"),
            @ApiJsonProperty(key = "orgId", example = "1", description = "机构id"),
            @ApiJsonProperty(key = "loginName", description = "登录名，新增必须"),
            @ApiJsonProperty(key = "name", description = "姓名，新增必须"),
            @ApiJsonProperty(key = "password", description = "密码，新增必须"),
            @ApiJsonProperty(key = "enable", type = "int", example = "1", description = "是否启用"),
            @ApiJsonProperty(key = "mobileNumber", description = "手机号"),
            @ApiJsonProperty(key = "roleCode", description = "角色")}) @ApiParam(value = "用户信息", required = true) @RequestBody Map<String, Object> mapParameter) {
        if (Objects.isNull(mapParameter)) {
            throw new BusinessException(ExceptionResultEnum.USER_INFO_IS_NULL);
        }
        if (Objects.isNull(mapParameter.get(SystemConstant.ORG_ID))) {
            throw new BusinessException(ExceptionResultEnum.ORG_ID_IS_NULL);
        }
        boolean cacheClean = false;
        TBUser loginUser = (TBUser) ServletUtil.getRequestAccount();
        TBUser dbUser = null;
        AuthDto authDto = null;
        if (Objects.nonNull(mapParameter.get(SystemConstant.ID))) {
            dbUser = themisCacheService.addAccountCache(Long.parseLong(String.valueOf(mapParameter.get(SystemConstant.ID))));
            authDto = themisCacheService.addAccountAuthCache(dbUser.getId());
        }
        TBUser tbUser = GsonUtil.fromJson(GsonUtil.toJson(mapParameter), TBUser.class);
        if ((Objects.isNull(tbUser.getPassword()) || Objects.equals(tbUser.getPassword(), "")) && Objects.nonNull(dbUser)) {
            tbUser.setPassword(dbUser.getPassword());
        }
        List<String> roleList = (List<String>) mapParameter.get("roleCode");
        if (Objects.isNull(roleList) || roleList.size() == 0) {
            throw new BusinessException("请选择角色");
        }
        Set<String> roleSet = new HashSet<>(roleList);
        if (roleSet.size() > 1) {
            throw new BusinessException("暂不支持多个角色");
        }
        if ((Objects.nonNull(tbUser) && Objects.nonNull(dbUser) && !tbUser.equals(dbUser))
                || (Objects.nonNull(authDto) && !roleSet.equals(authDto.getRoleCodes()))) {
            cacheClean = true;
        }
        Long orgId = Long.parseLong(String.valueOf(mapParameter.get(SystemConstant.ORG_ID)));
        try {
            if (Objects.isNull(tbUser.getId())) {
                tbUser.setId(uidUtil.getId());
                tbUser.setOrgId(orgId);
                tbUser.setCreateId(loginUser.getId());
                if (Objects.nonNull(roleSet) && roleSet.size() > 0) {
                    TBUser finalTbUser = tbUser;
                    roleSet.forEach(s -> {
                        TBUserRole tbUserRole = new TBUserRole(finalTbUser.getId(), s);
                        tbUserRoleService.save(tbUserRole);
                    });
                }
            } else {
                if (Objects.nonNull(roleSet) && roleSet.size() > 0) {
                    QueryWrapper<TBUserRole> tbUserRoleQueryWrapper = new QueryWrapper<>();
                    tbUserRoleQueryWrapper.lambda().eq(TBUserRole::getUserId, tbUser.getId());
                    tbUserRoleService.remove(tbUserRoleQueryWrapper);
                    TBUser finalTbUser1 = tbUser;
                    roleSet.forEach(s -> {
                        TBUserRole tbUserRole = new TBUserRole(finalTbUser1.getId(), s);
                        tbUserRoleService.save(tbUserRole);
                    });
                }
                tbUser.setUpdateId(loginUser.getId());
            }
            tbUserService.saveOrUpdate(tbUser);
            //清除用户缓存
            if (cacheClean && Objects.nonNull(authDto)) {
                for (Source s : Source.values()) {
                    String sessionId = SessionUtil
                            .digest(tbUser.getId(), Math.abs(authDto.getRoleCodes().toString().hashCode()),
                                    s.name());
                    tbSessionService.removeById(sessionId);
                    redisUtil.deleteUserSession(sessionId);
                }
                themisCacheService.removeAccountCache(tbUser.getId());
                themisCacheService.removeAccountAuthCache(tbUser.getId());
            } else {
                themisCacheService.removeAccountCache(tbUser.getId());
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (e instanceof DuplicateKeyException) {
                String errorColumn = e.getCause().toString();
                String columnStr = errorColumn.substring(errorColumn.lastIndexOf("key") + 3, errorColumn.length())
                        .replaceAll("'", "");
                throw new BusinessException(
                        "机构id[" + orgId + "]下的" + FieldUniqueEnum.convertToCode(columnStr) + "数据不允许重复插入");
            } else if (e instanceof BusinessException) {
                throw new BusinessException(e.getMessage());
            } else {
                throw new RuntimeException(e);
            }
        }
        return ResultUtil.ok(true);
    }

    @ApiOperation(value = "获取短信验证码接口")
    @RequestMapping(value = "/getVerifyCode", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "{\"verifyCode\":123456}", response = Result.class)})
    public Result getVerifyCode(@ApiParam(value = "登录名", required = true) @RequestParam String loginName) {
        if (Objects.isNull(loginName) || Objects.equals(loginName, "")) {
            throw new BusinessException(ExceptionResultEnum.LOGIN_NAME_IS_NULL);
        }
        return ResultUtil.ok(true);
    }

    @ApiOperation(value = "获取短信验证码接口")
    @RequestMapping(value = "/validate/verifyCode", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
    public Result validateVerifyCode(@ApiParam(value = "验证码", required = true) @RequestParam String verifyCode) {
        if (Objects.isNull(verifyCode) || Objects.equals(verifyCode, "")) {
            throw new BusinessException(ExceptionResultEnum.VERIFYCODE_IS_NULL);
        }
        return ResultUtil.ok(true);
    }

    @ApiOperation(value = "二次验证获取短信验证码接口")
    @RequestMapping(value = "/validate/getVerifyCode", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
    public Result validateGetVerifyCode() {
        return ResultUtil.ok(true);
    }

    @ApiOperation(value = "用户停用/启用接口")
    @RequestMapping(value = "/enable", method = RequestMethod.POST)
    @Transactional
    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
    public Result enableUser(@ApiJsonObject(name = "enableUser", value = {
            @ApiJsonProperty(key = "id", type = "long", example = "1", description = "用户id"),
            @ApiJsonProperty(key = "enable", type = "int", example = "1", description = "停用/启用")}) @ApiParam(value = "用户信息", required = true) @RequestBody Map<String, Object> user) throws NoSuchAlgorithmException {
        if (Objects.isNull(user.get(SystemConstant.ID)) || Objects.equals(user.get(SystemConstant.ID), "")) {
            throw new BusinessException(ExceptionResultEnum.USER_ID_IS_NULL);
        }
        Long userId = Long.parseLong(String.valueOf(user.get(SystemConstant.ID)));
        if (Objects.isNull(user.get("enable")) || Objects.equals(user.get("enable"), "")) {
            throw new BusinessException(ExceptionResultEnum.ENABLE_IS_NULL);
        }
        Integer enable = Integer.parseInt(String.valueOf(user.get("enable")));
        TBUser tbUser = themisCacheService.addAccountCache(userId);
        if (Objects.isNull(tbUser)) {
            throw new BusinessException(ExceptionResultEnum.USER_NO);
        }
        //保存用户
        tbUser.setEnable(enable);
        tbUserService.updateById(tbUser);
        if (enable == 0) {
            AuthDto authDto = themisCacheService.addAccountAuthCache(tbUser.getId());
            if (Objects.nonNull(authDto)) {
                for (Source s : Source.values()) {
                    String sessionId = SessionUtil
                            .digest(tbUser.getId(), Math.abs(authDto.getRoleCodes().toString().hashCode()),
                                    s.name());
                    tbSessionService.removeById(sessionId);
                    redisUtil.deleteUserSession(sessionId);
                }
            }
            themisCacheService.removeAccountCache(tbUser.getId());
            themisCacheService.removeAccountAuthCache(tbUser.getId());
        } else {
            themisCacheService.removeAccountCache(tbUser.getId());
        }
        return ResultUtil.ok(true);
    }

    @ApiOperation(value = "用户修改密码接口")
    @RequestMapping(value = "/updatePwd", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
    @Transactional
    public Result userUpdatePwd(@ApiJsonObject(name = "userUpdatePwd", value = {
            @ApiJsonProperty(key = "id", type = "long", example = "1", description = "用户ID"),
            @ApiJsonProperty(key = "password", description = "新密码")}) @ApiParam(value = "用户信息", required = true) @RequestBody Map<String, Object> mapParameter) throws NoSuchAlgorithmException {
        if (Objects.isNull(mapParameter.get(SystemConstant.ID)) || Objects.equals(mapParameter.get(SystemConstant.ID), "")) {
            throw new BusinessException(ExceptionResultEnum.USER_ID_IS_NULL);
        }
        Long id = Long.parseLong(String.valueOf(mapParameter.get(SystemConstant.ID)));
        if (Objects.isNull(mapParameter.get("password")) || Objects.equals(mapParameter.get("password"), "")) {
            throw new BusinessException(ExceptionResultEnum.PASSWORD_IS_NULL);
        }
        String password = String.valueOf(mapParameter.get("password"));
        TBUser tbUser = themisCacheService.addAccountCache(id);
        if (Objects.isNull(tbUser)) {
            throw new BusinessException(ExceptionResultEnum.USER_NO);
        }
        TBUser currentUser = (TBUser) ServletUtil.getRequestAccount();
        tbUser.setPassword(password);
        tbUser.setUpdateId(currentUser.getId());
        if (Objects.nonNull(password) && Objects.equals(password, SystemConstant.DEFAULT_PASSWORD)) {
            tbUser.setPwdForce(false);
        } else {
            tbUser.setPwdForce(true);
        }
        tbUserService.updateById(tbUser);

        AuthDto authDto = themisCacheService.addAccountAuthCache(tbUser.getId());
        if (Objects.nonNull(authDto)) {
            for (Source s : Source.values()) {
                String sessionId = SessionUtil
                        .digest(tbUser.getId(), Math.abs(authDto.getRoleCodes().toString().hashCode()), s.name());
                if (Objects.nonNull(redisUtil.getUserSession(sessionId))) {
                    redisUtil.deleteUserSession(sessionId);
                }
            }
        }

        themisCacheService.removeAccountCache(tbUser.getId());
        themisCacheService.removeAccountAuthCache(tbUser.getId());
        return ResultUtil.ok(true);
    }
}
