package com.tykj.dev.device.task.service.impl;

import com.github.wenhao.jpa.PredicateBuilder;
import com.github.wenhao.jpa.Specifications;
import com.tykj.dev.blockcha.subject.entity.BcHash;
import com.tykj.dev.blockcha.subject.service.BlockChainUtil;
import com.tykj.dev.config.GlobalMap;
import com.tykj.dev.config.Log;
import com.tykj.dev.config.TaskBeanConfig;
import com.tykj.dev.device.task.repository.TaskDao;
import com.tykj.dev.device.task.repository.TaskLogDao;
import com.tykj.dev.device.task.service.TaskService;
import com.tykj.dev.device.task.subject.bto.TaskBto;
import com.tykj.dev.device.task.subject.domin.Task;
import com.tykj.dev.device.task.subject.domin.TaskLog;
import com.tykj.dev.device.task.subject.vo.TaskSelectVo;
import com.tykj.dev.device.task.subject.vo.TaskUserVo;
import com.tykj.dev.device.task.utils.TaskUtils;
import com.tykj.dev.device.user.cache.UserCache;
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.entity.User;
import com.tykj.dev.device.user.subject.service.UserPublicService;
import com.tykj.dev.device.user.util.UserUtils;
import com.tykj.dev.misc.base.CustomOrder;
import com.tykj.dev.misc.base.StatusEnum;
import com.tykj.dev.misc.exception.ApiException;
import com.tykj.dev.misc.utils.JacksonUtil;
import com.tykj.dev.misc.utils.ResultUtil;
import com.tykj.dev.socket.MyWebSocket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.ExceptionHandler;

import javax.persistence.Transient;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @author dengdiyi
 */
@Service
public class TaskServiceImpl implements TaskService {

    @Autowired
    private TaskDao taskDao;

    @Autowired
    private TaskUtils taskUtils;

    @Autowired
    private UserUtils userUtils;

    @Autowired
    private UserPublicService userPublicService;

    @Autowired
    private TaskLogDao taskLogDao;

    @Autowired
    private UserCache userCache;

    @Autowired
    private BlockChainUtil blockChainUtil;

    @Autowired
    private MyWebSocket myWebSocket;

    @Autowired
    private MessageService messageService;

    /**
     * <p>业务进行到下一个状态</p>
     * <li>不指定待办用户</li>
     */
    @Override
    @Log
    public TaskBto moveToNext(TaskBto taskBto) {
//        confirmUser(taskBto);
        //status++
        taskBto.setBillStatus(GlobalMap.getStatusEnumMap().getOrDefault(taskBto.getBillStatus() + 1, StatusEnum.END).id);
        //list add 0,point++
        taskBto.getInvolveUserIdList().add(0);
        taskBto.setCurrentPoint(taskBto.getCurrentPoint() + 1);
        //set readList empty
        taskBto.setUserReadDetailList(new ArrayList<>());
        update(taskBto);
        myWebSocket.sendMessage1();
        return taskBto;
    }

    /**
     * <p>业务进行到下一个状态</p>
     * <li>不指定待办用户</li>
     * <li>添加自定义信息</li>
     *
     * @param customInfo 自定义信息
     */
    @Override
    @Log
    public TaskBto moveToNext(TaskBto taskBto, String customInfo) {
//        confirmUser(taskBto);
        //status++
        taskBto.setBillStatus(GlobalMap.getStatusEnumMap().getOrDefault(taskBto.getBillStatus() + 1, StatusEnum.END).id);
        //list add 0,point++
        taskBto.getInvolveUserIdList().add(0);
        taskBto.setCurrentPoint(taskBto.getCurrentPoint() + 1);
        //set readList empty
        taskBto.setUserReadDetailList(new ArrayList<>());
        //set customInfo
        taskBto.setCustomInfo(customInfo);
        update(taskBto);
        myWebSocket.sendMessage1();
        return taskBto;
    }

    /**
     * <p>业务进行到下一个状态（指定待办用户）</p>
     * <li>指定待办用户</li>
     *
     * @param userId 待办用户Id
     */
    @Override
    @Log
    public TaskBto moveToNext(TaskBto taskBto, Integer userId) {
//        confirmUser(taskBto);
        //status++
        taskBto.setBillStatus(GlobalMap.getStatusEnumMap().getOrDefault(taskBto.getBillStatus() + 1, StatusEnum.END).id);
        //list add userId,point++
        taskBto.getInvolveUserIdList().add(userId);
        taskBto.setCurrentPoint(taskBto.getCurrentPoint() + 1);
        //set readList empty
        taskBto.setUserReadDetailList(new ArrayList<>());
        update(taskBto);
        myWebSocket.sendMessage1();
        return taskBto;
    }

    /**
     * <p>业务进行到下一个状态（指定待办用户）</p>
     * <li>指定待办用户</li>
     * <li>添加自定义信息</li>
     *
     * @param userId     待办用户Id
     * @param customInfo 自定义信息
     */
    @Override
    @Log
    public TaskBto moveToNext(TaskBto taskBto, Integer userId, String customInfo) {
//        confirmUser(taskBto);
        //status++
        taskBto.setBillStatus(GlobalMap.getStatusEnumMap().getOrDefault(taskBto.getBillStatus() + 1, StatusEnum.END).id);
        //list add userId,point++
        taskBto.getInvolveUserIdList().add(userId);
        taskBto.setCurrentPoint(taskBto.getCurrentPoint() + 1);
        //set readList empty
        taskBto.setUserReadDetailList(new ArrayList<>());
        //set customInfo
        taskBto.setCustomInfo(customInfo);
        update(taskBto);
        myWebSocket.sendMessage1();
        return taskBto;
    }

    /**
     * <p>业务进行到特殊状态</p>
     * <li>不指定待办用户</li>
     *
     * @param statusEnum 状态枚举
     */
    @Override
    @Log
    public TaskBto moveToSpecial(TaskBto taskBto, StatusEnum statusEnum) {
//        confirmUser(taskBto);
        //status++
        taskBto.setBillStatus(statusEnum.id);
        //list add 0,point++
        taskBto.getInvolveUserIdList().add(0);
        taskBto.setCurrentPoint(taskBto.getCurrentPoint() + 1);
        //set readList empty
        taskBto.setUserReadDetailList(new ArrayList<>());
        update(taskBto);
        myWebSocket.sendMessage1();
        return taskBto;
    }

