package com.tykj.dev.device.train.controller;

import com.fasterxml.jackson.core.type.TypeReference;
import com.tykj.dev.blockcha.subject.entity.BcHash;
import com.tykj.dev.blockcha.subject.service.BlockChainUtil;
import com.tykj.dev.config.swagger.AutoDocument;
import com.tykj.dev.device.file.service.FilesUtil;
import com.tykj.dev.device.task.service.TaskLogService;
import com.tykj.dev.device.task.service.TaskService;
import com.tykj.dev.device.task.subject.bto.TaskBto;
import com.tykj.dev.device.task.subject.bto.TaskLogBto;
import com.tykj.dev.device.task.subject.domin.Task;
import com.tykj.dev.device.train.dao.OnlineTainUserTimeDao;
import com.tykj.dev.device.train.dao.TestPaperDao;
import com.tykj.dev.device.train.dao.TrainUnitDao;
import com.tykj.dev.device.train.dao.TrainUserDao;
import com.tykj.dev.device.train.entity.*;
import com.tykj.dev.device.train.entity.vo.*;
import com.tykj.dev.device.train.service.OnlineTainUserTimeService;
import com.tykj.dev.device.train.service.TestPaperService;
import com.tykj.dev.device.train.service.TrainTaskService;
import com.tykj.dev.device.train.service.TrainThemeService;
import com.tykj.dev.device.user.read.service.MessageService;
import com.tykj.dev.device.user.read.subject.bto.MessageBto;
import com.tykj.dev.device.user.subject.dao.UnitsDao;
import com.tykj.dev.device.user.subject.entity.SecurityUser;
import com.tykj.dev.device.user.subject.entity.Units;
import com.tykj.dev.device.user.subject.entity.User;
import com.tykj.dev.device.user.subject.entity.UserLog;
import com.tykj.dev.device.user.subject.service.MgrcertService;
import com.tykj.dev.device.user.subject.service.UnitsService;
import com.tykj.dev.device.user.subject.service.UserLogService;
import com.tykj.dev.device.user.subject.service.UserService;
import com.tykj.dev.misc.base.BeanHelper;
import com.tykj.dev.misc.base.BusinessEnum;
import com.tykj.dev.misc.base.StatusEnum;
import com.tykj.dev.misc.utils.JacksonUtil;
import com.tykj.dev.misc.utils.TaskDisposeUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;


/**
 * @author zjm
 * @version 1.0.0
 * @ClassName TrainJobController.java
 * @Description TODO
 * @createTime 2020年08月16日 21:26:00
 */
@RestController
@RequestMapping(value = "/job/train")
@AutoDocument
@Api(tags = "专管员培训业务", description = "培训业务接口")
@Slf4j
public class TrainJobController {

    @Autowired
    TrainThemeService trainThemeService;

    @Autowired
    OnlineTainUserTimeService onlineTainUserTimeService;

    @Autowired
    MgrcertService mgrcertService;

    @Autowired
    TestPaperDao testPaperDao;

    @Autowired
    TestPaperService testPaperService;

    @Autowired
    OnlineTainUserTimeDao onlineTainUserTimeDao;

    @Autowired
    UnitsService unitsService;

    @Autowired
    UnitsDao unitsDao;

    @Autowired
    UserService userService;

    @Autowired
    TaskService taskService;
    @Autowired
    TrainTaskService trainTaskService;
    @Autowired
    TaskLogService taskLogService;
    @Autowired
    TrainUserDao trainUserDao;
    @Autowired
    UserLogService userLogService;
    @Autowired
    BlockChainUtil blockChainUtil;
    @Autowired
    MessageService messageService;
    @Autowired
    TrainUnitDao trainUnitDao;

