package com.rf.psychological.plan.rest;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.rf.psychological.base.rest.BaseController;
import com.rf.psychological.dao.dto.InstitutionAuthSubjectNameDto;
import com.rf.psychological.dao.model.CognitiveTaskEntity;
import com.rf.psychological.scale.dao.model.SubjectEntity;
import com.rf.psychological.scale.dao.model.UserRecordEntity;
import com.rf.psychological.scale.service.UserRecordService;
import com.rf.psychological.user.dao.model.UserEntity;
import com.rf.psychological.group.service.GroupInfoService;
import com.rf.psychological.opLog.annotation.OperationLogAnnotation;
import com.rf.psychological.plan.dao.dto.*;
import com.rf.psychological.plan.dao.model.*;
import com.rf.psychological.plan.service.*;
import com.rf.psychological.scale.service.CognitiveTaskService;
import com.rf.psychological.security.AesEncryptUtils;
import com.rf.psychological.security.SafetyProcess;
import com.rf.psychological.scale.service.SubjectService;
import com.rf.psychological.user.service.UserService;
import com.rf.psychological.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lpf
 * @description:
 * @date 2022/1/615:16
 */
@Slf4j
@RestController
@RequestMapping("/testPlan")
@Api(tags = "预约测试计划管理")
public class TestPlanController extends BaseController {

    @Autowired
    private UserRecordService userRecordService;

    @Autowired
    private TestPlanService testPlanService;

    @Autowired
    private TestPlanContendService testPlanContendService;

    @Autowired
    private TestPlanUserService testPlanUserService;

    @Autowired
    private CognitiveTaskService cognitiveTaskService;

    @Autowired
    private SubjectService subjectService;

    @Autowired
    private UserService userService;

    @Autowired
    private PlanGroupService planGroupService;

    @Autowired
    private GroupInfoService groupInfoService;