    /**
     * <p>业务进行到特殊状态</p>
     * <li>不指定待办用户</li>
     * <li>添加自定义信息</li>
     *
     * @param statusEnum 状态枚举
     * @param customInfo 自定义信息
     */
    @Override
    @Log
    public TaskBto moveToSpecial(TaskBto taskBto, StatusEnum statusEnum, String customInfo) {
//        confirmUser(taskBto);
        //status++
        taskBto.setBillStatus(statusEnum.id);
        //list add 0,point++
        taskBto.getInvolveUserIdList().add(0);
        taskBto.setCurrentPoint(taskBto.getCurrentPoint() + 1);
        //set readList empty
        taskBto.setUserReadDetailList(new ArrayList<>());
        //set customInfo
        taskBto.setCustomInfo(customInfo);
        update(taskBto);
        myWebSocket.sendMessage1();
        return taskBto;
    }

    /**
     * <p>业务进行到特殊状态</p>
     * <li>指定待办用户</li>
     *
     * @param statusEnum 状态枚举
     * @param userId     待办用户Id
     */
    @Override
    @Log
    public TaskBto moveToSpecial(TaskBto taskBto, StatusEnum statusEnum, Integer userId) {
//        confirmUser(taskBto);
        //status++
        taskBto.setBillStatus(statusEnum.id);
        //list add userId,point++
        taskBto.getInvolveUserIdList().add(userId);
        taskBto.setCurrentPoint(taskBto.getCurrentPoint() + 1);
        //set readList empty
        taskBto.setUserReadDetailList(new ArrayList<>());
        update(taskBto);
        myWebSocket.sendMessage1();
        return taskBto;
    }

    /**
     * <p>业务进行到特殊状态</p>
     * <li>指定待办用户</li>
     * <li>添加自定义信息</li>
     *
     * @param statusEnum 状态枚举
     * @param userId     待办用户Id
     * @param customInfo 自定义信息
     */
    @Override
    @Log
    public TaskBto moveToSpecial(TaskBto taskBto, StatusEnum statusEnum, Integer userId, String customInfo) {
//        confirmUser(taskBto);
        //status++
        taskBto.setBillStatus(statusEnum.id);
        //list add userId,point++
        taskBto.getInvolveUserIdList().add(userId);
        taskBto.setCurrentPoint(taskBto.getCurrentPoint() + 1);
        //set readList empty
        taskBto.setUserReadDetailList(new ArrayList<>());
        //set customInfo
        taskBto.setCustomInfo(customInfo);
        update(taskBto);
        myWebSocket.sendMessage1();
        return taskBto;
    }

    /**
     * 业务完结
     */
    @Override
    @Log
    public TaskBto moveToEnd(TaskBto taskBto) {
//        confirmUser(taskBto);
        //set status end
        taskBto.setBillStatus(StatusEnum.END.id);
        update(taskBto);
        myWebSocket.sendMessage1();
        return taskBto;
    }

    /**
     * 业务审核失败封存
     */
    @Override
    @Log
    public TaskBto moveToArchive(TaskBto taskBto) {
//        confirmUser(taskBto);
        //set status archive
        taskBto.setBillStatus(StatusEnum.ARCHIVE.id);
        update(taskBto);
        myWebSocket.sendMessage1();
        return taskBto;
    }