    /**
     * 新建培训信息
     * 首先创建task(发起人task) 在创建状态为新建(id_done为1)以及报名中待job，在给所有的专管员发起一个job（待报名）
     */
    @ApiOperation(value = "1.培训业务新建接口", notes = "有两类人员，一必须培训的人员，这里状态为报名确认，只需要确认就ok，2。不是必须报名的人员 状态 待报名，需要让用户选择报名 或不报名")
    @PostMapping("/initiate")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity newTrain(@ApiIgnore @AuthenticationPrincipal SecurityUser securityUser, @RequestBody TrainThemeAddVo trainThemeAddVo) {
        TrainTheme trainThemeNoDb= trainThemeAddVo.toDo();
        trainThemeNoDb.setTrainDataFiles(FilesUtil.stringFileToList(trainThemeAddVo.getTrainDataFileList()));
        trainThemeNoDb.setCoursewareFiles(JacksonUtil.toJSon(trainThemeAddVo.getCoursewareFileList()));
        trainThemeNoDb.setGenerateTestPaperString(JacksonUtil.toJSon(trainThemeAddVo.getGenerateTestPaper()));
        TrainTheme trainTheme = trainThemeService.save(trainThemeNoDb);
        List<User> userList=userService.findUnitsIdInUsers(trainThemeAddVo.getUnitsIds());
        //添加培训用户信息
        userList.forEach(
                user -> {
            if (user.getTrainStatus()==1 || user.getTrainStatus()==2){
                TrainUser trainUser= userToTrainUser(user);
                trainUser.setIsSignUp(2);
                trainUser.setIsNotJoinUserId(1);
                trainUser.setTrainId(trainTheme.getTrainId());
                saveTrainUser(trainUser);
            }else {
                TrainUser trainUser= userToTrainUser(user);
                trainUser.setIsSignUp(2);
                trainUser.setIsNotJoinUserId(0);
                trainUser.setTrainId(trainTheme.getTrainId());
                saveTrainUser(trainUser);
            }
          }
        );
        //添加培训单位
        List<TrainUnit> trainUnits=new ArrayList<>();
        trainThemeAddVo.getUnitsIds().forEach(
                unitId->{
                    TrainUnit trainUnit=new TrainUnit();
                    trainUnit.setSubmitStatus(1);
                    trainUnit.setTrainId(trainTheme.getTrainId());
                    trainUnit.setUnitId(unitId);
                    trainUnits.add(trainUnit);
                }
        );
        trainUnitDao.saveAll(trainUnits);

        //生成培训总任务 任务状态待报名
        List<Integer> integers = new ArrayList<>();
        integers.add(securityUser.getCurrentUserInfo().getUserId());
        TaskBto taskVo = new TaskBto(StatusEnum.TRAIN1000.id, trainTheme.getName(), null, null, trainTheme.getTrainId(), BusinessEnum.TRAIN.id, securityUser.getCurrentUserInfo().getUnitsId(), 0, null, integers);
        if (trainThemeAddVo.getTrainType() == 0) {
            taskVo.setCustomInfo("online");
        }
        TaskBto task = taskService.start(taskVo);
        trainTheme.setTrainStatus(StatusEnum.TRAIN1000.id);
        trainThemeAddVo.getUnitsIds().forEach(
                unitId->{
                    List<Integer> list = new ArrayList<>();
                    list.add(0);
                    TaskBto taskBto= new TaskBto(StatusEnum.TRAIN1002.id, trainTheme.getName(), task.getId(), task.getId().toString(), trainTheme.getTrainId(), BusinessEnum.TRAIN_SIGN_UP.id, unitId, 0, null, list);
                    taskService.start(taskBto);
                }
        );
        if (securityUser.getCurrentUserInfo().getUnits().getLevel()==1){
            List<Integer> userIds=userService.findAllByUnite(securityUser.getCurrentUserInfo().getUnitsId()).stream().map(User::getUserId).collect(Collectors.toList());
            userIds.remove(securityUser.getCurrentUserInfo().getUserId());
            messageService.add(new MessageBto(task.getId(),BusinessEnum.TRAIN.id,"发起培训业务:"+trainTheme.getName(),userIds,trainTheme.getTrainId().toString()));
        }else {
            List<Integer> userIds=userService.findAllByUnite(securityUser.getCurrentUserInfo().getUnitsId()).stream().map(User::getUserId).collect(Collectors.toList());
            userIds.remove(securityUser.getCurrentUserInfo().getUserId());
            userIds.addAll(userService.findAllByUnite(1).stream().map(User::getUserId).collect(Collectors.toList()));
            messageService.add(new MessageBto(task.getId(),BusinessEnum.TRAIN.id,"发起培训业务:"+trainTheme.getName(),userIds,trainTheme.getTrainId().toString()));
        }
        return ResponseEntity.ok(trainThemeService.save(trainTheme));
    }

    //报名