    @Autowired
    private HisTestPlanService hisTestPlanService;
    @SafetyProcess
    @GetMapping("/institution")
    @ApiOperation("查询测试计划")
    public Result getInfoByInstitutionNo(String institutionNo, String searchKey, String beginTime, String endTime, String status, int beginNum, int pageSize) throws ParseException {
        if (pageSize == 0) {
            pageSize = 20;
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date beginDate = null;
        Date endDate = null;
        if(StringUtils.isNotEmpty(beginTime) && StringUtils.isNotEmpty(endTime)){
            beginDate = simpleDateFormat.parse(beginTime);
            endDate = simpleDateFormat.parse(endTime);
        }
        Page<TestPlanEntity> allByInstitutionNo = this.testPlanService.findAllByInstitutionNo(institutionNo, searchKey, beginDate, endDate, status, beginNum, pageSize);
        List<TestPlanEntity> testPlanEntityList = allByInstitutionNo.getContent();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("testPlanEntities", testPlanEntityList);
        jsonObject.put("num", allByInstitutionNo.getTotalElements());
        return success(jsonObject);
    }

    /**
     * @param userId 用户编号
     * @param planName 计划名称
     * @param beginTime 查询起始时间
     * @param endTime 查询截止时间
     * @param isComplete 完成状态：0未完成 9已完成
     * @param status 测试计划状态
     * @param beginNum 分页参数，当前页码
     * @param pageSize 分页参数 页容量
     * @return
     */
    @SafetyProcess
    @GetMapping("/user/plan")
    @ApiOperation("用户的预约计划")
    public Result getInfoInUser(String userId, String planName, String beginTime, String endTime, String isComplete, String status, int beginNum, int pageSize) {
        if (pageSize == 0) {
            pageSize = 20;
        }
        if (isComplete == null || status == null) {
            return fail("参数为空");
        }
        Date beginDate, endDate;
        try {
            beginDate = Utils.date2time(beginTime, Constant.DATE_TRANS_FLAG_START);
            endDate = Utils.date2time(endTime,Constant.DATE_TRANS_FLAG_END);
        } catch (ParseException e) {
            log.error("日期格式转换错误："+e.getLocalizedMessage());
            e.printStackTrace();
            return fail(HttpStatus.SERVER_EXCEPTION,null,"服务器内部错误");
        }
        //得到该用户下有哪些测试计划编号
        List<TestPlanUserEntity> testPlanByUId = this.testPlanUserService.findTestPlanByUId(userId, beginNum, pageSize,status, isComplete);
        List<TestPlanUserDto> testPlanInUser = testPlanService.getTestPlanInUser(testPlanByUId, planName, beginDate, endDate, userId, status);
        List<TestPlanUserDto> collect;
        //已完成
        if(status.isEmpty()){
            collect = testPlanInUser.stream()
                    .filter(testPlanUserDto -> Objects.equals(testPlanUserDto.getCompleteNum(), testPlanUserDto.getAllContendsNum()))
                    .collect(Collectors.toList());
        }else{
            collect = testPlanInUser.stream()
                    .filter(testPlanUserDto -> isComplete.equals(testPlanUserDto.getIsComplete()))
                    .collect(Collectors.toList());
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("testPlanEntities", collect);
        jsonObject.put("num", collect.size());
        return success(jsonObject);
    }

    /**
     * 查看测试计划没有添加的量表或认知任务
     *
     * @return
     */
    @SafetyProcess
    @PostMapping("/getNoAuth")
    @ApiOperation("查看测试计划没有的量表或认知任务")
    public Result getInstitutionAuth(@RequestBody String json) throws Exception {
        String data = AesEncryptUtils.decrypt(JSONObject.parseObject(json).getString("data"));
        System.out.println("data=====:" + data);
        try {
            JSONObject jsonObject = JSONObject.parseObject(data);
            if (!jsonObject.containsKey("testPlanId") || jsonObject.get("testPlanId").equals("")) {
                return fail("", "测试计划编号为空");
            }
            int pageNum =  jsonObject.getInteger("pageNum");
            int pageSize =  jsonObject.getInteger("pageSize");
            String institutionNo = jsonObject.getString("institutionNo");
            String type = jsonObject.getString("type");
            String searchKey = jsonObject.getString("searchKey");
            String testPlanId = jsonObject.getString("testPlanId");
            String categoryName = jsonObject.getString("categoryEname");
            JSONObject result = new JSONObject();
            if (type.equals(Constant.MAGIC_NUM_0)) {
                Page<InstitutionAuthSubjectNameDto> testPlanNoSubTask = this.testPlanContendService.getTestPlanNoSubTask(institutionNo, type, searchKey, testPlanId, pageNum, pageSize,categoryName);
                result.put("data", testPlanNoSubTask.getContent());
                result.put("allNum", testPlanNoSubTask.getTotalElements());
            }
            if (type.equals(Constant.MAGIC_NUM_1)) {
                Page<TestPlanAuthConTaskDto> testPlanNoConTask = this.testPlanContendService.getTestPlanNoConTask(institutionNo, type, searchKey, testPlanId, pageNum, pageSize,categoryName);
                result.put("data", testPlanNoConTask.getContent());
                result.put("allNum", testPlanNoConTask.getTotalElements());
            }
            return success(result, "查询成功");
        } catch (Exception exception) {
            log.error("系统内部错误：");
            exception.printStackTrace();
            return fail();
        }
    }

    /**
     * 查看测试计划没有的用户
     *
     * @return
     */
    @SafetyProcess
    @GetMapping("/getNoUser")
    @ApiOperation("查看测试计划没有的用户")
    public Result getNoUser(String institutionNo, String searchKey, @RequestParam("testPlanId") String testPlanId, int beginNum, int pageSize) throws Exception {
        if (pageSize == 0) {
            pageSize = 10;
        }
        if (institutionNo.equals("") || testPlanId.equals("")) {
            return fail("", "参数不全");
        }
        Page<UserEntity> userNoTestPlan = userService.findUserNoTestPlan(institutionNo, testPlanId, searchKey, beginNum, pageSize);
        JSONObject result = new JSONObject();
        result.put("userEntities", userNoTestPlan.getContent());
        result.put("num", userNoTestPlan.getTotalElements());
        try {
            return success(result, "查询成功");
        } catch (Exception exception) {
            exception.printStackTrace();
            return fail("", "查询失败，" + exception.toString());
        }
    }

    /**
     * @param testPlanId
     * @param searchKey
     * @param beginNum
     * @param pageSize
     * @return
     */
    @SafetyProcess
    @GetMapping("/user")
    @ApiOperation("查询测试计划中用户信息")
    public Result getInfoInUser(String testPlanId, String searchKey, int beginNum, int pageSize) {
        if (pageSize == 0) {
            pageSize = 20;
        }
        //查询该测试计划下有哪些用户
        Page<TestPlanUserEntity> testPlanUserByTestId = this.testPlanUserService.findTestPlanUserByTestId(testPlanId, searchKey, beginNum, pageSize);
        List<UserEntity> userEntities = new ArrayList<>();
        if(testPlanUserByTestId.getTotalElements()>0){
            testPlanUserByTestId.getContent().forEach(testPlanUserEntity -> {
                UserEntity userEntity = this.userService.getOne(testPlanUserEntity.getUId());
                if(userEntity != null ){
                    userEntities.add(userEntity);
                }
            });
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("data", userEntities);
        jsonObject.put("num", testPlanUserByTestId.getTotalElements());
        return success(jsonObject);
    }

    @SafetyProcess
    @GetMapping("/contend/info")
    @ApiOperation("预约计划里面的具体量表认知任务信息")
    public Result getContendInfo(String testPlanId, String type, int beginNum, int pageSize) {
        if (pageSize == 0) {
            pageSize = 20;
        }
        Page<TestPlanContendEntity> testPlanContendEntitiesByTestPlanId = testPlanContendService.findTestPlanContendEntitiesByTestPlanId(testPlanId, type, beginNum, pageSize);
        List<TestPlanContendEntity> contentList = testPlanContendEntitiesByTestPlanId.getContent();
        ArrayList<CognitiveTaskEntity> cognitiveTaskEntities = new ArrayList<>();
        ArrayList<SubjectEntity> subjectEntities = new ArrayList<>();
        for (TestPlanContendEntity testPlanContendEntity : contentList) {
            if (type.equals(Constant.MAGIC_NUM_1)) {
                Optional<CognitiveTaskEntity> allById = cognitiveTaskService.getAllById(testPlanContendEntity.getTestId());
                allById.ifPresent(cognitiveTaskEntities::add);
            } else if (type.equals(Constant.MAGIC_NUM_0)) {
                Optional<SubjectEntity> byId = subjectService.findById(testPlanContendEntity.getTestId());
                byId.ifPresent(subjectEntities::add);
            }
        }
        JSONObject jsonObject = new JSONObject();
        if (type.equals(Constant.MAGIC_NUM_1)) {
            jsonObject.put("data", cognitiveTaskEntities);
        } else if (type.equals(Constant.MAGIC_NUM_0)) {
            jsonObject.put("data", subjectEntities);
        }
        jsonObject.put("num", testPlanContendEntitiesByTestPlanId.getTotalElements());
        return success(jsonObject);
    }

    @SafetyProcess
    @GetMapping("/user/contend/info")
    @ApiOperation("用户界面预约计划的具体量表认知任务信息")
    public Result getContendInfoInUserPage(String testPlanId, String phone, String institutionNo) {
        //查询用户的预约计划是否超时，如果超时或者失效不允许打开
        TestPlanEntity testPlanEntityById = this.testPlanService.findById(testPlanId);
        if (testPlanEntityById.getStatus() == Constant.TEST_PLAN_STATUS_UNSTART) {
            return fail("", "测试计划还未开始");
        }
        if (testPlanEntityById.getStatus() == Constant.TEST_PLAN_STATUS_END || testPlanEntityById.getStatus() == Constant.TEST_PLAN_STATUS_STOP) {
            return fail("", "测试计划已关闭");
        }
        ArrayList<TestPlanUserContendDto> testPlanUserContendDtos = new ArrayList<>();
        //查看该用户下(已经完成的量表和认知任务)
        List<TestPlanContendEntity> userDoTestPlanContend = testPlanContendService.getUserDoTestPlanContend(institutionNo, phone, testPlanId);
        for (TestPlanContendEntity testPlanContendEntity : userDoTestPlanContend) {
            TestPlanUserContendDto testPlanUserContendDto = new TestPlanUserContendDto();
            BeanUtils.copyProperties(testPlanContendEntity, testPlanUserContendDto);
            if (testPlanContendEntity.getType().equals("0")){
                SubjectEntity subjectEntity = this.subjectService.getSubjectEntityByFlag(testPlanContendEntity.getFlag());
                testPlanUserContendDto.setStatus(subjectEntity.getStatus());
                testPlanUserContendDto.setMobileStatus(Constant.DEFAULT_VALUE_ONE);
                testPlanUserContendDto.setReportVersion(subjectEntity.getReportVersion());
            }else {
                CognitiveTaskEntity cognitiveTaskEntity = this.cognitiveTaskService.getCognizeListByTaskCode(testPlanContendEntity.getFlag());
                testPlanUserContendDto.setStatus(cognitiveTaskEntity.getStatus());
                testPlanUserContendDto.setMobileStatus(cognitiveTaskEntity.getMobileStatus());
                testPlanUserContendDto.setReportVersion(Integer.parseInt(cognitiveTaskEntity.getReportVersion()));
                if (testPlanContendEntity.getFlag().equals("RHYTHM")){
                    UserRecordEntity userRecordEntity = this.userRecordService.getRHYTHM(phone, institutionNo, testPlanId);
                    if (userRecordEntity != null && userRecordEntity.getImg().equals("27")) {

                    }else {
                        testPlanUserContendDto.setIsComplete(Constant.USER_PLAN_STATUS_UNCOMPLETED);
                        testPlanUserContendDtos.add(testPlanUserContendDto);
                        continue;
                    }
                }
            }

            testPlanUserContendDto.setIsComplete(Constant.USER_PLAN_STATUS_COMPLETED);
            testPlanUserContendDtos.add(testPlanUserContendDto);
        }
        //查看该用户下某一测试计划中还有哪些认知任务或者量表存在(未完成的量表和认知任务)
        List<TestPlanContendEntity> userNoDoTestPlanContend = testPlanContendService.getUserNoDoTestPlanContend(institutionNo, phone, testPlanId);
        for (TestPlanContendEntity testPlanContendEntity : userNoDoTestPlanContend) {
            TestPlanUserContendDto testPlanUserContendDto = new TestPlanUserContendDto();
            BeanUtils.copyProperties(testPlanContendEntity, testPlanUserContendDto);
            if (testPlanContendEntity.getType().equals("0")){
                SubjectEntity subjectEntity = this.subjectService.getSubjectEntityByFlag(testPlanContendEntity.getFlag());
                testPlanUserContendDto.setStatus(subjectEntity.getStatus());
                testPlanUserContendDto.setMobileStatus(Constant.DEFAULT_VALUE_ONE);
                testPlanUserContendDto.setReportVersion(subjectEntity.getReportVersion());
            }else {
                CognitiveTaskEntity cognitiveTaskEntity = this.cognitiveTaskService.getCognizeListByTaskCode(testPlanContendEntity.getFlag());
                testPlanUserContendDto.setStatus(cognitiveTaskEntity.getStatus());
                testPlanUserContendDto.setMobileStatus(cognitiveTaskEntity.getMobileStatus());
                testPlanUserContendDto.setReportVersion(Integer.parseInt(cognitiveTaskEntity.getReportVersion()));
            }
            testPlanUserContendDto.setIsComplete(Constant.USER_PLAN_STATUS_UNCOMPLETED);
            testPlanUserContendDtos.add(testPlanUserContendDto);
        }

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("data", testPlanUserContendDtos);
        return success(jsonObject);
    }

    @SafetyProcess
    @PostMapping("/save")
    @OperationLogAnnotation
    @ApiOperation("添加测试预约计划")
    public Result saveTestPlan(@RequestBody String json) {
        try {
            String data = AesEncryptUtils.decrypt(JSONObject.parseObject(json).getString("data"));
            JSONObject jsonObject = JSONObject.parseObject(data);
            TestPlanEntity testPlanEntity = jsonObject.toJavaObject(TestPlanEntity.class);
            if (testPlanEntity.getTestBeginTime().after(testPlanEntity.getTestEndTime())) {
                return fail("测试开始时间晚于测试结束时间");
            }
            //时间检测，测试计划开始时间不能小于当前时间，时间误差一分钟
            long beginTimeStamp = testPlanEntity.getTestBeginTime().getTime()/1000/60;
            long nowTimeStamp = System.currentTimeMillis()/1000/60;
            if(nowTimeStamp-beginTimeStamp > 1){
                return fail("开始时间早于当前时间，不合法");
            }
            testPlanEntity.setStatus(Constant.TEST_PLAN_STATUS_UNSTART);
            if(AssertUtils.isEmpty(testPlanEntity.getName())){
                return failBadRequest("测试计划名称为空");
            }
            if(AssertUtils.isEmpty(testPlanEntity.getInstitutionNo())){
                return failBadRequest("测试计划机构编号为空");
            }
            testPlanEntity.setCreateTime(new Date());
            testPlanEntity.setUpdateTime(new Date());
            this.testPlanService.save(testPlanEntity);

        } catch (Exception e) {
            e.printStackTrace();
            return fail("保存失败，请联系管理员");
        }
        return success();
    }

    @SafetyProcess
    @OperationLogAnnotation(value = "保存预约计划里面的详细内容")
    @PostMapping("/saveContends")
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation("保存预约计划里面的详细内容(testId：量表或认知任务id，type:0---量表 1---认知任务，testPlanId:测试计划id)")
    public Result saveTestPlanContend(@RequestBody String json) throws Exception {
        String data = AesEncryptUtils.decrypt(JSONObject.parseObject(json).getString("data"));
        JSONArray jsonObject = JSONArray.parseArray(data);
        List<TestPlanContendEntity> contendList = jsonObject.toJavaList(TestPlanContendEntity.class);
        String testPlanId = null;
        try {
            if(contendList != null && contendList.size()>0){
                for (TestPlanContendEntity entity:contendList) {
                    if (testPlanId == null) {
                        testPlanId = entity.getTestPlanId();
                        //校验测试计划状态：未开始或进行中的测试计划可以新增
                        int status  = this.testPlanService.findById(testPlanId).getStatus();
                        if(status!= Constant.TEST_PLAN_STATUS_UNSTART && status!= Constant.TEST_PLAN_STATUS_RUNNING){
                            return fail("当前测试计划"+(status == Constant.TEST_PLAN_STATUS_END?"已结束":"已关闭")+"不能增加测试任务");
                        }
                    }
                    entity.setCreateTime(new Date());
                    entity.setUpdateTime(new Date());
                }

            }
            this.testPlanContendService.saveInBatch(contendList);
            //如果有新添加的测试计划，将该测试计划下的所有用户变为未完成状态
            if (jsonObject.size() > 0) {
                testPlanUserService.updateIsComplete(testPlanId, Constant.TEST_PLAN_USER_STATUS_UNCOMPLETE);
            }
            return success();
        } catch (Exception e) {
            e.printStackTrace();
            return fail("", "保存失败，请联系管理员");
        }
    }

    @SafetyProcess
    @OperationLogAnnotation
    @PostMapping("/saveUser")
    @ApiOperation("添加预约计划里面的用户(uId：用户id，testPlanId:测试计划id)")
    public Result saveUser(@RequestBody String json) throws Exception {
        String data = AesEncryptUtils.decrypt(JSONObject.parseObject(json).getString("data"));
        List<TestPlanUserEntity> testPlanUserEntityList = JSONArray.parseArray(data).toJavaList(TestPlanUserEntity.class);
        if(testPlanUserEntityList!= null &&testPlanUserEntityList.size()>0){
            for (TestPlanUserEntity testPlanUserEntity:testPlanUserEntityList) {
                Optional<TestPlanUserEntity> testPlanUserByTestIdAndUserId = testPlanUserService.findTestPlanUserByTestIdAndUserId(testPlanUserEntity.getTestPlanId(), testPlanUserEntity.getUId());
                if (testPlanUserByTestIdAndUserId.isPresent()) {
                    UserEntity one = userService.findOne(testPlanUserByTestIdAndUserId.get().getUId());
                    if (one != null) {
                        return fail("用户:" + one.getPhone() + "已存在测试计划内，请重新选择");
                    } else {
                        return fail("不存在用户id:" + testPlanUserByTestIdAndUserId.get().getUId());
                    }
                }
                testPlanUserEntity.setCreateTime(LocalDateTime.now());
                testPlanUserEntity.setUpdateTime(LocalDateTime.now());
            }
            this.testPlanUserService.saveInBatch(testPlanUserEntityList);
        }
        return success();
    }

    @SafetyProcess
    @OperationLogAnnotation
    @PostMapping("/saveUserByGroup")
    @ApiOperation("通过分组添加预约计划里面的用户(groupId：分组id，testPlanId:测试计划id")
    public Result saveUserByGroup(@RequestBody String json) throws Exception {
        String data = AesEncryptUtils.decrypt(JSONObject.parseObject(json).getString("data"));
        JSONArray jsonArrays = JSONObject.parseArray(data);
        return testPlanUserService.saveByGroup(jsonArrays);
    }

    @SafetyProcess
    @OperationLogAnnotation
    @PostMapping("/changeStatus")
    @ApiOperation("更改预约计划状态")
    public Result changeTestPlanStatus(@RequestBody String json) throws Exception {

        String data = AesEncryptUtils.decrypt(JSONObject.parseObject(json).getString("data"));
        System.out.println(data);
        JSONObject jsonObject = JSONObject.parseObject(data);

        String status = (String) jsonObject.get("status");
        String id = (String) jsonObject.get("id");

        if (status.equals("") || id.equals("")) {
            return fail("", "信息不完整");
        }
        try {
            this.testPlanService.updateStatus(id, Integer.parseInt(status));
            return success();
        } catch (Exception e) {
            e.printStackTrace();
            return fail("", "更改失败，请联系管理员");
        }
    }

    @SafetyProcess
    @OperationLogAnnotation
    @PostMapping("/changeInfo")
    @ApiOperation("更改信息")
    public Result changeTestPlanInfo(@RequestBody String json) throws Exception {

        String data = AesEncryptUtils.decrypt(JSONObject.parseObject(json).getString("data"));
        System.out.println(data);
        JSONObject jsonObject = JSONObject.parseObject(data);
        String name =  jsonObject.getString("name");
        String testBeginTime =  jsonObject.getString("testBeginTime");
        String testEndTime =  jsonObject.getString("testEndTime");
        String id = jsonObject.getString("id");
        Integer status = jsonObject.getInteger("status");
        if (name.equals("") || id.equals("") || testBeginTime.equals("") || testEndTime.equals("")) {
            return failBadRequest();
        }
        Date beginDate, endDate;
        //格式化为数据库的时间样式
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            beginDate = simpleDateFormat.parse(testBeginTime);
            endDate = simpleDateFormat.parse(testEndTime);
        } catch (ParseException e) {
            e.printStackTrace();
            return fail("", "时间格式有误请联系管理员");
        }
        if (beginDate.after(endDate)) {
            return fail("测试开始时间晚于测试结束时间");
        }
        TestPlanEntity planEntity = this.testPlanService.findById(id);

//        未开始和正在使用状态可以修改状态且只能将状态修改为手动关闭状态

        if(status!=planEntity.getStatus() && status != Constant.TEST_PLAN_STATUS_STOP){
            return fail("状态不合法");
        }

        //手动关闭之后，将计划移动到历史计划
        if(status == Constant.TEST_PLAN_STATUS_STOP){
            HisTestPlanEntry hisTestPlanEntry = new HisTestPlanEntry(planEntity);
            hisTestPlanEntry.setStatus(Constant.TEST_PLAN_STATUS_STOP);
            this.testPlanService.deleteById(planEntity.getId());
            this.hisTestPlanService.save(hisTestPlanEntry);
            return success();
        }
        //进行中的状态只能修改测试计划结束时间和状态，且结束时间不能早于当前时间
        if(planEntity.getStatus() == Constant.TEST_PLAN_STATUS_RUNNING){
            //修改后的结束日期在当前日期之前
            if (endDate.before(new Date())) {
                return fail("结束时间早于当前时间，无效");
            }
        }
        //未开始状态下可修改所有信息，但是开始时间和结束时间不能小于当前时间
        if(planEntity.getStatus() == Constant.TEST_PLAN_STATUS_UNSTART){
            //修改后的起始日期在当前日期之后
            if (beginDate.before(new Date())) {
                return fail("开始时间早于当前时间，无效");
            }
            //修改后的结束日期在当前日期之前
            if (endDate.before(new Date())) {
                return fail("结束时间早于当前时间，无效");
            }
        }
        try {
            this.testPlanService.updateInfo(id, name, beginDate, endDate);
            return success();
        } catch (Exception e) {
            e.printStackTrace();
            return fail("", "更改失败，请联系管理员");
        }
    }

    @SafetyProcess
    @OperationLogAnnotation
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/deTestPlanContend")
    @ApiOperation("删除测试计划内的详细内容")
    public Result deTestPlanContend(@RequestBody String json) throws Exception {
        String data = AesEncryptUtils.decrypt(JSONObject.parseObject(json).getString("data"));
        JSONArray objects = JSON.parseArray(data);
        try {
            for (Object object : objects) {
                JSONObject jsonObject = (JSONObject) object;
                //量表或者认知任务id
                String testId = jsonObject.getString("id");
                //测试计划的id
                String testPlanId = jsonObject.getString("testPlanId");
                String message = checkPlanStatus(testPlanId);
                if(message != null){
                    return fail(message);
                }
                //删除该测试计划下的某一量表或认知任务id
                testPlanContendService.deleteByTestIdAndTestPlanId(testId, testPlanId);
            }
            return success();
        } catch (Exception e) {
            e.printStackTrace();
            return fail("", "删除失败，请联系管理员");
        }
    }

    @SafetyProcess
    @OperationLogAnnotation
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/deTestPlanUser")
    @ApiOperation("删除预约计划内的用户信息")
    public Result deTestPlanUser(@RequestBody String json) throws Exception {
        String data = AesEncryptUtils.decrypt(JSONObject.parseObject(json).getString("data"));
        JSONArray objects = JSON.parseArray(data);
        try {
            for (Object object : objects) {
                JSONObject jsonObject = (JSONObject) object;
                String uId = jsonObject.getString("id");
                String testPlanId = jsonObject.getString("testPlanId");
                String message = checkPlanStatus(testPlanId);
                if(message != null){
                    return fail(message);
                }
                //删除该测试计划下的某一用户
                testPlanUserService.deleteByUIdAndTestPlanId(uId, testPlanId);
            }
            return success();
        } catch (Exception e) {
            e.printStackTrace();
            return fail("", "删除失败，请联系管理员");
        }
    }
    private String  checkPlanStatus(String testPlanId){
        String message = null;
        TestPlanEntity testPlanEntity = this.testPlanService.findById(testPlanId);
        if(testPlanEntity == null){
            message = "测试计划不存在";
        }else{
            if(testPlanEntity.getStatus() != Constant.TEST_PLAN_STATUS_UNSTART){
                message =  "测试计划"+testPlanEntity.getName()+"当前状态不允许修改";
            }
        }
        return message;
    }
    @SafetyProcess
    @OperationLogAnnotation
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/deTestPlan")
    @ApiOperation("删除预约计划,会将预约计划中的详细内容一并删除")
    public Result deTestPlan(@RequestBody String json) throws Exception {
        String data = AesEncryptUtils.decrypt(JSONObject.parseObject(json).getString("data"));
        JSONArray objects = JSON.parseArray(data);
        try {
            for (int i = 0; i < objects.size(); i++) {
                JSONObject jsonObject = objects.getJSONObject(i);
                String testPlanId = jsonObject.getString("id");
                String message = checkPlanStatus(testPlanId);
                if(StringUtils.isNotBlank(message)) return fail(message);
                //删除contend里面关于该测试计划的量表和认知任务
                testPlanContendService.deleteByTestPlanId(testPlanId);
                //删除测试计划用户里面的用户
                testPlanUserService.deleteAllByTestPlanId(testPlanId);
                //删除测试计划分组关联信息
                this.planGroupService.deleteByPlanId(testPlanId);
                //删除测试计划里面
                testPlanService.deleteById(testPlanId);
            }
            return success();
        } catch (Exception e) {
            e.printStackTrace();
            return fail("", "删除失败，请联系管理员");
        }
    }


    @SafetyProcess
    @GetMapping("/progress/contends")
    @ApiOperation("测试计划进度：内容维度")
    public Result contendsProgress(String testPlanId, @RequestParam(required = false, defaultValue = "1") Integer pageNo,
                                   @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
        List<TestPlanContendProgressDto> result = testPlanContendService.getTestPlanContendProgress(testPlanId);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("result", result.stream().skip((long) (pageNo - 1) * pageSize).limit(pageSize).
                collect(Collectors.toList()));
        jsonObject.put("num", result.size());
        return success(jsonObject);
    }


    @SafetyProcess
    @GetMapping("/progress/users")
    @ApiOperation("测试计划进度：用户维度")
    public Result usersProgress(String testPlanId, @RequestParam(required = false, defaultValue = "1") Integer pageNo,
                                @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
        List<TestPlanUserProgressDto> result = testPlanContendService.getTestPlanUsersProgress(testPlanId);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("result", result.stream().skip((long) (pageNo - 1) * pageSize).limit(pageSize).
                collect(Collectors.toList()));
        jsonObject.put("num", result.size());
        return success(jsonObject);
    }

    @SafetyProcess
    @GetMapping("/info/subCog")
    @ApiOperation("查看量表和认知任务信息")
    public Result getSubCogInfo(String flag, String type) {
        return testPlanService.getSubCogInfo(flag, type);
    }


    /**
     * 保存测试计划基本信息
     * @return
     */
    @SafetyProcess
    @GetMapping("/save/plan")
    @ApiOperation("保存测试计划基本信息")
    public Result savePlanInfo(@RequestBody String json) throws Exception {

        JSONObject jsonObject = JSONObject.parseObject(AesEncryptUtils.decrypt(JSONObject.parseObject(json).getString("data")));
        TestPlanEntity testPlanEntity = JSONObject.toJavaObject(jsonObject, TestPlanEntity.class);
        if(testPlanEntity.getTestEndTime().before(new Date())){
            return fail("测试计划结束时间不能早于当前时间");
        }

        TestPlanEntity entity = this.testPlanService.findById(testPlanEntity.getId());
        if(entity == null){
            return fail("测试计划不存在");
        }
//        测试状态:0--已结束,1---手动关闭,2----还未开始,3---正在使用
        //非未开始状态，不允许修改开始时间,不允许修改测试计划名称,修改状态只能修改为手动关闭状态
        if(entity.getStatus() != Constant.TEST_PLAN_STATUS_UNSTART && entity.getStatus() != Constant.TEST_PLAN_STATUS_RUNNING){
            return fail("当前测试计划的状态为"+(entity.getStatus() == Constant.TEST_PLAN_STATUS_END ?"已结束":"已关闭")+"不允许修改");
        }
        //状态只能修改为手动关闭状态，不允许修改为其他状态
        if(testPlanEntity.getStatus() != entity.getStatus() && testPlanEntity.getStatus() != Constant.TEST_PLAN_STATUS_STOP  ){
            return fail("测试状态不符");
        }
        if(testPlanEntity.getTestEndTime().before(new Date())){
            return fail("计划结束时间不能早于当前时间");
        }
        //未开始状态  可修改所有信息，但是开始时间和结束时间不能小于当前时间
        if(entity.getStatus() == Constant.TEST_PLAN_STATUS_UNSTART){
            entity.setName(testPlanEntity.getName());
            entity.setStatus(testPlanEntity.getStatus());
            //测试计划开始时间小于当前时间
            long beginTimeStamp = testPlanEntity.getTestBeginTime().getTime()/1000/60;
            long nowTimeStamp = System.currentTimeMillis()/1000/60;
            if(nowTimeStamp-beginTimeStamp > 1){
                return fail("计划开始时间不能早于当前时间");
            }
            entity.setTestBeginTime(testPlanEntity.getTestBeginTime());
            entity.setTestEndTime(testPlanEntity.getTestEndTime());
        }else {
            //正在进行中的状态只能修改测试结束时间和状态
            if(!entity.getName().equals(testPlanEntity.getName())){
                return fail("当前计划正在进行中不允许修改计划名称");
            }
            if(entity.getTestBeginTime().compareTo(testPlanEntity.getTestBeginTime()) != 0){
                return fail("当前计划正在进行中不允许修改计划开始时间");
            }
            long endTimeStamp = testPlanEntity.getTestEndTime().getTime()/1000/60;
            long nowTimeStamp = System.currentTimeMillis()/1000/60;
            if(nowTimeStamp-endTimeStamp > 1){
                return fail("计划结束时间不能早于当前时间");
            }
        }
        entity.setTestEndTime(testPlanEntity.getTestEndTime());
        entity.setStatus(testPlanEntity.getStatus());
        entity.setUpdateTime(new Date());
        this.testPlanService.save(entity);
        return success();
    }


    @GetMapping("/group/{planId}/{pageNum}/{pageSize}")
    @SafetyProcess
    @ApiOperation("查询测试计划下的分组信息")
    public Result planGroupInfo(@PathVariable String planId,@PathVariable int pageNum,@PathVariable int pageSize){
        Page<PlanGroupEntry> entryPage = this.planGroupService.findByPlanId(planId,pageNum,pageSize);
        List<PlanGroupEntryDto> dtoList = new ArrayList<>();
        int allNum ;
        int allPage;
        if(entryPage.getTotalElements() > 0L){
            List<PlanGroupEntry> planGroupEntryList = entryPage.getContent();
            planGroupEntryList.forEach(item ->{
                PlanGroupEntryDto dto = new PlanGroupEntryDto();
                dto.setGroupId(item.getGroupId());
                dto.setPlanId(item.getPlanId());
                dto.setId(item.getId());
                dto.setUserNum(this.userService.findUsersInGroup(item.getGroupId()).size());
                dto.setGroupName(this.groupInfoService.findById(item.getGroupId()).getGroupName());
                dtoList.add(dto);
            });
            allNum = (int) entryPage.getTotalElements();
            allPage = entryPage.getTotalPages();
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("allNum",allNum);
            jsonObject.put("allPage",allPage);
            jsonObject.put("pageNum",pageNum);
            jsonObject.put("pageSize",pageSize);
            jsonObject.put("data",dtoList);
        }
        return success(dtoList);
    }

}