    /**
     * 新增Task
     */
    @Override
    @ExceptionHandler(Exception.class)
    @Log
    public TaskBto start(TaskBto taskBto) {
        Task task = taskDao.save(taskBto.toDo());
        myWebSocket.sendMessage1();
        CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Task task1 = taskDao.findById(task.getId()).get();
            BcHash bcText = blockChainUtil.sendHash(1000, JacksonUtil.toJSon(task1));
            String recordId = bcText.getData().getRecordID();
            task1.setRecordId(recordId);
            taskDao.save(task1);
        }, TaskBeanConfig.getThreadPoolTaskScheduler());
        return task.parse2Bto();
    }

    /**
     * @param taskBtos 异步上链
     */
    @Override
    @Async
    public void sendHash(List<TaskBto> taskBtos) {
        taskBtos.forEach(taskBto -> {
            Task task = taskBto.toDo();
            BcHash bcText = blockChainUtil.sendHash(1000, JacksonUtil.toJSon(task));
            String recordId = bcText.getData().getRecordID();
            task.setRecordId(recordId);
            update(task.parse2Bto());
        });
    }

    /**
     * @param taskBto 异步上链
     */
    @Override
    @Async("taskScheduler")
    public void sendHash(TaskBto taskBto) {
        Task task = taskBto.toDo();
        BcHash bcText = blockChainUtil.sendHash(1000, JacksonUtil.toJSon(task));
        String recordId = bcText.getData().getRecordID();
        task.setRecordId(recordId);
        update(task.parse2Bto());
    }

    /**
     * 更新Task
     */
    @Override
    public Task update(TaskBto taskBto) {
        taskBto.setUserReadDetailList(new ArrayList<>());
        Task task = taskDao.save(taskBto.toDo());
        CompletableFuture.runAsync(() -> blockChainUtil.appendHash(JacksonUtil.toJSon(taskBto.toDo()), taskBto.getRecordId()), TaskBeanConfig.getThreadPoolTaskScheduler());
        return task;
    }

    /**
     * 根据id获得Task
     */
    @Override
    public TaskBto get(Integer id) {
        Optional<Task> task = taskDao.findById(id);
        return task.map(Task::parse2Bto).orElse(null);
    }

    /**
     * 根据billId和businessType获得Task
     */
    @Override
    public TaskBto get(Integer billId, Integer businessType) {
        List<Task> tasks = taskDao.findAllByBillIdAndBusinessType(billId, businessType);
        if (tasks.size()==0){
            throw new ApiException(String.format("要查询的数据不存在,查询的billId为 %d,businessType为 %d", billId, businessType));
        }
        else if (tasks.size()==1){
            return tasks.get(0).parse2Bto();
        }
        else {
            return tasks.stream().filter(task -> "exam".equals(task.getCustomInfo())).collect(Collectors.toList()).get(0).parse2Bto();
        }
//        return taskDao.findByBillIdAndBusinessType(billId, businessType)
//                .orElseThrow(() -> new ApiException(String.format("要查询的数据不存在,查询的billId为 %d,businessType为 %d", billId, businessType)))
//                .parse2Bto();
    }

    /**
     * @param taskSelectVo 获取跟踪和待办业务列表
     */
    @Override
    public List<TaskUserVo> getList(TaskSelectVo taskSelectVo) {
        List<TaskUserVo> taskEntities = getTaskUserVoList(taskSelectVo);
        if (taskSelectVo.getSelectNum()==2){
            taskEntities = taskEntities.stream().sorted(Comparator.comparing(TaskUserVo::getTrackingTimeDate,Comparator.nullsFirst(Date::compareTo))).collect(Collectors.toList());
        }
        if (taskSelectVo.getSelectNum()==3){
            taskEntities = taskEntities.stream().sorted(Comparator.comparing(TaskUserVo::getUserTimeDate,Comparator.nullsFirst(Date::compareTo))).collect(Collectors.toList());
        }
        if (taskSelectVo.getOrders().size() > 0) {
            List<Comparator<TaskUserVo>> comparators = new ArrayList<>();
            if (taskSelectVo.getOrders().size() > 0) {
                for (CustomOrder c:taskSelectVo.getOrders()) {
                    if ("trackingTime".equals(c.getCoulmn())){
                        if ("ASC".equals(c.getDirection().toString())) {
                            comparators.add(Comparator.comparing(TaskUserVo::getTrackingTimeDate,Comparator.nullsFirst(Date::compareTo)));
                        }
                        else if ("DESC".equals(c.getDirection().toString())) {
                            comparators.add(Comparator.comparing(TaskUserVo::getTrackingTimeDate,Comparator.nullsFirst(Date::compareTo)).reversed());
                        }
                    }
                    else if ("userTime".equals(c.getCoulmn())){
                        if ("ASC".equals(c.getDirection().toString())) {
                            comparators.add(Comparator.comparing(TaskUserVo::getUserTimeDate,Comparator.nullsFirst(Date::compareTo)));
                        }
                        else if ("DESC".equals(c.getDirection().toString())) {
                            comparators.add(Comparator.comparing(TaskUserVo::getUserTimeDate,Comparator.nullsFirst(Date::compareTo)).reversed());
                        }
                    }
                    else if ("title".equals(c.getCoulmn())){
                        if ("ASC".equals(c.getDirection().toString())) {
                            comparators.add(Comparator.comparing(TaskUserVo::getTitle,Comparator.nullsFirst(String::compareTo)));
                        }
                        else if ("DESC".equals(c.getDirection().toString())) {
                            comparators.add(Comparator.comparing(TaskUserVo::getTitle,Comparator.nullsFirst(String::compareTo)).reversed());
                        }
                    }
                    else if ("startUnit".equals(c.getCoulmn())){
                        if ("ASC".equals(c.getDirection().toString())) {
                            comparators.add(Comparator.comparing(TaskUserVo::getStartUnit,Comparator.nullsFirst(String::compareTo)));
                        }
                        else if ("DESC".equals(c.getDirection().toString())) {
                            comparators.add(Comparator.comparing(TaskUserVo::getStartUnit,Comparator.nullsFirst(String::compareTo)).reversed());
                        }
                    }
                    else if ("status".equals(c.getCoulmn())){
                        if ("ASC".equals(c.getDirection().toString())) {
                            comparators.add(Comparator.comparing(TaskUserVo::getStatus,Comparator.nullsFirst(String::compareTo)));
                        }
                        else if ("DESC".equals(c.getDirection().toString())) {
                            comparators.add(Comparator.comparing(TaskUserVo::getStatus,Comparator.nullsFirst(String::compareTo)).reversed());
                        }
                    }
                    if (comparators.size()==1){
                        taskEntities = taskEntities.stream().sorted(comparators.get(0)).collect(Collectors.toList());
                    }
                    else if(comparators.size()==2){
                        taskEntities = taskEntities.stream().sorted(comparators.get(0).thenComparing(comparators.get(1))).collect(Collectors.toList());
                    }
                    else if(comparators.size()==3){
                        taskEntities = taskEntities.stream().sorted(comparators.get(0).thenComparing(comparators.get(1)).thenComparing(comparators.get(2))).collect(Collectors.toList());
                    }
                    else if(comparators.size()==4){
                        taskEntities = taskEntities.stream().sorted(comparators.get(0).thenComparing(comparators.get(1)).thenComparing(comparators.get(2)).thenComparing(comparators.get(3))).collect(Collectors.toList());
                    }
                }
            }
            //根据vo待办和跟踪时间的查询顺序按顺序或降序排序输出
//            if (taskSelectVo.getSelectNum() == 2 && "trackingTime".equals(taskSelectVo.getOrders().get(0).getCoulmn())) {
//                if ("ASC".equals(taskSelectVo.getOrders().get(0).getDirection().toString())) {
//                    return taskUtils.orderByTrackingTimeDateAsc(taskEntities);
//                }
//                if ("DESC".equals(taskSelectVo.getOrders().get(0).getDirection().toString())) {
//                    return taskUtils.orderByTrackingTimeDateDesc(taskEntities);
//                }
//            }
//            if (taskSelectVo.getSelectNum() == 3 && "userTime".equals(taskSelectVo.getOrders().get(0).getCoulmn())) {
//                if ("ASC".equals(taskSelectVo.getOrders().get(0).getDirection().toString())) {
//                    return taskUtils.orderByUserTimeDateAsc(taskEntities);
//                }
//                if ("DESC".equals(taskSelectVo.getOrders().get(0).getDirection().toString())) {
//                    return taskUtils.orderByUserTimeDateDesc(taskEntities);
//                }
//            }
        }
        return taskEntities;
    }

    /**
     * @param taskSelectVo 获取业务管理中的业务列表
     */
    @Override
    public List<TaskUserVo> getManageList(TaskSelectVo taskSelectVo) {
        Integer num = taskSelectVo.getSelectNum();
        Integer userId = userUtils.getCurrentUserId();
        //业务管理中的待办和跟踪
        if (num == 2 || num == 3) {
            //查询出符合筛选条件的所有task
            List<TaskUserVo> list = taskDao.findAll(getSelectSpecification(taskSelectVo)).stream()
                    .map(Task::parse2Bto)
                    .map(TaskBto::toVo)
                    .collect(Collectors.toList());
            //查询当前用户的跟踪和待办并和list按id取交集
            List<TaskUserVo> taskUserVos = getList(taskSelectVo).stream()
                    .filter(taskUserVo -> find(taskUserVo.getId(), list) > -1)
                    .collect(Collectors.toList());
            //判断是否需要按发起时间排序
            if (taskSelectVo.getOrders().size() > 0) {
                List<Comparator<TaskUserVo>> comparators = new ArrayList<>();
                if (taskSelectVo.getOrders().size() > 0) {
                    for (CustomOrder c : taskSelectVo.getOrders()) {
                        if ("createTime".equals(c.getCoulmn())) {
                            if ("ASC".equals(c.getDirection().toString())) {
                                comparators.add(Comparator.comparing(TaskUserVo::getCreateTime, Comparator.nullsFirst(Date::compareTo)));
                            } else if ("DESC".equals(c.getDirection().toString())) {
                                comparators.add(Comparator.comparing(TaskUserVo::getCreateTime, Comparator.nullsFirst(Date::compareTo)).reversed());
                            }
                        } else if ("title".equals(c.getCoulmn())) {
                            if ("ASC".equals(c.getDirection().toString())) {
                                comparators.add(Comparator.comparing(TaskUserVo::getTitle, Comparator.nullsFirst(String::compareTo)));
                            } else if ("DESC".equals(c.getDirection().toString())) {
                                comparators.add(Comparator.comparing(TaskUserVo::getTitle, Comparator.nullsFirst(String::compareTo)).reversed());
                            }
                        } else if ("businessType".equals(c.getCoulmn())) {
                            if ("ASC".equals(c.getDirection().toString())) {
                                comparators.add(Comparator.comparing(TaskUserVo::getBusinessType, Comparator.nullsFirst(Integer::compareTo)));
                            } else if ("DESC".equals(c.getDirection().toString())) {
                                comparators.add(Comparator.comparing(TaskUserVo::getBusinessType, Comparator.nullsFirst(Integer::compareTo)).reversed());
                            }
                        } else if ("status".equals(c.getCoulmn())) {
                            if ("ASC".equals(c.getDirection().toString())) {
                                comparators.add(Comparator.comparing(TaskUserVo::getStatus, Comparator.nullsFirst(String::compareTo)));
                            } else if ("DESC".equals(c.getDirection().toString())) {
                                comparators.add(Comparator.comparing(TaskUserVo::getStatus, Comparator.nullsFirst(String::compareTo)).reversed());
                            }
                        } else if ("startUnit".equals(c.getCoulmn())) {
                            if ("ASC".equals(c.getDirection().toString())) {
                                comparators.add(Comparator.comparing(TaskUserVo::getStartUnit, Comparator.nullsFirst(String::compareTo)));
                            } else if ("DESC".equals(c.getDirection().toString())) {
                                comparators.add(Comparator.comparing(TaskUserVo::getStartUnit, Comparator.nullsFirst(String::compareTo)).reversed());
                            }
                        }
                        if (comparators.size() == 1) {
                            taskUserVos = taskUserVos.stream().sorted(comparators.get(0)).collect(Collectors.toList());
                        } else if (comparators.size() == 2) {
                            taskUserVos = taskUserVos.stream().sorted(comparators.get(0).thenComparing(comparators.get(1))).collect(Collectors.toList());
                        } else if (comparators.size() == 3) {
                            taskUserVos = taskUserVos.stream().sorted(comparators.get(0).thenComparing(comparators.get(1)).thenComparing(comparators.get(2))).collect(Collectors.toList());
                        } else if (comparators.size() == 4) {
                            taskUserVos = taskUserVos.stream().sorted(comparators.get(0).thenComparing(comparators.get(1)).thenComparing(comparators.get(2)).thenComparing(comparators.get(3))).collect(Collectors.toList());
                        } else if (comparators.size() == 5) {
                            taskUserVos = taskUserVos.stream().sorted(comparators.get(0).thenComparing(comparators.get(1)).thenComparing(comparators.get(2)).thenComparing(comparators.get(3)).thenComparing(comparators.get(4))).collect(Collectors.toList());
                        }
                    }
                }
//                if ("createTime".equals(taskSelectVo.getOrders().get(0).getCoulmn())) {
//                    if ("ASC".equals(taskSelectVo.getOrders().get(0).getDirection().toString())) {
//                        return taskUtils.orderByCreateTimeAsc2(taskUserVos);
//                    }
//                    if ("DESC".equals(taskSelectVo.getOrders().get(0).getDirection().toString())) {
//                        return taskUtils.orderByCreateTimeDesc2(taskUserVos);
//                    }
//                }
            }
            return taskUserVos;
        }
        if (num == 4 || num == 5 || num == 1 || num == 0) {
            //获取单位等级
            Integer level = userUtils.getCurrentUnitLevel();
            //获取该单位以及下属单位所有用户Id
            List<Integer> idLists = userPublicService.findAllUserIdByUnitsName(userUtils.getCurrentUserUnitName());
            List<TaskUserVo> taskUserVos = new ArrayList<>();
            //省能看到所有业务
            if (level == 1) {
                taskUserVos = taskDao.findAll(getSelectSpecification(taskSelectVo)).stream()
                        .filter(taskBto -> taskSelectVo.getType() == null || taskSelectVo.getType()==1?(taskBto.getCustomInfo()==null|| !"country".equals(taskBto.getCustomInfo())):(taskBto.getCustomInfo()!=null&& "country".equals(taskBto.getCustomInfo())))
                        .map(Task::parse2Bto)
                        .map(TaskBto::toVo)
                        .collect(Collectors.toList());
            }
            //市或县只能看到涉及人员和idLists有交集的
            if (level == 2 || level == 3) {
                taskUserVos = taskDao.findAll(getSelectSpecification(taskSelectVo)).stream()
                        .map(Task::parse2Bto)
                        .map(TaskBto::toVo)
                        .filter(taskUserVo -> !Collections.disjoint(idLists, taskUserVo.getInvolveUserIdList())||(taskUserVo.getCreateUserId()!=null&&idLists.contains(taskUserVo.getCreateUserId())))
                        .collect(Collectors.toList());
            }
            //set经办人，置顶以及阅读情况
            for (TaskUserVo taskUserVo : taskUserVos) {
                List<Integer> idList = taskUserVo.getUserReadDetailList();
                List<Integer> idList2 = taskUserVo.getTopFlagDetailList();
                if (taskUserVo.getInvolveUserIdList() != null && taskUserVo.getInvolveUserIdList().size() > 0) {
                    //获取涉及人员当前指针
                    List<Integer> userIds = taskUserVo.getInvolveUserIdList();
                    if (userIds.size() > 0 && taskUserVo.getCurrentPoint() < userIds.size()) {
                        Integer userId3 = userIds.get(taskUserVo.getCurrentPoint());
                        //当前指针userId大于0，待办人即当前id
                        if (userId3 > 0) {
                            User user=userCache.findById(userId3);
                            if (user!=null){
                                taskUserVo.setProcessingUser(userCache.findById(userId3).getName());
                            }
                        }
                        //当前指针userId等于0，待办人为所属单位下所有用户
                        else if (userId3 == 0 && taskUserVo.getOwnUnit() != null) {
                            StringBuffer stringBuffer = new StringBuffer();
                            List<User> users = userCache.findAll();
                            users.stream().filter(user -> user.getUnitsId().equals(taskUserVo.getOwnUnit())).forEach(user -> {
                                stringBuffer.append(user.getName()).append(",");
                            });
                            if (stringBuffer.length() > 0) {
                                stringBuffer.deleteCharAt(stringBuffer.length() - 1);
                            }
                            taskUserVo.setProcessingUser(stringBuffer.toString());
                        } else {
                            taskUserVo.setProcessingUser("");
                        }
                    }
                }
                //判断当前用户是否已读
                if (idList.contains(userId)) {
                    taskUserVo.setIsRead(1);
                }
                //判断当前用户是否置顶
                if (idList2.contains(userId)) {
                    taskUserVo.setIsTop(1);
                }
            }
            taskUserVos = taskUserVos.stream().sorted(Comparator.comparing(TaskUserVo::getCreateTime,Comparator.nullsFirst(Date::compareTo)).reversed()).collect(Collectors.toList());
            //判断是否需要按发起时间排序
            if (!taskSelectVo.getOrders().isEmpty()) {
                List<Comparator<TaskUserVo>> comparators = new ArrayList<>();
                if (taskSelectVo.getOrders().size() > 0) {
                    for (CustomOrder c : taskSelectVo.getOrders()) {
                        if ("createTime".equals(c.getCoulmn())) {
                            if ("ASC".equals(c.getDirection().toString())) {
                                comparators.add(Comparator.comparing(TaskUserVo::getCreateTime, Comparator.nullsFirst(Date::compareTo)));
                            } else if ("DESC".equals(c.getDirection().toString())) {
                                comparators.add(Comparator.comparing(TaskUserVo::getCreateTime, Comparator.nullsFirst(Date::compareTo)).reversed());
                            }
                        } else if ("title".equals(c.getCoulmn())) {
                            if ("ASC".equals(c.getDirection().toString())) {
                                comparators.add(Comparator.comparing(TaskUserVo::getTitle, Comparator.nullsFirst(String::compareTo)));
                            } else if ("DESC".equals(c.getDirection().toString())) {
                                comparators.add(Comparator.comparing(TaskUserVo::getTitle, Comparator.nullsFirst(String::compareTo)).reversed());
                            }
                        } else if ("businessType".equals(c.getCoulmn())) {
                            if ("ASC".equals(c.getDirection().toString())) {
                                comparators.add(Comparator.comparing(TaskUserVo::getBusinessType, Comparator.nullsFirst(Integer::compareTo)));
                            } else if ("DESC".equals(c.getDirection().toString())) {
                                comparators.add(Comparator.comparing(TaskUserVo::getBusinessType, Comparator.nullsFirst(Integer::compareTo)).reversed());
                            }
                        } else if ("status".equals(c.getCoulmn())) {
                            if ("ASC".equals(c.getDirection().toString())) {
                                comparators.add(Comparator.comparing(TaskUserVo::getStatus, Comparator.nullsFirst(String::compareTo)));
                            } else if ("DESC".equals(c.getDirection().toString())) {
                                comparators.add(Comparator.comparing(TaskUserVo::getStatus, Comparator.nullsFirst(String::compareTo)).reversed());
                            }
                        } else if ("startUnit".equals(c.getCoulmn())) {
                            if ("ASC".equals(c.getDirection().toString())) {
                                comparators.add(Comparator.comparing(TaskUserVo::getStartUnit, Comparator.nullsFirst(String::compareTo)));
                            } else if ("DESC".equals(c.getDirection().toString())) {
                                comparators.add(Comparator.comparing(TaskUserVo::getStartUnit, Comparator.nullsFirst(String::compareTo)).reversed());
                            }
                        }
                        if (comparators.size() == 1) {
                            taskUserVos = taskUserVos.stream().sorted(comparators.get(0)).collect(Collectors.toList());
                        } else if (comparators.size() == 2) {
                            taskUserVos = taskUserVos.stream().sorted(comparators.get(0).thenComparing(comparators.get(1))).collect(Collectors.toList());
                        } else if (comparators.size() == 3) {
                            taskUserVos = taskUserVos.stream().sorted(comparators.get(0).thenComparing(comparators.get(1)).thenComparing(comparators.get(2))).collect(Collectors.toList());
                        } else if (comparators.size() == 4) {
                            taskUserVos = taskUserVos.stream().sorted(comparators.get(0).thenComparing(comparators.get(1)).thenComparing(comparators.get(2)).thenComparing(comparators.get(3))).collect(Collectors.toList());
                        } else if (comparators.size() == 5) {
                            taskUserVos = taskUserVos.stream().sorted(comparators.get(0).thenComparing(comparators.get(1)).thenComparing(comparators.get(2)).thenComparing(comparators.get(3)).thenComparing(comparators.get(4))).collect(Collectors.toList());
                        }
                    }
                }
            }
            return taskUserVos;
        } else {
            throw new ApiException(ResultUtil.failed("selectNum只能为0，1，2，3，4，5"));
        }
    }

    /**
     * @param taskBto 任务bto
     * @param userId  新增涉及用户id
     */
    @Override
    public TaskBto addInvolveUser(TaskBto taskBto, Integer userId) {
//        confirmUser(taskBto);
        List<Integer> list = taskBto.getInvolveUserIdList();
        //添加涉及用户Id
        list.add(userId);
        taskBto.setInvolveUserIdList(list);
        //指针后移
        taskBto.setCurrentPoint(taskBto.getCurrentPoint() + 1);
        update(taskBto);
        return taskBto;
    }

    /**
     * 判断该根任务节点下的所有task是否都处于完结状态
     *
     * @param rootId task的根节点id
     * @return Task Tree 是否已经结束
     */
    @Override
    public boolean TaskTreeIsOver(int rootId) {
        List<Task> taskList = taskDao.findAllByParentTaskId(rootId);
        if (CollectionUtils.isEmpty(taskList)) {
            return true;
        } else {
            return taskList.stream()
                    .allMatch(task -> task.getBillStatus().equals(StatusEnum.END.id));
        }
    }

    /**
     * 判断该任务节点下的下一级节点是否任意一个都没有处于完结状态(即用来判断该任务树是否是初始状态)
     *
     * @param rootId task的根节点id
     * @return Task Tree 是否是初始状态
     */
    @Override
    public boolean TaskTreeIsStart(int rootId, boolean currentIsOver) {
        List<Task> taskList = taskDao.findAllByParentTaskId(rootId);
        if (CollectionUtils.isEmpty(taskList)) {
            return false;
        } else {
            long overJobCount = taskList.stream()
                    .filter(task -> task.getBillStatus().equals(StatusEnum.END.id))
                    .count();

            //如果当前任务是完结的,那么完结数量等于1就证明是初始状态,否则必须为0
            if (currentIsOver) {
                return overJobCount == 1;
            } else {
                return overJobCount == 0;
            }
        }

    }

    /**
     * @param oldUserId 旧专管员id
     * @param newUserId 新交接专管员id
     */
    @Override
    public void workHandover(Integer oldUserId, Integer newUserId) {
        //筛选出未完结和未封存业务，映射成bto
        List<TaskBto> taskBtos = taskDao.findAll().stream()
                .filter(task -> (!task.getBillStatus().equals(StatusEnum.END.id)) && (!task.getBillStatus().equals(StatusEnum.ARCHIVE.id)))
                .map(Task::parse2Bto)
                .collect(Collectors.toList());
        //查询待办
        //当前指针对应userId是旧用户
        List<TaskBto> taskBtoList = taskBtos.stream()
                .filter(taskBto -> {
                    boolean involveExists = taskBto.getInvolveUserIdList().size() > 0;
                    boolean pointExists = taskBto.getCurrentPoint() < taskBto.getInvolveUserIdList().size();
                    boolean userConfirm = oldUserId.equals(taskBto.getInvolveUserIdList().get(taskBto.getCurrentPoint()));
                    return involveExists && pointExists && userConfirm;
                })
                .collect(Collectors.toList());
        //替换用户id
        taskBtoList.forEach(taskBto -> {
            List<Integer> ids = taskBto.getInvolveUserIdList();
            ids.set(taskBto.getCurrentPoint(), newUserId);
            taskBto.setInvolveUserIdList(ids);
            update(taskBto);
        });
        //查询跟踪
        //涉及人员包括旧用户
        List<TaskBto> taskBtos1 = taskBtos.stream()
                .filter(taskBto -> {
                    boolean involveExists = taskBto.getInvolveUserIdList().contains(oldUserId);
                    boolean pointExists = taskBto.getCurrentPoint() < taskBto.getInvolveUserIdList().size();
                    return involveExists && pointExists;
                })
                .collect(Collectors.toList());
        //替换用户id
        taskBtos1.forEach(taskBto -> {
            List<Integer> ids = taskBto.getInvolveUserIdList();
            for (int i = 0; i < ids.size(); i++) {
                if (ids.get(i).equals(oldUserId)) {
                    ids.set(i, newUserId);
                }
            }
            taskBto.setInvolveUserIdList(ids);
            update(taskBto);
        });
        //查询阅知
        List<MessageBto> messageBtos = messageService.getBtoList();
        //替换用户id
        messageBtos.forEach(messageBto -> {
            List<Integer> ids = messageBto.getInvolveUserIdList();
            List<Integer> ids2 = messageBto.getCompleteUserIdList();
            for (int i = 0; i < ids.size(); i++) {
                if (ids.get(i).equals(oldUserId)) {
                    ids.set(i, newUserId);
                }
            }
            for (int i = 0; i < ids2.size(); i++) {
                if (ids2.get(i).equals(oldUserId)) {
                    ids2.set(i, newUserId);
                }
            }
            messageBto.setInvolveUserIdList(ids);
            messageBto.setCompleteUserIdList(ids2);
            messageService.update(messageBto.toDo());
        });
        myWebSocket.sendMessage1();
    }

    @Override
    public List<TaskBto> findBillIdAndBillType(List<Integer> billIds,Integer billType) {
        return taskDao.findAllByBillIdInAndBusinessType(billIds,billType).stream().map(Task::parse2Bto).collect(Collectors.toList());
    }

    @Override
    public Optional<Task> findBillIdAndBusinessType(Integer billId, Integer businessType,Integer billStatus) {
        return taskDao.findByBillIdAndBusinessTypeAndBillStatusNot(billId,businessType,billStatus);
    }

    @Override
    public Optional<Task> findBillIdAndBusinessTypeNotBillStatus(Integer billId, Integer businessType) {
        return taskDao.findByBillIdAndBusinessType(billId,businessType);
    }

    @Override
    public TaskBto findFatherIdAndCustomInfo(Integer taskId) {

       List<TaskBto> taskBtos = taskDao.findAllByParentTaskId(taskId).stream().filter(task -> task.getCustomInfo().equals("shi")).map(Task::parse2Bto).collect(Collectors.toList());
       for (TaskBto taskBto:taskBtos){
           if (taskBto.getCustomInfo().equals("shi")){
               return taskBto;
           }
       }
      throw new ApiException(ResponseEntity.status(500).body("[清退] id："+taskId+"没有找到子类CustomInfo为shi的"));
    }

    @Override
    public List<TaskBto> findBillType(Integer billType) {
        return taskDao.findAllByBusinessType(billType).stream().map(Task::parse2Bto).collect(Collectors.toList());
    }

    @Override
    public TaskBto findBillTypeAndFatherId(Integer billType, Integer fatherId) {

        return taskDao.findByParentTaskIdAndBusinessType(fatherId,billType).parse2Bto();
    }

    @Override
    public void moveAllSonNodeToEnd(Integer taaskId) {
        List<Task> tasks = taskDao.findAllByParentTaskId(taaskId);
        if (tasks.size()>0){
            tasks.forEach(task -> {
                moveToEnd(task.parse2Bto());
                moveAllSonNodeToEnd(task.getId());
            });
        }
    }

    /**
     * @param taskSelectVo 查询vo
     *                     查询跟踪和待办列表
     * @return taskUserVo列表
     */
    private List<TaskUserVo> getTaskUserVoList(TaskSelectVo taskSelectVo) {
        Integer userId = userUtils.getCurrentUserId();
        List<Integer> bussinessType = taskSelectVo.getBusinessType();
        Integer unitId = userUtils.getCurrentUnitId();
        //筛选出未完结和未封存业务，映射成bto
        List<TaskBto> taskBtos = taskDao.findAll().stream()
                .filter(task -> (!task.getBillStatus().equals(StatusEnum.END.id)) && (!task.getBillStatus().equals(StatusEnum.ARCHIVE.id)))
                .map(Task::parse2Bto)
                .collect(Collectors.toList());
        //查询待办
        if (taskSelectVo.getSelectNum() == 2) {
            //当前指针对应userId是当前用户或者为0且所属单位为当前单位
            List<TaskBto> taskBtoList = taskBtos.stream()
                    .filter(taskBto -> {
                        boolean involveExists = taskBto.getInvolveUserIdList().size() > 0;
                        boolean pointExists = taskBto.getCurrentPoint() < taskBto.getInvolveUserIdList().size();
                        boolean userConfirm = userId.equals(taskBto.getInvolveUserIdList().get(taskBto.getCurrentPoint()));
                        boolean noUserHandle = taskBto.getInvolveUserIdList().get(taskBto.getCurrentPoint()) == 0;
                        boolean belongUnit = taskBto.getOwnUnit().equals(userUtils.getCurrentUnitId());
                        boolean isCountry = taskSelectVo.getType() == null || (taskSelectVo.getType() == 1 ? (taskBto.getCustomInfo() == null || !"country".equals(taskBto.getCustomInfo())) : (taskBto.getCustomInfo() != null && "country".equals(taskBto.getCustomInfo())));
                        return involveExists && pointExists && (userConfirm || (noUserHandle && belongUnit)) && isCountry;
                    })
                    .collect(Collectors.toList());
            //查询所有的业务
            if (bussinessType == null ||bussinessType.isEmpty()) {
                List<TaskUserVo> taskUserVos = taskBtoList.stream().map(TaskBto::toVo).collect(Collectors.toList());
                return setTaskUserVo(taskUserVos, 0);
            } else {
                //查询工作台其它业务
                if (bussinessType.contains(0)) {
                    List<TaskUserVo> taskUserVos = taskBtoList.stream()
                            .filter(taskBto -> !new ArrayList<>(Arrays.asList(3, 4, 5, 6)).contains(taskBto.getBusinessType()))
                            .map(TaskBto::toVo)
                            .collect(Collectors.toList());
                    return setTaskUserVo(taskUserVos, 0);
                }
                //查询某一业务
                else {
                    List<TaskUserVo> taskUserVos = taskBtoList.stream()
                            .filter(taskBto -> bussinessType.contains(taskBto.getBusinessType()))
                            .map(TaskBto::toVo)
                            .collect(Collectors.toList());
                    return setTaskUserVo(taskUserVos, 0);
                }
            }
        }
        //查询跟踪
        if (taskSelectVo.getSelectNum() == 3) {
            //所有涉及人员所在单位包含当前用户所在单位且指针对应UserId不是当前用户
            List<Integer> status = Arrays.asList(201,333,810,322,722,788,1250,2223,8110,888,140,130,141,111,1002);
            List<TaskBto> taskBtoList = taskBtos.stream()
                    .filter(taskBto -> {
//                        boolean unitExists = getUnitsByUsers(taskBto.getInvolveUserIdList()).contains(unitId);
                        boolean userConfirm2 = taskBto.getInvolveUserIdList().get(taskBto.getCurrentPoint()) == -1;
                        boolean pointExists = taskBto.getCurrentPoint() < taskBto.getInvolveUserIdList().size();
                        boolean userConfirm = userId.equals(taskBto.getInvolveUserIdList().get(taskBto.getCurrentPoint())) || (taskBto.getInvolveUserIdList().get(taskBto.getCurrentPoint())==0 && taskBto.getOwnUnit().equals(userUtils.getCurrentUnitId()));
                        boolean isDraft = status.contains(taskBto.getBillStatus());
//                        boolean isCreateUser = userId.equals(taskBto.getCreateUserId());
                        boolean isCreateUnit = taskBto.getCreateUserId()!=null&&unitId.equals(userCache.findById(taskBto.getCreateUserId()).getUnitsId());
                        return pointExists && !userConfirm && !userConfirm2 && !isDraft && isCreateUnit;
                    })
                    .collect(Collectors.toList());

            //涉及人员当前指针为-1，且所属单位为当前单位
            List<TaskBto> taskBtos1 = taskBtos.stream()
                    .filter(taskBto -> {
//                        boolean involveExists = taskBto.getInvolveUserIdList().contains(userId);
                        boolean pointExists = taskBto.getCurrentPoint() < taskBto.getInvolveUserIdList().size();
                        boolean userConfirm = taskBto.getInvolveUserIdList().get(taskBto.getCurrentPoint()) == -1;
                        boolean unitConfirm = taskBto.getOwnUnit().equals(unitId);
                        boolean isCreateUser = userId.equals(taskBto.getCreateUserId());
                        return pointExists && userConfirm && unitConfirm && isCreateUser;
                    })
                    .collect(Collectors.toList());
            taskBtoList.addAll(taskBtos1);
            //查询所有业务
            if (bussinessType == null) {
                List<TaskUserVo> taskUserVos = taskBtoList.stream().map(TaskBto::toVo).collect(Collectors.toList());
                return setTaskUserVo(taskUserVos, 1);
            } else {
                //查询工作台其它业务
                if (bussinessType.contains(0)) {
                    List<TaskUserVo> taskUserVos = taskBtoList.stream()
                            .filter(taskBto -> !new ArrayList<>(Arrays.asList(3, 4, 5, 6)).contains(taskBto.getBusinessType()))
                            .map(TaskBto::toVo)
                            .collect(Collectors.toList());
                    return setTaskUserVo(taskUserVos, 1);
                }
                //查询某一业务
                else {
                    List<TaskUserVo> taskUserVos = taskBtoList.stream()
                            .filter(taskBto -> bussinessType.contains(taskBto.getBusinessType()))
                            .map(TaskBto::toVo)
                            .collect(Collectors.toList());
                    return setTaskUserVo(taskUserVos, 1);
                }
            }
        } else {
            throw new ApiException(ResultUtil.failed("selectNum只能为2或3"));
        }
    }

    /**
     * @param list taskUserVos
     * @param type 0:set待办 1:set跟踪
     *             set一些输出给前端的值
     */
    private List<TaskUserVo> setTaskUserVo(List<TaskUserVo> list, int type) {
        Integer userId = userUtils.getCurrentUserId();
        list.forEach(taskUserVo -> {
            List<Integer> idList = taskUserVo.getUserReadDetailList();
            List<Integer> idList2 = taskUserVo.getTopFlagDetailList();
            if (taskUserVo.getInvolveUserIdList() != null && taskUserVo.getInvolveUserIdList().size() > 0) {
                //获取涉及人员当前指针
                List<Integer> userIds = taskUserVo.getInvolveUserIdList();
                if (userIds.size() > 0 && taskUserVo.getCurrentPoint() < userIds.size()) {
                    Integer userId3 = userIds.get(taskUserVo.getCurrentPoint());
                    //当前指针userId大于0，待办人即当前id
                    if (userId3 > 0) {
                        taskUserVo.setProcessingUser(userCache.findById(userId3).getName());
                    }
                    //当前指针userId等于0，待办人为所属单位下所有用户
                    else if (userId3 == 0 && taskUserVo.getOwnUnit() != null) {
                        StringBuffer stringBuffer = new StringBuffer();
                        List<User> users = userCache.findAll();
                        users.stream().filter(user -> user.getUnitsId().equals(taskUserVo.getOwnUnit())).forEach(user -> {
                            stringBuffer.append(user.getName()).append(",");
                        });
                        if (stringBuffer.length() > 0) {
                            stringBuffer.deleteCharAt(stringBuffer.length() - 1);
                        }
                        taskUserVo.setProcessingUser(stringBuffer.toString());
                    } else {
                        taskUserVo.setProcessingUser("");
                    }
                }
            }
            //判断当前用户是否已读
            if (idList.contains(userId)) {
                taskUserVo.setIsRead(1);
            }
            //判断当前用户是否置顶
            if (idList2.contains(userId)) {
                taskUserVo.setIsTop(1);
            }
            //set待办时间
            if (type == 0) {
                long time = System.currentTimeMillis() - taskUserVo.getUpdateTime().getTime();
                int day = new Long(time / 86_400_000).intValue();
                int hour = new Long((time % 86_400_000) / 3_600_000).intValue();
                if (day==0){
                    taskUserVo.setTrackingTime(hour + "小时");
                }
                else {
                    taskUserVo.setTrackingTime(day + "天");
                }
//                taskUserVo.setTrackingTime(day + "天" + hour + "小时");
                taskUserVo.setTrackingTimeDate(new Date(time));
            }
            //set跟踪时间
            if (type == 1) {
//                Date userTime = getUserTime(taskUserVo.getId());
//                if (userTime == null) {
//                    taskUserVo.setUserTime("0天0小时");
//                    taskUserVo.setUserTimeDate(new Date(0));
//                } else {
                long time = System.currentTimeMillis() - taskUserVo.getCreateTime().getTime();
                int day = new Long(time / 86_400_000).intValue();
                int hour = new Long((time % 86_400_000) / 3_600_000).intValue();
                if (day==0){
                    taskUserVo.setUserTime(hour + "小时");
                }
                else {
                    taskUserVo.setUserTime(day + "天");
                }
//                taskUserVo.setUserTime(day + "天" + hour + "小时");
                taskUserVo.setUserTimeDate(new Date(time));
//                }
            }
        });
        return list;
    }

    /**
     * @param taskId 业务id
     *               获取当前用户上次处理业务时间
     */
    private Date getUserTime(Integer taskId) {
        List<TaskLog> list = taskLogDao.getAllByTaskId(taskId);
        if (list.size() > 0) {
            //筛选出当前用户操作该业务的所有日志，根据业务日志的创建时间降序排列，得到最新的上一次操作时间
            List<TaskLog> taskLogs = taskUtils.orderByCreateTimeDesc(list.stream().filter(taskLog -> taskLog.getCreateUserId().equals(userUtils.getCurrentUserId())).collect(Collectors.toList()));
            if (taskLogs.size() == 0) {
                return null;
            }
            return taskLogs.get(0).getCreateTime();
        } else {
            return null;
        }
    }

    /**
     * @param taskSelectVo task查询器
     */
    private Specification<Task> getSelectSpecification(TaskSelectVo taskSelectVo) {
        PredicateBuilder<Task> predicateBuilder = Specifications.and();
        if (taskSelectVo.getBusinessType() != null && taskSelectVo.getBusinessType().size()>0) {
            predicateBuilder.in("businessType", taskSelectVo.getBusinessType().toArray(new Integer[]{}));
        }
        if (taskSelectVo.getContent() != null) {
            Class<Task> taskEntityClass = Task.class;
            Field[] declaredFields = taskEntityClass.getDeclaredFields();
            PredicateBuilder<Task> p = Specifications.or();
            for (Field field : declaredFields) {
                if (field.getType().equals(String.class) && field.getAnnotation(Transient.class) == null) {
                    p.like(field.getName(), "%" + taskSelectVo.getContent() + "%");
                }
            }
            predicateBuilder.predicate(p.build());
        }
        if (taskSelectVo.getStartTime() != null) {
            predicateBuilder.gt("createTime", taskSelectVo.getStartTime());
        }
        if (taskSelectVo.getEndTime() != null) {
            predicateBuilder.lt("createTime", taskSelectVo.getEndTime());
        }
        if (taskSelectVo.getSelectNum() == 4) {
            predicateBuilder.eq("billStatus", StatusEnum.END.id);
        }
        if (taskSelectVo.getSelectNum() == 5) {
            predicateBuilder.eq("billStatus", StatusEnum.ARCHIVE.id);
        }
        if (taskSelectVo.getSelectNum() == 0) {
            predicateBuilder.notIn("billStatus", StatusEnum.ARCHIVE.id);
        }
        if (taskSelectVo.getSelectNum() == 1) {
            predicateBuilder.eq("createUserId", userUtils.getCurrentUserId());
            predicateBuilder.notIn("billStatus", StatusEnum.ARCHIVE.id);
        }
        if (taskSelectVo.getBillStatus()!=null){
            predicateBuilder.eq("billStatus", taskSelectVo.getBillStatus());
        }
        if (taskSelectVo.getRemark()!=null&&taskSelectVo.getRemark().size()>0){
            predicateBuilder.in("remark", taskSelectVo.getRemark());
        }
        return predicateBuilder.build();
    }

    /**
     * 判断list中是否包含某个id的taskUserVo,若不存在返回-1，存在则返回第一次出现的索引值
     */
    int find(Integer id, List<TaskUserVo> list) {
        int index = -1;
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).getId().equals(id)) {
                    index = i;
                    break;
                }
            }
        }
        return index;
    }

    /**
     * @param userIds 用户Id列表
     * @return 返回存在这些用户的单位
     */
    private Set<Integer> getUnitsByUsers(List<Integer> userIds) {
        Set<Integer> unitIds = new HashSet<>();
        userIds.forEach(integer -> {
            if (integer > 0) {
                unitIds.add(userCache.findById(integer).getUnitsId());
            }
        });
        return unitIds;
    }

    public void confirmUser(TaskBto taskBto){
        Integer userId = userUtils.getCurrentUserId();
        List<Integer> userIds = taskBto.getInvolveUserIdList();
        List<Integer> ids = new ArrayList<>();
        if (userIds.size() > 0 && taskBto.getCurrentPoint() < userIds.size()) {
            Integer userId3 = userIds.get(taskBto.getCurrentPoint());
            //当前指针userId大于0，待办人即当前id
            if (userId3 > 0) {
                ids.add(userId3);
            }
            //当前指针userId等于0，待办人为所属单位下所有用户
            else if (userId3 == 0 && taskBto.getOwnUnit() != null) {
                List<User> users = userCache.findAll();
                users.stream().filter(user -> user.getUnitsId().equals(taskBto.getOwnUnit())).forEach(user -> {
                    ids.add(user.getUserId());
                });
            }
        }
//        if (!ids.contains(userId)){
//            throw new ApiException(ResponseEntity.status(50000).body("当前用户不能操作此任务"));
//        }
    }
}