    /**
     * 待报名 （所调用的接口）
     * 用户报名接口
     * @param signUpReturn
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation(value = "2。报名和确认接口", notes = "若是确认请填写confirm为1，若报名returns=0、若不报名returns=1")
    @PostMapping("/signUp")
    public ResponseEntity signUp(@ApiIgnore @AuthenticationPrincipal SecurityUser securityUser, @RequestBody signUpReturn signUpReturn) {
        TrainTheme trainTheme = trainThemeService.findById(signUpReturn.getTrainThemeId());
        TaskBto taskBto = taskService.get(signUpReturn.getTaskId());
        TaskDisposeUtil.isNotSubmit(taskBto.getBillStatus(),StatusEnum.TRAIN1002);
        Integer taskId=taskBto.getId();
        List<Integer> userIds=new ArrayList<>();
        TrainUnit trainUnit= trainUnitDao.findByTrainIdAndUnitId(trainTheme.getTrainId(),taskBto.getOwnUnit());
        if (trainTheme.getTrainTime().getTime()<new Date().getTime()){
            trainUnit.setSubmitStatus(3);
        }else {
            trainUnit.setSubmitStatus(2);
        }
        List<SignUpUsers> signUpUsers= signUpReturn.getSignUpUsers();
        signUpUsers.forEach(signUpUser -> {
            TrainUser trainUser= trainUserDao.findByUserIdAndTrainId(signUpUser.getUserId(),trainTheme.getTrainId());
            if (signUpUser.getReturns() == 0) {
                trainUser.setIsSignUp(1);
                trainUser.setArriveMeal(signUpUser.getArriveMeal());
                trainUser.setArriveTime(signUpUser.getArriveTime());
                trainUser.setLeaveMeal(signUpUser.getLeaveMeal());
                trainUser.setLeaveTime(signUpUser.getLeaveTime());
                trainUser.setNote(signUpUser.getNote());
                userIds.add(trainUser.getUserId());
                userLogService.save(new UserLog(trainUser.getUserId(),new Date(),"报名参加培训"));
            } else {
                trainUser.setIsSignUp(2);
                trainUser.setNote(signUpUser.getNote());
            }
            trainUser.setUnitsName(unitsDao.findById(trainUser.getUnitsId()).get().getName());
            saveTrainUser(trainUser);
        });
        TaskLogBto taskLogBto = new TaskLogBto(taskId, "提交了培训名单", null);
        taskLogService.addLog(taskLogBto);
//        userLogService.save(new UserLog(securityUser.getCurrentUserInfo().getUserId(),new Date(),"不参加培训"));
//        taskBto.setCreateUserId(securityUser.getCurrentUserInfo().getUserId());
//        taskBto = taskService.moveToEnd(taskBto);
        trainUnitDao.save(trainUnit);
        messageService.add(new MessageBto(0, BusinessEnum.TRAIN_SIGN_UP.id, securityUser.getCurrentUserInfo().getName()+"帮你报名["+trainTheme.getName()+"]培训,培训地点："+trainTheme.getTrainLocation(), userIds, trainTheme.getTrainId().toString()));
        return ResponseEntity.ok(taskBto);
    }


    /**
     * 拒绝报名
     * 管理者拒绝某个单位的报名
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation(value = "拒绝某个单位的报名", notes = "拒绝某个单位的报名")
    @GetMapping("/refuse/{taskId}")
    public ResponseEntity signUp(@ApiIgnore @AuthenticationPrincipal SecurityUser securityUser, @PathVariable Integer taskId) {
        TaskBto taskBto = taskService.get(taskId);
        Units units=unitsService.findById(taskBto.getOwnUnit());
        TrainTheme trainTheme = trainThemeService.findById(taskBto.getBillId());
        TaskDisposeUtil.isNotSubmit(taskBto.getBillStatus(), StatusEnum.END);
        taskBto = taskService.moveToSpecial(taskBto, StatusEnum.TRAIN1002, 0);
        List<Integer> userIds = userService.findAllByUnite(securityUser.getCurrentUserInfo().getUnitsId()).stream().map(User::getUserId).collect(Collectors.toList());
        userIds.addAll(userService.findAllByUnite(trainTheme.getUnitsId()).stream().filter(user -> !user.getUserId().equals(securityUser.getCurrentUserInfo().getUserId())).map(User::getUserId).collect(Collectors.toList()));
        messageService.add(new MessageBto(0, BusinessEnum.TRAIN.id, securityUser.getCurrentUserInfo().getName()+"让"+units.getName()+"重新培训报名", userIds, trainTheme.getTrainId().toString()));
        return ResponseEntity.ok(taskBto);
    }


    /**
     * 报名结束
     *
     * @param trainId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @GetMapping("/signUpEnd/{trainId}")
    public ResponseEntity signUpEnd(@PathVariable Integer trainId) {
        TrainTheme trainTheme = trainThemeService.findById(trainId);
        //查询所有必须报名而没有报名的task 状态直接转为待培训
        trainTaskService.selectBillidAndBillType(trainId, BusinessEnum.TRAIN_SIGN_UP.id, StatusEnum.TRAIN1002.id).forEach(
                taskBto -> {
                    taskService.moveToEnd(taskBto);
                }
        );
        //查询主task
        TaskBto taskBto = trainTaskService.selectFatherIsNullAndBillidAndBillType(trainTheme.getTrainId(), BusinessEnum.TRAIN.id);
       //主task往下推待培训状态，0
        taskService.moveToSpecial(taskBto, StatusEnum.TRAIN1010, 0);
        //5 待培训
        trainTheme.setTrainStatus(StatusEnum.TRAIN1010.id);
        return ResponseEntity.ok(trainThemeService.save(trainTheme));
    }

    //培训中
    @GetMapping("/inTraining/{trainId}")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity inTraining(@PathVariable Integer trainId) {
        TrainTheme trainTheme = trainThemeService.findById(trainId);
        //5 培训中
        TaskBto taskBto = trainTaskService.selectFatherIsNullAndBillidAndBillType(trainTheme.getTrainId(), BusinessEnum.TRAIN.id);
//      //主task往下推待培训状态，0
        taskService.moveToSpecial(taskBto, StatusEnum.TRAIN1004, 0);
        trainTheme.setTrainStatus(StatusEnum.TRAIN1004.id);

        //判断是否为线上培训 如是 则任务发给个人 如不是 则给单位推送任务。
        if (trainTheme.getTrainType()==1) {
//            trainTaskService.selectBillidAndBillType(trainId, BusinessEnum.TRAIN_SIGN_UP.id, StatusEnum.TRAIN1010.id).forEach(
//                    taskBto1 -> taskService.moveToSpecial(taskBto1, StatusEnum.TRAIN1004, taskBto1.getInvolveUserIdList().get(0))
//            );
        }else {
//            trainTaskService.selectBillidAndBillType(trainId, BusinessEnum.TRAIN_SIGN_UP.id, StatusEnum.TRAIN1003.id).forEach(
//                    taskBto1 -> taskService.moveToEnd(taskBto1)
//            );
           List<Integer> userIds= trainUserDao.findAllByIsSignUpAndTrainId(1,trainId).stream().map(TrainUser::getUserId).collect(Collectors.toList());
           userIds.forEach(
                   userId-> onlineLearningTask(trainId,taskBto.getId(),trainTheme.getName(),userId,taskBto.getOwnUnit())
           );
        }
        return ResponseEntity.ok(trainThemeService.save(trainTheme));
    }

    //等待批阅接口 判断人员是否全部提交试卷
    @GetMapping("/waitExamines/{trainId}/{taskId}")
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation(value = "等待批阅接口 判断人员是否全部提交试卷", notes = "等待批阅接口 判断人员是否全部提交试卷")
    public ResponseEntity inTraining(@PathVariable Integer trainId, @PathVariable Integer taskId) {
        TrainTheme trainTheme = trainThemeService.findById(trainId);
        //5 培训中
        WaitExaminesVo waitExaminesVo=trainTheme.toWaitExaminesVo();
        waitExaminesVo.setTrainDataFileList(FilesUtil.stringFileToList(trainTheme.getTrainDataFiles()));
        waitExaminesVo.setCoursewareFileList(JacksonUtil.readValue(trainTheme.getCoursewareFiles(), new TypeReference<List<CoursewareFile>>() {
        }));
        waitExaminesVo.setGenerateTestPaper(JacksonUtil.readValue(trainTheme.getGenerateTestPaperString(), GenerateTestPaper.class));
        List<TrainUser> userList= trainUserDao.findAllByTrainId(trainId).stream().filter(trainUser -> trainUser.getIsSignUp()==1).collect(Collectors.toList());
//        if (userList.stream().allMatch(trainUser -> trainUser.getOnlineStatus()==2 ||trainUser.getOnlineStatus()==3)) {
//            if (!taskBto.getBillStatus().equals(StatusEnum.TRAIN1007.id)) {
//                taskService.moveToSpecial(taskBto, StatusEnum.TRAIN1015, 0);
//                trainTheme.setTrainStatus(StatusEnum.TRAIN1015.id);
//            }
//            waitExaminesVo.setIsNot(1);
//            trainTheme.setIsNotExamines(1);
//        }
        waitExaminesVo.setTrainUsers(userList);
        return ResponseEntity.ok(waitExaminesVo);
    }


    /**
     * 学习课件，课件阅读保存接口
     */
    @ApiOperation(value = "生成试卷", notes = "生成试卷")
    @GetMapping("/generateTestPaper/{trainId}/{taskId}")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity generateTestPaper(@ApiIgnore @AuthenticationPrincipal SecurityUser securityUser,@PathVariable Integer trainId, @PathVariable Integer taskId){
            TrainTheme trainTheme = trainThemeService.findById(trainId);
            GenerateTestPaper generateTestPaper=JacksonUtil.readValue(trainTheme.getGenerateTestPaperString(), GenerateTestPaper.class);
            TestPaper testPaper=  testPaperService.generateTestPaper(generateTestPaper);
            testPaper.setTaskId(taskId);
            testPaper.setTrainId(trainId);
            testPaper.setUserId(securityUser.getCurrentUserInfo().getUserId());
            testPaper.setUserName(securityUser.getCurrentUserInfo().getName());
            testPaper.setGenerateTestPaper(generateTestPaper);
            return ResponseEntity.ok(testPaper);
    }

    /**
     * 学习课件，课件阅读保存接口
     */
    @ApiOperation(value = "学习课件，课件阅读保存接口", notes = "状态改为'市培训申请发证")
    @PostMapping("/onlineTainUserTime/save")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity upDateSubject(@RequestBody OnlineTainUserTime onlineTainUserTime){
        onlineTainUserTime.setSubjectVos(JacksonUtil.toJSon(onlineTainUserTime.getSubjectVoList()));
        boolean falg= onlineTainUserTime.getSubjectVoList().stream().allMatch(subjectVo -> subjectVo.getIsEnd()==1);
        if (falg){
            onlineTainUserTime.setIsNotCanExam(1);
            TaskBto taskBto = taskService.get(onlineTainUserTime.getTaskId());
            taskService.moveToSpecial(taskBto,StatusEnum.TRAIN1014,onlineTainUserTime.getUserId());
        }
        onlineTainUserTime = onlineTainUserTimeDao.save(onlineTainUserTime);
        return ResponseEntity.ok(onlineTainUserTime);
    }

    /**
     * 查询个人学习课件时间
     */
    @ApiOperation(value = "查询个人学习课件时间", notes = "查询个人学习课件时间")
    @GetMapping("/select/onlineTainUserTime/{trainId}/{userId}")
    public ResponseEntity selectOnlineTainUserTime(@PathVariable Integer trainId, @PathVariable Integer userId){
        return ResponseEntity.ok(onlineTainUserTimeService.findByUserIdAndTrainId(userId,trainId));
    }

    /**
     * 提交试卷
     */
    @ApiOperation(value = "提交考卷", notes = "提交考卷接口")
    @PostMapping("/submitTestPaper")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity submitTestPaper(@RequestBody TestPaper testPaper){
        testPaper.setJudgeProblem(JacksonUtil.toJSon(testPaper.getJudgeProblemList()));
        testPaper.setChooseProblem(JacksonUtil.toJSon(testPaper.getChooseProblemList()));
        testPaper.setMultipleChoiceProblem(JacksonUtil.toJSon(testPaper.getMultipleChoiceProblemList()));
        testPaper.setShortAnswerProblem(JacksonUtil.toJSon(testPaper.getShortAnswerProblemList()));
        automaticReadingTestPaper(testPaper);
        TrainUser trainUser= trainUserDao.findByUserIdAndTrainId(testPaper.getUserId(),testPaper.getTrainId());
        trainUser.setOnlineStatus(2);
        trainUserDao.save(trainUser);
        TaskBto taskBto = taskService.get(testPaper.getTaskId());
        taskService.moveToSpecial(taskBto,StatusEnum.TRAIN1013,-1);
        testPaper = testPaperDao.save(testPaper);
        return ResponseEntity.ok(testPaper);
    }


    /**
     * 批阅试卷
     */
    @ApiOperation(value = "批阅试卷", notes = "批阅试卷")
    @PostMapping("/readOverTestPaper")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity readOverTestPaper(@RequestBody ReadOverTestPaper readOverTestPaper,@ApiIgnore @AuthenticationPrincipal SecurityUser securityUser){
        AtomicReference<Float> shortAnswerScore = new AtomicReference<>();
        shortAnswerScore.set(0f);
        readOverTestPaper.getProblemVos().forEach(
                problemVo -> shortAnswerScore.set(shortAnswerScore.get() + problemVo.getScore())
        );
        TestPaper testPaper= testPaperService.findByUserIdAndTrainId1(readOverTestPaper.getUserId(),readOverTestPaper.getTrainId());
        testPaper.setShortAnswerScore(shortAnswerScore.get());
        testPaper.setShortAnswerProblem(JacksonUtil.toJSon(readOverTestPaper.getProblemVos()));
        testPaper.setCountScore(testPaper.getChooseScore()+testPaper.getJudgeScore()+testPaper.getMultipleScore()+testPaper.getShortAnswerScore());
        testPaper.setStatus(1);
        testPaper.setMarkingId(securityUser.getCurrentUserInfo().getUserId());
        TrainUser trainUser= trainUserDao.findByUserIdAndTrainId(testPaper.getUserId(),testPaper.getTrainId());
        trainUser.setScore(testPaper.getCountScore().toString());
        trainUser.setOnlineStatus(3);
        trainUserDao.save(trainUser);
        TaskBto testPaperTaskBto = taskService.get(testPaper.getTaskId());
        taskService.moveToSpecial(testPaperTaskBto,StatusEnum.TRAIN1013,-1);
        testPaperDao.save(testPaper);
        boolean falg=trainUserDao.findAllByTrainId(readOverTestPaper.getTrainId()).stream().filter(trainUser1 -> trainUser1.getIsSignUp()==1).allMatch(trainUser1 -> trainUser1.getOnlineStatus()==3);
        if (falg){
           TaskBto taskBto = trainTaskService.selectFatherIsNullAndBillidAndBillType(testPaper.getTrainId(), BusinessEnum.TRAIN.id);
           taskService.moveToSpecial(taskBto,StatusEnum.TRAIN1007,0);
           TrainTheme trainTheme= trainThemeService.findById(testPaper.getTrainId());
           trainTheme.setIsNotExamines(2);
           trainTheme.setTrainStatus(StatusEnum.TRAIN1007.id);
           trainThemeService.save(trainTheme);
        }
        return ResponseEntity.ok(falg);
    }

    /**
     * 查询试卷 用户id和培训id
     */
    @ApiOperation(value = "查询试卷 用户id和培训id", notes = "查询试卷")
    @GetMapping("/select/testPaper/{trainId}/{userId}")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity readOverTestPaper(@PathVariable Integer trainId, @PathVariable Integer userId){
        TestPaper testPaper=  testPaperDao.findByTrainIdAndUserId(trainId,userId);
        testPaper.setChooseProblemList(JacksonUtil.readValue(testPaper.getChooseProblem(), new TypeReference<List<ProblemVo>>() {
        }));
        testPaper.setJudgeProblemList(JacksonUtil.readValue(testPaper.getJudgeProblem(), new TypeReference<List<ProblemVo>>() {
        }));
        testPaper.setMultipleChoiceProblemList(JacksonUtil.readValue(testPaper.getMultipleChoiceProblem(), new TypeReference<List<ProblemVo>>() {
        }));
        testPaper.setShortAnswerProblemList(JacksonUtil.readValue(testPaper.getShortAnswerProblem(), new TypeReference<List<ProblemVo>>() {
        }));
        return ResponseEntity.ok(testPaper);
    }


    private void automaticReadingTestPaper(TestPaper testPaper){
         TrainTheme trainTheme = trainThemeService.findById(testPaper.getTrainId());
         GenerateTestPaper generateTestPaper =  JacksonUtil.readValue(trainTheme.getGenerateTestPaperString(),GenerateTestPaper.class);

         AtomicReference<Float> chooseScore= new AtomicReference<>((float) 0);

         AtomicReference<Float> judgeScore = new AtomicReference<>((float) 0);

         AtomicReference<Float>  multipleScore = new AtomicReference<>((float) 0);


        testPaper.getChooseProblemList().forEach(
                problemVo -> {
                    if (problemVo.getProblemAnswer().equals(problemVo.getUserAnswers())) {
                        problemVo.setScore(Float.valueOf(generateTestPaper.getChooseScore()));
                        chooseScore.set(chooseScore.get() + Float.valueOf(generateTestPaper.getChooseScore()));
                    }
                }
        );
        testPaper.getJudgeProblemList().forEach(
                problemVo -> {
                    if (problemVo.getProblemAnswer().equals(problemVo.getUserAnswers())) {
                        problemVo.setScore(Float.valueOf(generateTestPaper.getJudgeScore()));
                        judgeScore.set(judgeScore.get() + Float.valueOf(generateTestPaper.getJudgeScore()));
                    }
                }
        );
        testPaper.getMultipleChoiceProblemList().forEach(
                problemVo -> {
                    if (problemVo.getProblemAnswer().equals(problemVo.getUserAnswers())) {
                        problemVo.setScore(Float.valueOf(generateTestPaper.getMultipleChoiceScore()));
                        multipleScore.set(multipleScore.get()+Float.valueOf(generateTestPaper.getMultipleChoiceScore()));
                    }
                }
        );
        testPaper.setChooseScore(chooseScore.get());
        testPaper.setMultipleScore(multipleScore.get());
        testPaper.setJudgeScore(judgeScore.get());
    }

    //市培训待审核
    @ApiOperation(value = "3 录入成绩后调用的接口", notes = "状态改为'市培训申请发证")
    @PostMapping("/gradesGrade")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity cityAudit(@ApiIgnore @AuthenticationPrincipal SecurityUser securityUser, @RequestBody GradeEntryVo gradeEntryVo) {
        TrainTheme trainTheme = trainThemeService.findById(gradeEntryVo.getTrainThemeId());
        trainTheme.setTrainPapersFiles(FilesUtil.stringFileToList(gradeEntryVo.getTrainPapersFileList()));
        TaskBto taskBto = trainTaskService.selectFatherIsNullAndBillidAndBillType(trainTheme.getTrainId(), BusinessEnum.TRAIN.id);
        //判断
        List<StatusEnum> statusEnums=new ArrayList<>();
        statusEnums.add(StatusEnum.TRAIN1004);
        statusEnums.add(StatusEnum.TRAIN1007);
        TaskDisposeUtil.isNotSubmit(taskBto.getBillStatus(),statusEnums);

        taskBto.setOwnUnit(1);
        taskService.moveToSpecial(taskBto, StatusEnum.TRAIN1006,0);
        gradeEntryVo.getGradeEntryList().forEach(
                gradeEntry -> {
                  TrainUser trainUser = trainUserDao.findByUserIdAndTrainId(gradeEntry.getUserId(),trainTheme.getTrainId());
                  trainUser.setAttendance(gradeEntry.getAttendance());
                  trainUser.setScore(gradeEntry.getScore());
                  trainUser.setEvaluation(gradeEntry.getEvaluation());
                  trainUser.setCertificate(gradeEntry.getCertificate());
//                  trainUserDao.save(trainUser);
                  saveTrainUser(trainUser);
                }
        );
        trainTheme.setTrainStatus(StatusEnum.TRAIN1006.id);
        trainTheme.setGood(gradeEntryVo.getGood());
        trainTheme.setPass(gradeEntryVo.getPass());
        if (gradeEntryVo.getTrainPapersFileList()!=null && gradeEntryVo.getTrainPapersFileList().size()!=0){
            trainTheme.setTrainPapersFiles(FilesUtil.stringFileToList(gradeEntryVo.getTrainPapersFileList()));
        }
        TaskLogBto taskLogBto = new TaskLogBto(taskBto.getId(), "申请发证", null);
        taskLogService.addLog(taskLogBto);
        return ResponseEntity.ok(trainThemeService.save(trainTheme));
    }


    @ApiOperation(value = "省培训发证审核以及市培训申请发证审核调用接口", notes = "同意培训完成")
    @PostMapping("/auditResult")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity gradeeEntry(@ApiIgnore @AuthenticationPrincipal SecurityUser securityUser, @RequestBody GradeEntryVo gradeEntryVo) {
        TrainTheme trainTheme = trainThemeService.findById(gradeEntryVo.getTrainThemeId());
        //给培训报名的人员都发起一个通知，查看自己都证书
        TaskBto taskBto = trainTaskService.selectFatherIsNullAndBillidAndBillType(trainTheme.getTrainId(), BusinessEnum.TRAIN.id);

        List<StatusEnum> statusEnums=new ArrayList<>();
        statusEnums.add(StatusEnum.TRAIN1006);
        statusEnums.add(StatusEnum.TRAIN1004);
        statusEnums.add(StatusEnum.TRAIN1007);
        TaskDisposeUtil.isNotSubmit(taskBto.getBillStatus(),statusEnums);
        //向专管员证书表中添加数据
        CompletableFuture.runAsync(()-> {
            log.info("[培训] 异步添加人员,证书以及人员日志");
                    if (gradeEntryVo.getIsCertificate() == 0) {
                        gradeEntryVo.getGradeEntryList().forEach(
                                gradeEntry -> {
                                    if (gradeEntry.getCertificate() == 0) {
                                        mgrcertService.save(gradeEntry.toDo());
                                        userLogService.save(new UserLog(gradeEntry.getUserId(), new Date(), "通过培训获得证书"));
                                    }
                                }
                        );
                    }
        });
        List<Integer> userIds= gradeEntryVo.getGradeEntryList().stream().map(GradeEntry::getUserId).collect(Collectors.toList());
        userService.updateUserTrainStatus(userIds,0);
        trainTheme.setTrainPapersFiles(FilesUtil.stringFileToList(gradeEntryVo.getTrainPapersFileList()));
        trainTheme.setTrainDataFiles(FilesUtil.stringFileToList(gradeEntryVo.getTrainDataFileList()));
        taskService.moveToEnd(taskBto);
        trainTheme.setTrainStatus(StatusEnum.END.id);
        gradeEntryVo.getGradeEntryList().forEach(
                gradeEntry -> {
                    TrainUser trainUser = trainUserDao.findByUserIdAndTrainId(gradeEntry.getUserId(),trainTheme.getTrainId());
                    trainUser.setAttendance(gradeEntry.getAttendance());
                    trainUser.setScore(gradeEntry.getScore());
                    trainUser.setEvaluation(gradeEntry.getEvaluation());
                    trainUser.setCertificate(gradeEntry.getCertificate());
                    saveTrainUser(trainUser);
                }
        );
        trainTheme.setPass(gradeEntryVo.getPass());
        trainTheme.setGood(gradeEntryVo.getGood());
        trainTheme.setIsCertificate(gradeEntryVo.getIsCertificate());
        //
        if (trainTheme.getTrainType()==0) {
            trainTaskService.selectBillidAndBillType(gradeEntryVo.getTrainThemeId(), BusinessEnum.TRAIN_STUDY.id, StatusEnum.TRAIN1013.id).forEach(
                    taskBto1 -> {
                        taskService.moveToSpecial(taskBto1, StatusEnum.TRAIN1009,taskBto1.getInvolveUserIdList().get(0));
                    }
            );
        }else {
            gradeEntryVo.getGradeEntryList().forEach(
                    gradeEntry -> {
                        onlineLearningTaskCheck(trainTheme.getTrainId(),taskBto.getId(),trainTheme.getName(),gradeEntry.getUserId(),0);
                    }
            );
        }
        trainThemeService.save(trainTheme);
        TaskLogBto taskLogBto = new TaskLogBto(taskBto.getId(), "审核通过", null);
        taskLogService.addLog(taskLogBto);
        return ResponseEntity.ok(trainTheme);
        //修改业务都状态
    }

    /**
     * 成绩查看确认
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation(value = "中止培训业务")
    @GetMapping("/suspendTrain/{taskId}/{trainId}")
    public ResponseEntity suspendTrain(@ApiIgnore @AuthenticationPrincipal SecurityUser securityUser, @PathVariable Integer taskId, @PathVariable Integer trainId) {
        TrainTheme trainTheme = trainThemeService.findById(trainId);
        trainTheme.setDeleteTag(1);
        trainThemeService.save(trainTheme);
        TaskBto taskBto= taskService.findBillIdAndBusinessTypeNotBillStatus(trainTheme.getTrainId(),BusinessEnum.TRAIN.id).get().parse2Bto();
        taskService.moveToArchive(taskBto);
        taskService.findByBillIdAndBusinessType(trainId,BusinessEnum.TRAIN_SIGN_UP.id).stream().map(Task::parse2Bto).forEach(
                taskBto1 -> taskService.moveToArchive(taskBto1)
        );
        List<TrainUnit> trainUnits = trainUnitDao.findAllByTrainId(trainTheme.getTrainId()).stream().filter(trainUnit -> trainUnit.getSubmitStatus()!=1).collect(Collectors.toList());
        //已报名阅知用户
        List<Integer> userIds=new ArrayList<>();
        if (trainUnits.size()>0){
            trainUnits.forEach(
                    trainUnit -> userIds.addAll(trainUserDao.findAllByUnitsIdAndTrainId(trainUnit.getUnitId(),trainId).stream().filter(trainUser -> trainUser.getIsSignUp()==1).map(TrainUser::getUserId).collect(Collectors.toList()))
            );
        }
        messageService.add(new MessageBto(0, BusinessEnum.TRAIN.id, securityUser.getCurrentUserInfo().getName()+"终止了["+trainTheme.getName()+"]培训业务,本次培训作废", userIds, trainTheme.getTrainId().toString()));
        //查询所有的task 同送至中止
        //查询出所有以报名的单位人员
        //给人员推送阅知
        return ResponseEntity.ok(trainTheme);
    }

    /**
     * 成绩查看确认
     *
     * @param signUpReturn
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation(value = "end。成绩查看确认接口")
    @PostMapping("/resultsConfirm")
    public ResponseEntity resultsConfirm(@ApiIgnore @AuthenticationPrincipal SecurityUser securityUser, @RequestBody signUpReturn signUpReturn) {
        TrainTheme trainTheme = trainThemeService.findById(signUpReturn.getTrainThemeId());
        //给培训报名的人员都发起一个通知，查看自己都证书
        TaskBto taskBto = taskService.get(signUpReturn.getTaskId());
        taskService.moveToEnd(taskBto);
        return ResponseEntity.ok(true);
    }

    @ApiOperation(value = "报名页面和确认页面接口，查看成绩页面接口")
    @GetMapping("/train/{trainId}")
    public ResponseEntity resultsConfirm(@ApiIgnore @AuthenticationPrincipal SecurityUser securityUser, @PathVariable Integer trainId) {
        return ResponseEntity.ok(trainThemeService.findByTrainingPeople(trainId, securityUser.getCurrentUserInfo().getUserId()));
    }

    @ApiOperation(value = "成绩确认页面接口，查看成绩页面接口")
    @GetMapping("/train/check/{trainId}")
    public ResponseEntity resultsConfirmCheck(@ApiIgnore @AuthenticationPrincipal SecurityUser securityUser, @PathVariable Integer trainId) {
        return ResponseEntity.ok(trainThemeService.findByTrainingPeople(trainId, securityUser.getCurrentUserInfo().getUserId()));
    }

    @ApiOperation(value = "报名中请求的详情接口")
    @GetMapping("/trainRegistration/{trainId}")
    public ResponseEntity TrainRegistrationVo(@ApiIgnore @AuthenticationPrincipal SecurityUser securityUser, @PathVariable Integer trainId) {
        return ResponseEntity.ok(trainThemeService.findRegistrationVo(trainId));
    }

    @ApiOperation(value = "培训中请求接口请求的详情接口")
    @GetMapping("/trainTrainingVo/{trainId}")
    public ResponseEntity TrainTrainingVo(@ApiIgnore @AuthenticationPrincipal SecurityUser securityUser, @PathVariable Integer trainId) {
        return ResponseEntity.ok(trainThemeService.findTrainTrainingVo(trainId));
    }

    @ApiOperation(value = "审核请求的详情接口")
    @GetMapping("/trainAuditVo/{trainId}")
    public ResponseEntity TrainAuditVo(@ApiIgnore @AuthenticationPrincipal SecurityUser securityUser, @PathVariable Integer trainId) {
        return ResponseEntity.ok(trainThemeService.findTrainAuditVo(trainId));
    }

    @ApiOperation(value = "培训修改接口")
    @PostMapping("/trainUpdateVo")
    public ResponseEntity TrainRegistrationVo(@ApiIgnore @AuthenticationPrincipal SecurityUser securityUser, @RequestBody TrainUpdateVo trainUpdateVo) {
        return ResponseEntity.ok(trainThemeService.updateTrain(trainUpdateVo));
    }

    @ApiOperation(value = "培训详情接口查询")
    @GetMapping("/details/{trainId}")
    public ResponseEntity details(@ApiIgnore @AuthenticationPrincipal SecurityUser securityUser, @PathVariable Integer trainId) {
        return ResponseEntity.ok(trainThemeService.findSelectDetailsVo(trainId));
    }

   private TrainUser userToTrainUser(User user){
       ModelMapper mapper = BeanHelper.getUserMapper();
       return mapper.map(user,TrainUser.class);
   }

   private void saveTrainUser(TrainUser trainUser){
            TrainUser trainUser1 = trainUserDao.save(trainUser);
            //异步线程
            CompletableFuture.runAsync(()-> {
            BcHash bcHash = blockChainUtil.sendHash(1000, JacksonUtil.toJSon(trainUser1));
            trainUserDao.upDate(bcHash.getData().getRecordID(),trainUser1.getId());
            });
    }

    /**
     * 线上培训业务  线上学习任务生成
     */
    private TaskBto onlineLearningTask(Integer trainId, Integer parentTaskId,String title,Integer userId,Integer ownUnitId){
        List<Integer> list=new ArrayList<>();
        list.add(userId);
        TaskBto taskBto =  new TaskBto(StatusEnum.TRAIN1012.id,title , parentTaskId, ".", trainId, BusinessEnum.TRAIN_STUDY.id, ownUnitId, 0, "online", list);
        taskBto.setCreateUserId(userId);
        return taskService.start(taskBto);
    }

    /**
     * 线上培训业务  线上学习任务生成 成绩确认
     */
    private TaskBto onlineLearningTaskCheck(Integer trainId, Integer parentTaskId,String title,Integer userId,Integer ownUnitId){
        List<Integer> list=new ArrayList<>();
        list.add(userId);
        TaskBto taskBto=  new TaskBto(StatusEnum.TRAIN1009.id,title , parentTaskId, ".", trainId, BusinessEnum.TRAIN_STUDY.id, ownUnitId, 0, "online", list);
        return taskService.start(taskBto);
    }
}
