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

import cn.hutool.core.util.ObjectUtil;
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.TaskBeanConfig;
import com.tykj.dev.config.UpdateCache;
import com.tykj.dev.config.base.DeviceLifeStatus;
import com.tykj.dev.device.library.controller.CacheLibraryController;
import com.tykj.dev.device.library.repository.DeviceLibraryDao;
import com.tykj.dev.device.library.service.DeviceLibraryCacheService;
import com.tykj.dev.device.library.service.DeviceLibraryService;
import com.tykj.dev.device.library.service.DeviceLogService;
import com.tykj.dev.device.library.subject.Dto.DeviceLogDto;
import com.tykj.dev.device.library.subject.domin.DeviceLibrary;
import com.tykj.dev.device.library.subject.vo.*;
import com.tykj.dev.device.library.utils.DeviceNumberUtils;
import com.tykj.dev.device.user.subject.entity.Units;
import com.tykj.dev.device.user.subject.service.UnitsService;
import com.tykj.dev.device.user.subject.service.UserPublicService;
import com.tykj.dev.device.user.util.UserUtils;
import com.tykj.dev.misc.exception.ApiException;
import com.tykj.dev.misc.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
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 javax.persistence.Transient;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Function;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

/**
 * @author dengdiyi
 */
@Service
@Slf4j
public class DeviceLibraryServiceImpl implements DeviceLibraryService {

    @Autowired
    UserUtils userUtils;
    @Autowired
    private DeviceLibraryDao deviceLibraryDao;
    @Autowired
    private UserPublicService userPublicService;

    @Autowired
    private BlockChainUtil blockChainUtil;

    @Autowired
    private UnitsService unitsService;

    @Autowired
    private DeviceLibraryCacheService cacheLibraryService;

    @Autowired
    private DeviceLogService deviceLogService;

    @Autowired
    private DeviceLibraryCacheService deviceLibraryCacheService;

    @Autowired
    @Qualifier("taskExecutor")
    private Executor executor;

    @Override
    @UpdateCache
    public DeviceLibrary addEntity(DeviceLibrary deviceLibraryEntity) {
        DeviceLibrary deviceLibrary = deviceLibraryDao.save(deviceLibraryEntity);
        CompletableFuture.runAsync(()->{
            DeviceLibrary deviceLibrary1 = getOne(deviceLibrary.getId());
            BcHash bcText = blockChainUtil.sendHash(1000, JacksonUtil.toJSon(deviceLibrary1));
            String recordId = bcText.getData().getRecordID();
            deviceLibrary1.setRecordId(recordId);
            deviceLibraryDao.save(deviceLibrary1);
        }, TaskBeanConfig.getThreadPoolTaskScheduler());
        return deviceLibrary;
    }

    /**
     * @param deviceLibraries 异步上链
     */
    @Override
    @Async
    public void sendHash(List<DeviceLibrary> deviceLibraries) {
        deviceLibraries.forEach(deviceLibrary -> {
            BcHash bcText = blockChainUtil.sendHash(1000, JacksonUtil.toJSon(deviceLibrary));
            String recordId = bcText.getData().getRecordID();
            deviceLibrary.setRecordId(recordId);
            update(deviceLibrary);
        });
    }

    @Override
    public Page<DeviceLibrary> getPage(DeviceLibrarySelectVo deviceLibrarySelectVo, Pageable pageable) {
        Specification<DeviceLibrary> selectSpecification = getSelectSpecification(deviceLibrarySelectVo);
        return deviceLibraryDao.findAll(selectSpecification, pageable);
    }

    @Override
    public List<DeviceLibrary> getTagPage(DeviceLibrarySelectVo deviceLibrarySelectVo, Pageable pageable) {
        PredicateBuilder<DeviceLibrary> predicateBuilder = getPredicateBuilder(deviceLibrarySelectVo);
        predicateBuilder.notIn("ownUnit", unitsService.findSuperiorUnitsList().stream().map(Units::getName).toArray());
        return deviceLibraryDao.findAll(predicateBuilder.build());
    }

    @Override
    public List<DeviceLibrary> getCoreDevicePage(DeviceLibrarySelectVo deviceLibrarySelectVo) {
        Integer selectUnitId = deviceLibrarySelectVo.getUnitId();
        Integer selectAreaId = deviceLibrarySelectVo.getAreaId();
        //areaId为null
        if (selectAreaId == null) {
            List<DeviceLibrary> libraryEntities;
            //unitId为null,按照父子结构查询返回当前单位的所有装备
            if (selectUnitId == null) {
                libraryEntities = getList2(deviceLibrarySelectVo);
            }
            //unitId不为null,按照父子结构查询该单位的所有装备
            else {
                String unitName = userPublicService.findByUnitsToname(selectUnitId);
                libraryEntities = getList3(deviceLibrarySelectVo, unitName);
            }

            //按照子装备跟在父装备后面排列返回
//            List<DeviceLibrary> resultList = new ArrayList<>();
//            for (DeviceLibrary d : libraryEntities) {
//                resultList.add(d);
//                if (d.getChilds().size() > 0) {
//                    resultList.addAll(d.getChilds());
//                }
//            }
//            if (deviceLibrarySelectVo.getContent()!=null){
//                resultList = resultList.stream().filter(deviceLibrary -> deviceLibrary.getKeyWords().contains(deviceLibrarySelectVo.getContent())).collect(Collectors.toList());
//            }
//            return GetTreeUtils.splitTree(libraryEntities,DeviceLibrary::getChilds,DeviceLibrary::setChildNull);
            libraryEntities.forEach(DeviceLibrary::setConfigName);
            return libraryEntities;
        }
        //areId不为空，查询某个区域下的所有单位的所有装备
        else {
            //查询区域等级
            Integer selectLevel;
            List<String> units;
            if (selectAreaId==0){
                selectLevel=2;
                units = userPublicService.findAllUnitNameByType2();
            }else {
                 selectLevel = userPublicService.getArea(selectAreaId).getType();
                //查询该区域下的所有单位
                 units = userPublicService.findAllUnitNameByAreaId(selectAreaId);
            }
            //市或县筛选出装备所属单位在units列表中的装备    zsp：或者所在
            if (selectLevel == 3 || selectLevel == 2 || selectLevel ==4) {
                List<DeviceLibrary> libraryEntities = getAllList(deviceLibrarySelectVo).stream()
                        .filter(deviceLibraryEntity -> units.contains(deviceLibraryEntity.getOwnUnit()))
                        .collect(Collectors.toList());
//                List<DeviceLibrary> deviceLibraries = getList4(libraryEntities);
//                List<DeviceLibrary> resultList = new ArrayList<>();
//                for (DeviceLibrary d : deviceLibraries) {
//                    resultList.add(d);
//                    if (d.getChilds().size() > 0) {
//                        resultList.addAll(d.getChilds());
//                    }
//                }
//                if (deviceLibrarySelectVo.getContent()!=null){
//                    resultList = resultList.stream().filter(deviceLibrary -> deviceLibrary.getKeyWords().contains(deviceLibrarySelectVo.getContent())).collect(Collectors.toList());
//                }
//                return GetTreeUtils.splitTree(deviceLibraries,DeviceLibrary::getChilds,DeviceLibrary::setChildNull);
                libraryEntities.forEach(DeviceLibrary::setConfigName);
                return libraryEntities;
            }
            //省能看到所有装备
            if (selectLevel == 1) {
                List<String> unitNames = unitsService.findSuperiorUnitsList().stream().map(Units::getName).collect(Collectors.toList());
                List<DeviceLibrary> deviceLibraries = getAllList(deviceLibrarySelectVo).stream()
                        .filter(deviceLibraryEntity -> !unitNames.contains(deviceLibraryEntity.getOwnUnit()))
                        //过滤出掉毁的装备
                        .filter(deviceLibrary -> !deviceLibrary.getLifeStatus().equals(DeviceLifeStatus.DESTROYED.id))
                        .collect(Collectors.toList());
//                List<DeviceLibrary> libraryEntities = getList4(deviceLibraries);
//                List<DeviceLibrary> resultList = new ArrayList<>();
//                for (DeviceLibrary d : libraryEntities) {
//                    resultList.add(d);
//                    if (d.getChilds().size() > 0) {
//                        resultList.addAll(d.getChilds());
//                    }
//                }
//                if (deviceLibrarySelectVo.getContent()!=null){
//                    resultList = resultList.stream().filter(deviceLibrary -> deviceLibrary.getKeyWords().contains(deviceLibrarySelectVo.getContent())).collect(Collectors.toList());
//                }
//                return GetTreeUtils.splitTree(libraryEntities,DeviceLibrary::getChilds,DeviceLibrary::setChildNull);
                deviceLibraries.forEach(DeviceLibrary::setConfigName);
                return deviceLibraries;
            } else {
                throw new ApiException(ResultUtil.failed("区域等级只能为1，2，3，4"));
            }
        }
    }

    @Override
    public List<DeviceStatisticsVo> getDeviceStatisticsPage(DeviceLibrarySelectVo deviceLibrarySelectVo, Pageable pageable, Sort sort) {
        //获取存在的所有装备型号
//        List<String> list = new ArrayList<>();
//        if (deviceLibrarySelectVo.getModel() != null) {
//            list.add(deviceLibrarySelectVo.getModel());
//        } else {
//            list = getAllModel();
//        }
        //设置最大size的装备查询vo
        List<DeviceStatisticsVo> deviceStatisticsVos = new ArrayList<>();
        DeviceLibrarySelectVo d = new DeviceLibrarySelectVo();
//        BeanUtils.copyProperties(deviceLibrarySelectVo, d);
        d.setSize(Integer.MAX_VALUE);
        d.setPage(0);
        d.setAreaId(deviceLibrarySelectVo.getAreaId());
        d.setUnitId(deviceLibrarySelectVo.getUnitId());
        d.setModel(deviceLibrarySelectVo.getModel());
        d.setName(deviceLibrarySelectVo.getName());
        d.setContent(deviceLibrarySelectVo.getContent());
        d.setType(deviceLibrarySelectVo.getType());
        //获取所有的核心装备
        List<DeviceLibrary> libraryEntities = getCoreDevicePage(d);
        if (libraryEntities.size() > 0) {
//            Map<String, List<DeviceLibrary>> map = libraryEntities.stream().collect(groupingBy(deviceLibrary -> deviceLibrary.getModel()+"Ǵ"+deviceLibrary.getName()));
            Map<String, List<DeviceLibrary>> map = libraryEntities.stream().collect(groupingBy(deviceLibrary -> deviceLibrary.getModel()+"Ǵ"+deviceLibrary.getName()+"Ǵ"+deviceLibrary.getType()+"Ǵ"+deviceLibrary.getMatchingRangeName()+"Ǵ"+deviceLibrary.getIsPart()));
            //按型号遍历统计各种状态的装备数量
            for (String s : map.keySet()) {
                String[] strings = s.split("Ǵ");
                if (strings.length == 5) {
                    DeviceStatisticsVo deviceStatisticsVo = new DeviceStatisticsVo();
                    List<Integer> deviceIds = new ArrayList<>();
                    List<String> devSeqs = new ArrayList<>();
                    deviceStatisticsVo.setModel(strings[0]);
                    deviceStatisticsVo.setName(strings[1]);
                    deviceStatisticsVo.setType(Integer.valueOf(strings[2]));
                    deviceStatisticsVo.setMatchingRangeName(strings[3]);
                    deviceStatisticsVo.setIsPart(Integer.valueOf(strings[4]));
//                    deviceStatisticsVo.setDeviceNumber(map.get(s).size());
//                    deviceStatisticsVo.setDeviceIds(map.get(s).stream().map(DeviceLibrary::getId).collect(Collectors.toList()));
                    int num = 0;
                    int inLibraryNum = 0;
                    int repairNum = 0;
                    int destoryNum = 0;
                    int scrappedNum = 0;
                    int allotNum = 0;
                    int retiredNum = 0;
                    int useNum = 0;
                    List<Integer> inLibraryIds = new ArrayList<>();
                    List<Integer> repairIds = new ArrayList<>();
                    List<Integer> destoryIds = new ArrayList<>();
                    List<Integer> retiredIds = new ArrayList<>();
                    List<Integer> scrappedIds = new ArrayList<>();
                    List<Integer> allotIds = new ArrayList<>();
                    List<Integer> useIds = new ArrayList<>();
                    //遍历核心装备，按照相同型号的装备生命状态统计
                    for (DeviceLibrary d2 : map.get(s)) {
                        deviceIds.add(d2.getId());
                        if (d2.getSeqNumber()!=null) {
                            devSeqs.add(d2.getSeqNumber());
                        }
                        num++;
                        switch (d2.getLifeStatus()) {
                            case 2:
                                inLibraryNum++;
                                inLibraryIds.add(d2.getId());
                                break;
                            case 3:
                                allotNum++;
                                allotIds.add(d2.getId());
                                break;
                            case 4:
                                //如果所属跟所在不一致
                                if (!d2.getLocationUnit().equals(d2.getOwnUnit())){
                                    if (d2.getOwnUnit().equals(userUtils.getCurrentUserUnitName())){
                                        repairNum++;
                                        repairIds.add(d2.getId());
                                    }

                                }else {
                                    repairNum++;
                                    repairIds.add(d2.getId());
                                }
                                break;
                            case 5:
                                scrappedNum++;
                                scrappedIds.add(d2.getId());
                                break;
                            case 17:
                                scrappedNum++;
                                scrappedIds.add(d2.getId());
                                break;
                            case 18:
                                scrappedNum++;
                                scrappedIds.add(d2.getId());
                                break;
                            case 6:
                                retiredNum++;
                                retiredIds.add(d2.getId());
                                break;
                            case 7:
                                retiredNum++;
                                retiredIds.add(d2.getId());
                                break;
                            case 9:
                                destoryNum++;
                                allotIds.add(d2.getId());
                                break;
                            case 10:
                                destoryNum++;
                                destoryIds.add(d2.getId());
                                break;
                            case 19:
                                destoryNum++;
                                destoryIds.add(d2.getId());
                                break;
                            case 20:
                                destoryNum++;
                                destoryIds.add(d2.getId());
                                break;
                            case 13:
                                scrappedNum++;
                                scrappedIds.add(d2.getId());
                                break;
                            case 14:
                                useNum++;
                                useIds.add(d2.getId());
                                break;
                            default:
                                break;
                        }

                    }

                    //添加统计vo
                    if (num > 0) {
                        deviceStatisticsVo.setDeviceIds(deviceIds);
                        deviceStatisticsVo.setAllotIds(allotIds);
                        deviceStatisticsVo.setDestoryIds(destoryIds);
                        deviceStatisticsVo.setInLibraryIds(inLibraryIds);
                        deviceStatisticsVo.setRepairIds(repairIds);
                        deviceStatisticsVo.setRetiredIds(retiredIds);
                        deviceStatisticsVo.setScrappedIds(scrappedIds);
                        deviceStatisticsVo.setUseIds(useIds);
                        deviceStatisticsVo.setDeviceNumber(num);
                        deviceStatisticsVo.setAllotNum(allotNum);
                        deviceStatisticsVo.setInLibraryNum(inLibraryNum);
                        deviceStatisticsVo.setRepairNum(repairNum);
                        deviceStatisticsVo.setDestoryNum(destoryNum);
                        deviceStatisticsVo.setScrappedNum(scrappedNum);
                        deviceStatisticsVo.setRetiredNum(retiredNum);
                        deviceStatisticsVo.setUseNum(useNum);
                        deviceStatisticsVo.setOtherNum(num-allotNum-inLibraryNum-repairNum-destoryNum-scrappedNum-retiredNum-useNum);
                        deviceIds.removeAll(allotIds);
                        deviceIds.removeAll(destoryIds);
                        deviceIds.removeAll(inLibraryIds);
                        deviceIds.removeAll(repairIds);
                        deviceIds.removeAll(retiredIds);
                        deviceIds.removeAll(scrappedIds);
                        deviceIds.removeAll(useIds);
                        deviceStatisticsVo.setOtherNumIds(deviceIds);
                        deviceStatisticsVo.setSeqs(StringSplitUtil.stringListToString(DeviceSeqUtil.getContinuousSeqs(devSeqs)));


                        deviceStatisticsVos.add(deviceStatisticsVo);
                    }
                }
            }
            if (deviceLibrarySelectVo.getName() != null) {
                deviceStatisticsVos = selectByName(deviceLibrarySelectVo.getName(), deviceStatisticsVos);
            }
            return deviceStatisticsVos;
        }
        return deviceStatisticsVos;
    }

    @Override
    public List<String> getAllName() {
        List<DeviceLibrary> list = deviceLibraryDao.findAll();
        //用Set存装备名称，排除重复名称
        Set<String> s = new HashSet<>();
        for (DeviceLibrary d : list) {
            s.add(d.getName());
        }
        return new ArrayList<>(s);
    }

    @Override
    public List<DeviceLibrary> getList(DeviceLibrarySelectVo deviceLibrarySelectVo) {
        //返回父子结构
//        Map<Integer, DeviceLibrary> nodeCollect =
//                deviceLibraryEntities.stream().collect(Collectors.toMap(DeviceLibrary::getId, deviceLibraryEntity -> deviceLibraryEntity));
//        return GetTreeUtils.parseTreeFromDown(
//                deviceLibraryEntities,
//                DeviceLibrary::getId,
//                deviceLibraryEntity -> Optional.ofNullable(nodeCollect.get(deviceLibraryEntity.getPartParentId())),
//                DeviceLibrary::addChildNode
//        );
        return deviceLibraryDao.findAll(getSelectSpecification(deviceLibrarySelectVo),deviceLibrarySelectVo.getPageable().getSort());
    }

    public List<DeviceLibrary> getList2(DeviceLibrarySelectVo deviceLibrarySelectVo) {
        List<DeviceLibrary> deviceLibraryEntities = deviceLibraryDao.findAll(getSelectSpecification6(deviceLibrarySelectVo),deviceLibrarySelectVo.getPageable().getSort());
        //返回父子结构
//        Map<Integer, DeviceLibrary> nodeCollect =
//                deviceLibraryEntities.stream().collect(Collectors.toMap(DeviceLibrary::getId, deviceLibraryEntity -> deviceLibraryEntity));
//        return GetTreeUtils.parseTreeFromDown(
//                deviceLibraryEntities,
//                DeviceLibrary::getId,
//                deviceLibraryEntity -> Optional.ofNullable(nodeCollect.get(deviceLibraryEntity.getPartParentId())),
//                DeviceLibrary::addChildNode
//        );
        return deviceLibraryEntities;
    }

    public List<DeviceLibrary> getList3(DeviceLibrarySelectVo deviceLibrarySelectVo, String name) {
        List<DeviceLibrary> deviceLibraryEntities = deviceLibraryDao.findAll(getSelectSpecification2(deviceLibrarySelectVo, name),deviceLibrarySelectVo.getPageable().getSort());
        //返回父子结构
//        Map<Integer, DeviceLibrary> nodeCollect =
//                deviceLibraryEntities.stream().collect(Collectors.toMap(DeviceLibrary::getId, deviceLibraryEntity -> deviceLibraryEntity));
//        return GetTreeUtils.parseTreeFromDown(
//                deviceLibraryEntities,
//                DeviceLibrary::getId,
//                deviceLibraryEntity -> Optional.ofNullable(nodeCollect.get(deviceLibraryEntity.getPartParentId())),
//                DeviceLibrary::addChildNode
//        );
        return deviceLibraryEntities;
    }

    public List<DeviceLibrary> getList4(List<DeviceLibrary> deviceLibraryEntities) {
        //以父子结构返回
        Map<Integer, DeviceLibrary> nodeCollect =
                deviceLibraryEntities.stream().collect(Collectors.toMap(DeviceLibrary::getId, deviceLibraryEntity -> deviceLibraryEntity));
        return GetTreeUtils.parseTreeFromDown(
                deviceLibraryEntities,
                DeviceLibrary::getId,
                deviceLibraryEntity -> Optional.ofNullable(nodeCollect.get(deviceLibraryEntity.getPartParentId())),
                DeviceLibrary::addChildNode
        );
    }

    @Override
    public List<DeviceLibrary> getListWithoutParent(DeviceLibrarySelectVo deviceLibrarySelectVo) {
        return deviceLibraryDao.findAll(getSelectSpecification(deviceLibrarySelectVo));
    }

    @Override
    public List<String> getAllUnit() {
        List<DeviceLibrary> list = deviceLibraryDao.findAll();
        //用set存储所属单位，排除重复单位
        Set<String> s = new HashSet<>();
        for (DeviceLibrary d : list) {
            s.add(d.getOwnUnit());
        }
        return new ArrayList<>(s);
    }

    /**
     * 查询在库所有装备的型号
     */
    @Override
    public List<String> getAllInLibraryModels() {
        List<DeviceLibrary> deviceLibraryEntities = deviceLibraryDao.findAll(getAllotSelectSpecification(new DeviceLibrarySelectVo()));
        //用Set存装备型号，排除重复名称
        Set<String> s = new HashSet<>();
        for (DeviceLibrary d : deviceLibraryEntities) {
            s.add(d.getModel());
        }
        return new ArrayList<>(s);
    }

    /**
     * 查询可清退装备
     */
    @Override
    public List<DeviceLibrary> getSendBackDevice(DeviceLibrarySelectVo deviceLibrarySelectVo) {
        return deviceLibraryDao.findAll(getSelectSpecification3(deviceLibrarySelectVo));
    }

    /**
     * 判断装备状态是否在库
     *
     * @param ids 装备id集合
     */
    @Override
    public void isInStock(List<Integer> ids) {
        ids.forEach(integer -> {
            DeviceLibrary deviceLibrary = getOne(integer);
            if (deviceLibrary.getLifeStatus()!=2&&deviceLibrary.getLifeStatus()!=14){
                throw new ApiException(ResponseEntity.status(303).body("序列号"+deviceLibrary.getSeqNumber()+"的装备已被其他专管员操作"));
            }
        });
    }

    /**
     * 判断装备状态是否待退役
     *
     * @param ids 装备id集合
     */
    @Override
    public void isWaitRetired(List<Integer> ids) {
        ids.forEach(integer -> {
            DeviceLibrary deviceLibrary = getOne(integer);
            if (deviceLibrary.getLifeStatus()!=15){
                throw new ApiException(ResponseEntity.status(303).body("序列号"+deviceLibrary.getSeqNumber()+"的装备已被其他专管员操作"));
            }
        });
    }

    /**
     * 判断装备状态是否在库或待退役（若不是抛出303异常）
     *
     * @param ids 装备id集合
     */
    @Override
    public void isInStockOrWaitRetired(List<Integer> ids) {
        ids.forEach(integer -> {
            DeviceLibrary deviceLibrary = getOne(integer);
            if (deviceLibrary.getLifeStatus()!=2 && deviceLibrary.getLifeStatus()!=15&&deviceLibrary.getLifeStatus()!=14 && !deviceLibrary.getLifeStatus().equals(DeviceLifeStatus.SEND_BACK.id)){
                throw new ApiException(ResponseEntity.status(303).body("序列号"+deviceLibrary.getSeqNumber()+"的装备已被其他专管员操作"));
            }
        });
    }

    /**
     * 判断装备状态是否在库或维修中
     *
     * @param ids 装备id集合
     */
    @Override
    public void isInStockOrRepairing(List<Integer> ids) {
        ids.forEach(integer -> {
            DeviceLibrary deviceLibrary = getOne(integer);
            if (deviceLibrary.getLifeStatus()!=2&&deviceLibrary.getLifeStatus()!=4&&deviceLibrary.getLifeStatus()!=14){
                throw new ApiException(ResponseEntity.status(303).body("序列号"+deviceLibrary.getSeqNumber()+"的装备已被其他专管员操作"));
            }
        });
    }

    @Override
    public void isFirstRepair(List<Integer> ids) {
        ids.forEach(integer -> {
            DeviceLibrary deviceLibrary = getOne(integer);
            if (deviceLibrary.getLifeStatus() ==4){
                throw new ApiException(ResponseEntity.status(303).body("序列号"+deviceLibrary.getSeqNumber()+"的装备已被其他专管员操作"));
            }
        });
    }

    @Override
    public int getDeviceCount() {
        PredicateBuilder<DeviceLibrary> predicateBuilder = Specifications.and();
        predicateBuilder.notIn("lifeStatus", 0,1,5,6,10,11,12,13);
        return deviceLibraryDao.findAll(predicateBuilder.build()).size();
    }

    @Override
    public Map<Integer, DeviceLibrary> getAllDeviceMap() {
//        List<DeviceLibrary> libraries = deviceLibraryDao.findAll();
        List<DeviceLibrary> libraries = cacheLibraryService.getAllDeviceLibraryList();
        libraries.forEach(DeviceLibrary::setConfigName);
        return libraries.stream().collect(Collectors.toMap(DeviceLibrary::getId, Function.identity()));
    }

    /**
     * 获取所有装备序列号map
     */
    @Override
    public Map<String, DeviceLibrary> getAllDeviceSeqMap() {
//        List<DeviceLibrary> libraries = deviceLibraryDao.findAll();
        List<DeviceLibrary> libraries = cacheLibraryService.getAllDeviceLibraryList();
        List<String> seqs = new ArrayList<>();
        Iterator<DeviceLibrary> iterator = libraries.iterator();
        while (iterator.hasNext()){
            DeviceLibrary d = iterator.next();
            if (!seqs.contains(d.getSeqNumber())) {
                seqs.add(d.getSeqNumber());
                d.setConfigName();
            }
            else {
                iterator.remove();
            }
        }
//        libraries.forEach(DeviceLibrary::setConfigName);
        return libraries.stream().filter(deviceLibrary -> deviceLibrary.getSeqNumber()!=null&&!"".equals(deviceLibrary.getSeqNumber())).collect(Collectors.toMap(DeviceLibrary::getSeqNumber, Function.identity()));
    }

    @Override
    public Integer countAllRepel(List<Integer> fieldingIds, List<String> unitNames, List<String> seqNums,List<Integer> lifeStatusList) {
        //判断装备序列号是否为空 是 走列装id查询。
        if (seqNums!=null && seqNums.size()!=0){
          return  deviceLibraryDao.countAllBySeqNumberInAndOwnUnitInAndLifeStatusIn(seqNums,unitNames,lifeStatusList);
        }else {
            return deviceLibraryDao.countAllByPackingIdInAndOwnUnitInAndLifeStatusIn(fieldingIds,unitNames,lifeStatusList);
        }
    }

    @Override
    public List<DeviceLibrary> findAllBySeqNumber(List<String> seqNumbers) {
        return deviceLibraryDao.findAllBySeqNumberIn(seqNumbers);
    }

    @Override
    public void judgeSeqNumbersInNotEqualLifeStatus(List<String> seqNumbers, Integer leftStatus) {
        if(!deviceLibraryDao.existsAllBySeqNumberInAndLifeStatus(seqNumbers, leftStatus)){
            throw new ApiException(ResponseEntity.status(303).body("装备已被其他同单位专管员操作"));
        }
    }

    @Override
    public List<DeviceLibrary> getAllDevByDevIds(List<Integer> ids) {
        List<DeviceLibrary> allByIdIn = deviceLibraryDao.findAllByIdIn(ids);
        return allByIdIn;
    }

    @Override
    @UpdateCache
    public void updateLifeStatus(Integer lifeStatus,Integer id) {
        deviceLibraryDao.batchUpdate(lifeStatus,id);
    }

    @Override
    @UpdateCache
    public void updateLifeStatus2(Integer lifeStatus, List<Integer> ids) {
         deviceLibraryDao.batchUpdate2(lifeStatus,ids);
    }

    @Override
    public List<DeviceLibrary> findByIds(List<Integer> ids) {

        return deviceLibraryDao.findAllByIdIn(ids);
    }

    @Override
    public DeviceLibrary findBySeqNumber(String seqNumber) {
        return deviceLibraryDao.findBySeqNumber(seqNumber);
    }

    @Override
    @Cacheable()
    public List<DeviceLibrary> getAllDeviceList(DeviceLibrarySelectVo deviceLibrarySelectVo) {
        long l = System.currentTimeMillis();
//        List<DeviceLibrary> all = deviceLibraryDao.findAll();
        List<DeviceLibrary> all = cacheLibraryService.getAllDeviceLibraryList();
        System.out.println("查询时间为"+(System.currentTimeMillis()-l));
        return all;
    }

    @Override
    public List<DeviceLibrary> findAllByPackingId(Integer packingId) {
        return  deviceLibraryDao.findAllByPackingId(packingId);
    }

    @Override
    public List<DeviceLibrary> findAllByPackingIdsIn(List<Integer> packingIds, Pageable pageable) {
        return deviceLibraryDao.findAllByPackingIdIn(packingIds,pageable);
    }

    @Override
    public List<DeviceLibrary> findAllByPackingIdsIn(List<Integer> packingIds) {
        return deviceLibraryDao.findAllByPackingIdIn(packingIds);
    }

//    @Override
//    public List<DeviceLibrary> findAllByPackingIdsIn(List<Integer> packingIds,Pageable pageable) {
//        return deviceLibraryDao.findAllByPackingIdIn(packingIds,pageable);
//    }

    @Override
    public List<DeviceLibrary> findAllByPartParentId(Integer id) {
        return  deviceLibraryDao.findAllByPartParentId(id);
    }

//    @Override
//    public List<DeviceLibrary> findAllByPackingId2(List<Integer> packingIds) {
//        //查询可以使用并且在库 是所在或者所属是自己的
////        List<DeviceLibrary> deviceLibraries = deviceLibraryDao.findAllByPackingIdIn(packingIds).stream().filter(
////                        deviceLibrary -> deviceLibrary.getLifeStatus() == 2
////                ).filter(deviceLibrary -> deviceLibrary.getOwnUnit().equals(userUtils.getCurrentUserUnitName()))
////                .filter(deviceLibrary -> deviceLibrary.getLocationUnit().equals(userUtils.getCurrentUserUnitName()))
////                .collect(Collectors.toList());
//        //筛选出当前单位在库的装备
//        DeviceLibrarySelectVo deviceLibrarySelectVo = new DeviceLibrarySelectVo();
//        deviceLibrarySelectVo.setLifeStatus(Collections.singletonList(2));
//        long l = System.currentTimeMillis();
//        List<DeviceLibrary> deviceLibraries = getList(deviceLibrarySelectVo);
//        System.out.println("查询在库时间"+(System.currentTimeMillis()-l));
//        //转为列装id的map
//        Map<Integer,List<DeviceLibrary>> map = deviceLibraries.stream().collect(groupingBy(DeviceLibrary::getPackingId));
//
//        return  deviceLibraries;
//    }

    @Override
    public  Map<Integer,List<DeviceLibrary>> findAllByPackingId3() {
        //筛选出当前单位在库的装备
        List<DeviceLibrary> deviceLibraryList = cacheLibraryService.getAllDeviceLibraryList();
        String currentUserUnitName = userUtils.getCurrentUserUnitName();
        List<DeviceLibrary> deviceLibraries = deviceLibraryList.stream().filter(deviceLibrary -> deviceLibrary.getLifeStatus() == 2)
                .filter(deviceLibrary -> deviceLibrary.getLocationUnit().equals(currentUserUnitName)
                        || deviceLibrary.getOwnUnit().equals(currentUserUnitName))
                .collect(Collectors.toList());
        //转为列装id的map
        Map<Integer,List<DeviceLibrary>> map = deviceLibraries.stream().collect(groupingBy(DeviceLibrary::getPackingId));
        return  map;
    }

    @Override
    @UpdateCache
    public void batchUpdateDevices(String oldModel,String newModel) {
        deviceLibraryDao.batchUpdateDevices(oldModel,newModel);
    }

    @Override
    public List<DeviceLibrary> findAllByModel(String model) {
        return deviceLibraryDao.findAllByModel(model);
    }

    @Override
    public void isNotLoss(List<Integer> ids) {
        ids.forEach(integer -> {
            DeviceLibrary deviceLibrary = getOne(integer);
            if (deviceLibrary.getLifeStatus()!=11){
                throw new ApiException(ResponseEntity.status(303).body("序列号"+deviceLibrary.getSeqNumber()+"的装备已被其他专管员操作"));
            }
        });
    }

    @Override
    public List<DeviceLibrary> getAllList(DeviceLibrarySelectVo deviceLibrarySelectVo) {
//        List<DeviceLibrary> allDeviceLibraryList = cacheLibraryService.getAllDeviceLibraryList();
        return deviceLibraryDao.findAll(getSelectSpecification4(deviceLibrarySelectVo),deviceLibrarySelectVo.getPageable().getSort());
//        return allDeviceLibraryList;
    }

    @Override
    public List<DeviceLibrary> getCheckList() {
        PredicateBuilder<DeviceLibrary> predicateBuilder = Specifications.and();
        predicateBuilder.eq("ownUnit", userUtils.getCurrentUserUnitName());
        predicateBuilder.eq("lifeStatus", 2);
        return deviceLibraryDao.findAll(predicateBuilder.build());
    }

    /**
     * 获取单位自查未在库装备列表
     */
    @Override
    public List<DeviceLibrary> getNotInStockList() {
        PredicateBuilder<DeviceLibrary> predicateBuilder = Specifications.and();
        predicateBuilder.eq("ownUnit", userUtils.getCurrentUserUnitName());
        predicateBuilder.notIn("lifeStatus", 2);
        return deviceLibraryDao.findAll(predicateBuilder.build());
    }

    @Override
    public List<DeviceLibrary> getAllotList(DeviceLibrarySelectVo deviceLibrarySelectVo) {
        List<DeviceLibrary> deviceLibraryEntities = deviceLibraryDao.findAll(getAllotSelectSpecification(deviceLibrarySelectVo));
        deviceLibraryEntities.forEach(DeviceLibrary::setConfigName);
        Map<Integer, DeviceLibrary> nodeCollect =
                deviceLibraryEntities.stream().collect(Collectors.toMap(DeviceLibrary::getId, deviceLibraryEntity -> deviceLibraryEntity));
        return GetTreeUtils.parseTreeFromDown(
                deviceLibraryEntities,
                DeviceLibrary::getId,
                deviceLibraryEntity -> Optional.ofNullable(nodeCollect.get(deviceLibraryEntity.getPartParentId())),
                DeviceLibrary::addChildNode
        );
    }

    @Override
    public List<DeviceLibrary> getListByBillId(Integer id) {
        PredicateBuilder<DeviceLibrary> predicateBuilder = Specifications.and();
        predicateBuilder.eq("storageBillId", id);
        return deviceLibraryDao.findAll(predicateBuilder.build());
    }

    @Override
    @UpdateCache
    public void updateDevicesOwnUnit(List<Integer> deviceIds) {
        deviceLibraryDao.updateDevicesOwnUnit(deviceIds);
    }


    @Override
    public List<DeviceLibrary> findAllDeviceLibraryList() {
        return deviceLibraryDao.findAll().stream().map(DeviceLibrary::setConfigName).collect(Collectors.toList());
    }

    @Override
    @UpdateCache
    public void updateLocalAndOwn(String localUnit,List<Integer> deviceIds) {
        deviceLibraryDao.updateDevicesOwnUnit(localUnit,deviceIds);
    }

    @Override
    public int getMaxSeqNumber(String model) {
        List<DeviceLibrary> devices = deviceLibraryDao.findAllByModel(model);

        return devices.stream()
                .max(Comparator.comparing(DeviceNumberUtils::extractSeqNumber))
                .map(d->DeviceNumberUtils.parseSeq2Number(d.getSeqNumber()))
                .orElse(0);


//        return devices.stream()
//                .map(deviceLibrary -> deviceLibrary.getSeqNumber().substring(deviceLibrary.getSeqNumber().length()-4))
//                .sorted(Comparator.comparing(String::toString).reversed())
//                .collect(Collectors.toList());
    }

    @Override
    public List<String> getMaxPartSeqNumber(String model, Integer isPart) {
        //查询配件型号中是否存在随机生成4位数的
        List<DeviceLibrary> deviceLibraries = deviceLibraryDao.findByModelAndIsPart(model, isPart);
        //如果是老数据则是从0开始  老数据就是12035412   新的数据就是AA021234

        return  deviceLibraries.stream().filter(deviceLibrary -> deviceLibrary.getSeqNumber().contains(model))
                .map(deviceLibrary -> deviceLibrary.getSeqNumber().substring(deviceLibrary.getSeqNumber().length()-4))
                .sorted(Comparator.comparing(String::toString).reversed())
                .collect(Collectors.toList());


    }

    @Override
    public List<DeviceLibrary> findDevicesByPacking(Integer packing) {
        return  deviceLibraryDao.findAllByPackingId(packing);
    }

    @Override
    @UpdateCache
    public void updateMatchingRange(List<DeviceLibrary> libraries) {

    }

//    @Override
//    @UpdateCache
//    public void relieveDevice(int deviceId) {
//        Integer currentUserId = userUtils.getCurrentUserId();
//        //根据装备id查询附件
//        List<DeviceLibrary> deviceLibraries = deviceLibraryDao.findAllByPartParentId(deviceId);
//        deviceLibraries.forEach(deviceLibrary -> {
//            deviceLibrary.setPartParentId(null);
//            update(deviceLibrary);
//            //添加日志
//            String remark = "该装备进行解绑";
//            DeviceLogDto deviceLogDto = new DeviceLogDto(deviceId, remark, null,currentUserId,null);
//            deviceLogService.addLog(deviceLogDto);
//        });
//    }

//    @Override
//    @UpdateCache
//    public void bindingDevice(BindingDeviceVo bindingDeviceVo) {
//        Integer currentUserId = userUtils.getCurrentUserId();
//        //查询需要绑定的装备的型号和被绑定的装备的型号
//        DeviceLibrary originDev = deviceLibraryDao.findById(bindingDeviceVo.getOriginDeviceId()).get();
//        DeviceLibrary toDev = deviceLibraryDao.findById(bindingDeviceVo.getToDeviceId()).get();
//        if (!originDev.getModel().equals(toDev.getModel())){
//            //型号进行修改
//            List<DeviceLibrary> libraries = deviceLibraryDao.findAllByPartParentId(originDev.getId());
//            libraries.forEach(deviceLibrary -> {
//                deviceLibrary.setModel(toDev.getModel());
//                update(deviceLibrary);
//            });
//            String remark = "由于需要进行装备的绑定，原来型号修改为"+toDev.getModel();
//            DeviceLogDto deviceLogDto = new DeviceLogDto(toDev.getId(), remark, null,currentUserId,null);
//            deviceLogService.addLog(deviceLogDto);
//        }
//        originDev.setModel(toDev.getModel());
//        originDev.setPartParentId(toDev.getId());
//        update(originDev);
//        //添加日志
//        String remark = "原装备和"+toDev.getName()+"的装备进行绑定";
//        DeviceLogDto deviceLogDto = new DeviceLogDto(toDev.getId(), remark, null,currentUserId,null);
//        deviceLogService.addLog(deviceLogDto);
//    }

    @Override
    @UpdateCache
    public void upDateSeqNumbersApplyTaskId(Integer taskId, List<String> seqNumbers) {
        deviceLibraryDao.upDateSeqNumbersApplyTaskId(taskId,seqNumbers);
    }

    @Override
    public List<DeviceLibrary> findAllByOwnUnit(String ownUnit) {
        return deviceLibraryDao.findAllByOwnUnit(ownUnit);
    }

    @Override
    public List<DeviceLibrary> getAllByRfidCardId(String rfidCardId) {
        return deviceLibraryDao.getAllByRfidCardId(rfidCardId);
    }

    @Override
    @UpdateCache
    public int upDateLeftStatus(Integer lifeStatus, List<Integer> idList) {
        return deviceLibraryDao.upDateLeftStatus(lifeStatus,idList);
    }

    @Override
    @UpdateCache
    public int upDateSeqNumbersLeftStatus(Integer lifeStatus, List<String> seqNumbers) {
        return deviceLibraryDao.upDateSeqNumbersLeftStatus(lifeStatus,seqNumbers);
    }

    @Override
    @UpdateCache
    public int upDateLeftStatusAndLockStatus(Integer lifeStatus, Integer lock, List<Integer> idList) {
        return deviceLibraryDao.upDateLeftStatusAndLockStatus(lifeStatus,lock,idList);
    }

    @Override
    @UpdateCache
    public int upDateLockStatus(Integer lock, List<Integer> idList) {
        return deviceLibraryDao.upDateLockStatus(lock,idList);
    }

    @Override
    @UpdateCache
    public int upDateLeftStatusAndUnitNameAndLockStatus(Integer lifeStatus, String unitName, Integer lock, List<Integer> idList) {
        return deviceLibraryDao.upDateLeftStatusAndUnitNameAndLockStatus(lifeStatus,unitName,lock,idList);
    }

    @Override
    @UpdateCache
    public int upDateSeqNumbersLeftStatusAndUnitNameAndLockStatus(Integer lifeStatus, String unitName, Integer lock, List<String> seqNumbers) {
        return deviceLibraryDao.upDateSeqNumbersLeftStatusAndUnitNameAndLockStatus(lifeStatus,unitName,lock,seqNumbers);
    }

    @Override
    @UpdateCache
    public int upDateLeftStatusAndOwnUnitName(Integer lifeStatus, String unitName, List<Integer> idList) {
        return deviceLibraryDao.upDateLeftStatusAndOwnUnitName(lifeStatus,unitName,idList);
    }

    @Override
    @UpdateCache
    public int upDateRfidSurfaceIdAsSeqNumber(List<Integer> idList) {
        return deviceLibraryDao.upDateRfidSurfaceIdAsSeqNumber(idList);
    }

    @Override
    @UpdateCache
    public int upDateName(String name, Integer packingId) {
        return deviceLibraryDao.upDateName(name,packingId);
    }

    @Override
    @UpdateCache
    public int upDateMatchingRange(Integer matchingRange, Integer packingId) {
        return deviceLibraryDao.upDateMatchingRange(matchingRange,packingId);
    }

    @Override
    @UpdateCache
    public int batchUpdate(Integer lifeStatus, Integer id) {
        return deviceLibraryDao.batchUpdate(lifeStatus,id);
    }

    @Override
    @UpdateCache
    public int batchUpdate2(Integer lifeStatus, List<Integer> ids) {
        return deviceLibraryDao.batchUpdate2(lifeStatus,ids);
    }

    @Override
    @UpdateCache
    public int updateMatchingRange(Integer matchingRange, Integer packingId) {
        return deviceLibraryDao.updateMatchingRange(matchingRange,packingId);
    }

    @Override
    @UpdateCache
    public int updateMatchingRange2(Integer matchingRange, List<Integer> deviceIds) {
        return deviceLibraryDao.updateMatchingRange2(matchingRange,deviceIds);
    }

    @Override
    @UpdateCache
    public int updateModelAndPackingId(String newModel, Integer packingId, List<Integer> deviceIds) {
        return deviceLibraryDao.updateModelAndPackingId(newModel,packingId,deviceIds);
    }

    @Override
    @UpdateCache
    public int updatePackingId(Integer packingId, List<Integer> deviceIds) {
        return deviceLibraryDao.updatePackingId(packingId,deviceIds);
    }

    @Override
    public List<DeviceLibrary> findAllDevices() {
        return cacheLibraryService.getAllDeviceLibraryList();
    }

    @Override
    @UpdateCache
    public void updatePartParentId(List<Integer> deviceIds) {
        deviceLibraryDao.updatePartParentId(deviceIds);
    }

    @Override
    @UpdateCache
    public void unboundDevice(List<DeviceLibrary> deviceLibraries) {
        //将附件的父id设置为null
        if (deviceLibraries.size()>0){
            deviceLibraries.forEach(deviceLibrary -> {
                deviceLibrary.setPartParentId(null);
                update(deviceLibrary);
            });
        }else {
            throw new ApiException("请选择解绑的装备");
        }
    }

    @Override
    @UpdateCache
    public void boundDevice(BindingDeviceVo bindingDeviceVo) {
        //取出装备的id
        DeviceLibrary orginDeviceLibrary = bindingDeviceVo.getOrginDeviceLibrary();
        Integer id = orginDeviceLibrary.getId();
        //将附件的父id设置为装备的id
        List<DeviceLibrary> deviceLibraries = bindingDeviceVo.getDeviceLibraries();
        deviceLibraries.forEach(deviceLibrary -> {
            deviceLibrary.setPartParentId(id);
            deviceLibrary.setModel(orginDeviceLibrary.getModel());
            update(deviceLibrary);
        });
    }

    @Override
    public List<DeviceLibrary> getAllBySeqNumber(String rfid) {
        return deviceLibraryDao.getAllBySeqNumber(rfid);
    }

    @Override
    public List<DeviceLibrary> findAllByIds(List<Integer> ids) {
        return deviceLibraryDao.findAllByIdIn(ids);
    }

    @Override
    @UpdateCache
    public void updateTry(List<DeviceLibrary> deviceLibraries) {
        deviceLibraries.forEach(deviceLibrary -> {
            deviceLibrary.setTryOutDevice(0);
            update(deviceLibrary);
        });
    }

    @Override
    public List<DeviceLibrary> getAlldevList(DeviceLibrarySelectVo deviceLibrarySelectVo) {
        List<DeviceLibrary> deviceLibraryList = cacheLibraryService.getAllDeviceLibraryList();
        List<Integer> status = new ArrayList<>(Arrays.asList(2, 11, 14));
        String currentUserUnitName = userUtils.getCurrentUserUnitName();
        if (deviceLibrarySelectVo.getLifeStatus().size()>0){
            List<Integer> lifeStatus = deviceLibrarySelectVo.getLifeStatus();
            deviceLibraryList = deviceLibraryList.stream().filter(deviceLibrary ->
                            deviceLibrary.getOwnUnit().equals(currentUserUnitName) &&
                                    deviceLibrary.getLocationUnit().equals(currentUserUnitName) &&
                                    lifeStatus.contains(deviceLibrary.getLifeStatus()))
                    .collect(Collectors.toList());
        }else {
            deviceLibraryList = deviceLibraryList.stream().filter(deviceLibrary ->
                            deviceLibrary.getOwnUnit().equals(currentUserUnitName) &&
                                    deviceLibrary.getLocationUnit().equals(currentUserUnitName) &&
                                    status.contains(deviceLibrary.getLifeStatus()))
                    .collect(Collectors.toList());
        }

//        DeviceLibraryCacheSelectVo deviceLibraryCacheSelectVo = new DeviceLibraryCacheSelectVo();
//        BeanUtils.copyProperties(deviceLibrarySelectVo,deviceLibraryCacheSelectVo);
            List<DeviceLibrary> list = null;
            try {
                long l = System.currentTimeMillis();
                list = filterFields(deviceLibraryList, deviceLibrarySelectVo);
//                list = filterFields2(deviceLibraryList, deviceLibraryCacheSelectVo);
                log.info("过滤时间为：{}",(System.currentTimeMillis()-l));
            } catch (Exception e) {
                e.printStackTrace();
            }
            return list;
    }

    @Override
    @UpdateCache
    public void updateSeqNumber(List<DeviceForApplyVo> deviceForApplyVos) {
        List<String> inputSeq = deviceForApplyVos.stream()
                .filter(deviceForApplyVo -> deviceForApplyVo.getIsUpdate() == 0)
                .map(DeviceForApplyVo::getSeqNumber)
                .collect(Collectors.toList());
        //数据库中的seq
        List<String> existSeq = cacheLibraryService.getAllDeviceLibraryList().stream()
                .map(DeviceLibrary::getSeqNumber)
                .collect(Collectors.toList());
        Integer userId = userUtils.getCurrentUserId();
        List<DeviceLogDto> deviceLogDtos = new ArrayList<>();
        //取交集
        inputSeq.retainAll(existSeq);
        if (inputSeq.size()>0){
            String join = String.join(",", inputSeq);
            throw new ApiException(join+"序列号已经存在");
        }else {
            //进行更新装备
            deviceForApplyVos.forEach(deviceForApplyVo -> {
                //如果前后修改的序列号一样  则不发送阅知
                Integer deviceId = deviceForApplyVo.getDeviceId();
                String seqNumber = deviceForApplyVo.getSeqNumber();
                DeviceLibrary one = getOne(deviceId);
                if(!one.getSeqNumber().equals(seqNumber)){
                    //添加装备日志
                    DeviceLogDto deviceLogDto = new DeviceLogDto();
                    deviceLogDto.setDeviceId(deviceId);
                    deviceLogDto.setRemark("将原来的序列号"+one.getSeqNumber()+"修改为"+seqNumber);
                    deviceLogDto.setCreateUserId(userId);
                    one.setSeqNumber(seqNumber);
                    update(one);
                    deviceLogDtos.add(deviceLogDto);
                }
            });
        }
        executor.execute(()->{
            deviceLogService.addAllLog(deviceLogDtos);
        });

    }

    @Override
    @UpdateCache
    public void updateStorageLocation(UpdateStorageLocationVo updateStorageLocationVo) {
        List<Integer> deviceIds = updateStorageLocationVo.getDeviceIds();
        Integer userId = userUtils.getCurrentUserId();
        List<DeviceLogDto> deviceLogDtos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(deviceIds)){
            //添加装备日志
            deviceIds.forEach(integer -> {
                DeviceLogDto deviceLogDto= new DeviceLogDto(integer,"将存放位置修改为"+
                        updateStorageLocationVo.getStorageLocation(),null,userId);
                deviceLogDtos.add(deviceLogDto);
            });
            deviceLibraryDao.updateStorageLocation(updateStorageLocationVo.getStorageLocation(),deviceIds);
        }else {
            throw new ApiException("请选择要修改的装备");
        }
        CompletableFuture.runAsync(()->{
            deviceLogService.addAllLog(deviceLogDtos);
        });
    }

//    @Override
//    @UpdateCache
//    public int updatePartParentId(List<Integer> deviceIds) {
//        return deviceLibraryDao.updatePartParentId(deviceIds);
//    }


    @Override
    @UpdateCache
    public DeviceLibrary update(DeviceLibrary deviceLibraryEntity) {
        DeviceLibrary deviceLibrary = deviceLibraryDao.save(deviceLibraryEntity);
        CompletableFuture.runAsync(()->blockChainUtil.appendHash(JacksonUtil.toJSon(deviceLibrary),deviceLibrary.getRecordId()),TaskBeanConfig.getThreadPoolTaskScheduler());
        return deviceLibrary;
    }

    @Override
    public DeviceLibrary getOne(Integer id) {
        Optional<DeviceLibrary> deviceLibraryEntity = deviceLibraryDao.findById(id);
        if (deviceLibraryEntity.isPresent()){
            return deviceLibraryEntity.get().setConfigName();
        }
        else {
            throw new ApiException("查询的装备Id不存在");
        }
    }

    @Override
    @UpdateCache
    public void delete(Integer id) {
        deviceLibraryDao.deleteById(id);
    }

    private Specification<DeviceLibrary> getSelectSpecification(DeviceLibrarySelectVo deviceLibrarySelectVo) {
        PredicateBuilder<DeviceLibrary> predicateBuilder = getPredicateBuilder(deviceLibrarySelectVo);
        //unitId为空，默认查询当前单位
        if (deviceLibrarySelectVo.getUnitId() == null) {
            String unit = userUtils.getCurrentUserUnitName();
            predicateBuilder.eq("ownUnit", unit);
            predicateBuilder.eq("locationUnit", unit);
        } else {
            String unit = userPublicService.findByUnitsToname(deviceLibrarySelectVo.getUnitId());
            predicateBuilder.eq("ownUnit", unit);
            predicateBuilder.eq("locationUnit", unit);
        }
        return predicateBuilder.build();
    }

    private Specification<DeviceLibrary> getSelectSpecification2(DeviceLibrarySelectVo deviceLibrarySelectVo, String name) {
        PredicateBuilder<DeviceLibrary> predicateBuilder = getPredicateBuilder(deviceLibrarySelectVo);
        predicateBuilder.eq("ownUnit", name);
        return predicateBuilder.build();
    }

    private Specification<DeviceLibrary> getSelectSpecification3(DeviceLibrarySelectVo deviceLibrarySelectVo) {
        PredicateBuilder<DeviceLibrary> predicateBuilder = getPredicateBuilder(deviceLibrarySelectVo);
        predicateBuilder.notIn("ownUnit", userUtils.getCurrentUserUnitName());
        return predicateBuilder.build();
    }

    private Specification<DeviceLibrary> getSelectSpecification4(DeviceLibrarySelectVo deviceLibrarySelectVo) {
        PredicateBuilder<DeviceLibrary> predicateBuilder = getPredicateBuilder(deviceLibrarySelectVo);
        return predicateBuilder.build();
    }

    private Specification<DeviceLibrary> getSelectSpecification6(DeviceLibrarySelectVo deviceLibrarySelectVo) {
        PredicateBuilder<DeviceLibrary> predicateBuilder = getPredicateBuilder(deviceLibrarySelectVo);
        if (deviceLibrarySelectVo.getUnitId() == null) {
            String unit = userUtils.getCurrentUserUnitName();
            predicateBuilder.eq("ownUnit", unit);
        }
        return predicateBuilder.build();
    }

    private Specification<DeviceLibrary> getAllotSelectSpecification(DeviceLibrarySelectVo deviceLibrarySelectVo) {
        PredicateBuilder<DeviceLibrary> predicateBuilder = getPredicateBuilder(deviceLibrarySelectVo);
        String unit = userUtils.getCurrentUserUnitName();
        predicateBuilder.eq("ownUnit", unit);
        predicateBuilder.eq("locationUnit", unit);
        predicateBuilder.eq("lifeStatus", 2,15);
        return predicateBuilder.build();
    }

    private PredicateBuilder<DeviceLibrary> getPredicateBuilder(DeviceLibrarySelectVo deviceLibrarySelectVo) {
        PredicateBuilder<DeviceLibrary> predicateBuilder = Specifications.and();
        if (deviceLibrarySelectVo != null) {
            List<Integer> lifeStatus = deviceLibrarySelectVo.getLifeStatus();
            if (deviceLibrarySelectVo.getModel() != null) {
                predicateBuilder.eq("model", deviceLibrarySelectVo.getModel());
            }
            if (deviceLibrarySelectVo.getName() != null) {
                predicateBuilder.eq("name", deviceLibrarySelectVo.getName());
            }
            if (deviceLibrarySelectVo.getSecretLevel() != null) {
                predicateBuilder.eq("secretLevel", deviceLibrarySelectVo.getSecretLevel());
            }
            if (deviceLibrarySelectVo.getMatchingRange() != null) {
                predicateBuilder.eq("matchingRange", deviceLibrarySelectVo.getMatchingRange());
            }
            if (deviceLibrarySelectVo.getStorageType() != null) {
                predicateBuilder.eq("storageType", deviceLibrarySelectVo.getStorageType());
            }
            if (deviceLibrarySelectVo.getManageStatus() != null) {
                predicateBuilder.eq("manageStatus", deviceLibrarySelectVo.getManageStatus());
            }
            if (lifeStatus != null && lifeStatus.size()>0) {
                predicateBuilder.in("lifeStatus", lifeStatus.toArray(new Integer[]{}));
            }
            if (deviceLibrarySelectVo.getType() != null) {
                predicateBuilder.eq("type", deviceLibrarySelectVo.getType());
            }
            if (deviceLibrarySelectVo.getInvisibleRange() != null) {
                predicateBuilder.eq("invisibleRange", deviceLibrarySelectVo.getInvisibleRange());
            }
            if (deviceLibrarySelectVo.getLocationUnit() != null) {
                predicateBuilder.eq("locationUnit", deviceLibrarySelectVo.getLocationUnit());
            }
            if (deviceLibrarySelectVo.getOwnUnit() != null) {
                predicateBuilder.eq("ownUnit", deviceLibrarySelectVo.getOwnUnit());
            }
            if (deviceLibrarySelectVo.getRfidCardId() != null) {
                predicateBuilder.like("rfidCardId", deviceLibrarySelectVo.getRfidCardId());
            }
            if (deviceLibrarySelectVo.getPackingId() != null) {
                predicateBuilder.eq("packingId", deviceLibrarySelectVo.getPackingId());
            }
            if (deviceLibrarySelectVo.getIsPart() != null) {
                predicateBuilder.eq("isPart", deviceLibrarySelectVo.getIsPart());
            }
            if (deviceLibrarySelectVo.getIsPrint()!=null){
                if (deviceLibrarySelectVo.getIsPrint()==1){
                    predicateBuilder.notIn("rfidCardId", "");
                }
                else if (deviceLibrarySelectVo.getIsPrint()==0){
                    predicateBuilder.in("rfidCardId", null,"");
                }
            }
            if (deviceLibrarySelectVo.getContent() != null) {
                Class<DeviceLibrary> deviceLibraryEntity = DeviceLibrary.class;
                Field[] declaredFields = deviceLibraryEntity.getDeclaredFields();
                PredicateBuilder<DeviceLibrary> p = Specifications.or();
                for (Field field : declaredFields) {
                    if (field.getType().equals(String.class) && field.getAnnotation(Transient.class) == null) {
                        p.like(field.getName(), "%" + deviceLibrarySelectVo.getContent() + "%");
                    }
                }
                predicateBuilder.predicate(p.build());
            }
            if (deviceLibrarySelectVo.getStartTime() != null) {
                predicateBuilder.gt("createTime", deviceLibrarySelectVo.getStartTime());
            }
            if (deviceLibrarySelectVo.getEndTime() != null) {
                predicateBuilder.lt("updateTime", deviceLibrarySelectVo.getEndTime());
            }
            if (deviceLibrarySelectVo.getSeqInterval()!=null&&DeviceSeqUtil.selectDeviceSeqs(deviceLibrarySelectVo.getSeqInterval()).size()>0){
                predicateBuilder.in("seqNumber", DeviceSeqUtil.selectDeviceSeqs(deviceLibrarySelectVo.getSeqInterval()));
            }
            //新增库房位置
            predicateBuilder.eq(deviceLibrarySelectVo.getStorageLocation() != null,"storageLocation",deviceLibrarySelectVo.getStorageLocation());
            //新增装备的形态
            predicateBuilder.eq(deviceLibrarySelectVo.getType() != null,"type",deviceLibrarySelectVo.getType());
        }
        return predicateBuilder;
    }

    private List<String> getAllModel() {
        List<DeviceLibrary> list = deviceLibraryDao.findAll();
        Set<String> s = new HashSet<>();
        for (DeviceLibrary d : list) {
            s.add(d.getModel());
        }
        return new ArrayList<>(s);
    }

    private List<DeviceStatisticsVo> selectByName(String name, List<DeviceStatisticsVo> deviceStatisticsVos) {
        return deviceStatisticsVos.stream().filter(deviceStatisticsVo -> deviceStatisticsVo.getName().equals(name)).collect(Collectors.toList());
    }
    private List<DeviceLibrary> getAllDevww(DeviceLibrarySelectVo deviceLibrarySelectVo) throws Exception {
        List<DeviceLibrary> deviceLibraryList = cacheLibraryService.getAllDeviceLibraryList();
        long l = System.currentTimeMillis();
        List<DeviceLibrary> list = filterFields(deviceLibraryList, deviceLibrarySelectVo);
        log.info("过滤时间为:{}",(System.currentTimeMillis()-l));
        return list;
    }

    public List<DeviceLibrary> filterFields(List<DeviceLibrary> list,DeviceLibrarySelectVo params) throws Exception {
        Method[] methods = params.getClass().getMethods();
//        getUserName getPassWord
        List<Method> useMethods = Arrays.stream(methods).filter(method -> !method.getName().equals("getClass")
                && method.getName().startsWith("get")).collect(Collectors.toList());
//        Map<String,Object> filterFields = new HashMap<>();
        //获取参数不为空的集合 如 username = "张三",password = "123456" age = "null"
        Set<String> nameMethods = new HashSet<>();
        for (DeviceLibrary deviceLibrary : list) {
            for (Method declaredField : deviceLibrary.getClass().getDeclaredMethods()) {
                nameMethods.add(declaredField.getName());
            }
        }
        for (Method useMethod : useMethods) {
            Object invoke = params.getClass().getMethod(useMethod.getName()).invoke(params);
            //判断是否为空
            if (ObjectUtil.isNotNull(invoke)) {
                if (invoke instanceof ArrayList){
                    if (((ArrayList<?>) invoke).size() == 3){
                        list = list;
                    }
                }else {
                    if (nameMethods.contains(useMethod.getName())) {
                        list = list.stream().filter(deviceLibrary1 -> {
                            try {
                                Object invoke1 = deviceLibrary1.getClass().getMethod(useMethod.getName())
                                        .invoke(deviceLibrary1);
                                //判断是不是同一个
                                if (ObjectUtil.equal(invoke, invoke1) || ObjectUtil.contains(invoke1, invoke)) {
                                    return true;
                                }
                            } catch (Exception e) {
                            }
                            return false;
                        }).collect(Collectors.toList());
                    }
                }


            }

        }

        return list;
    }

    public List<DeviceLibrary> filterFields2(List<DeviceLibrary> list,DeviceLibraryCacheSelectVo params) throws Exception {
        Method[] methods = params.getClass().getMethods();
//        getUserName getPassWord
        List<Method> useMethods = Arrays.stream(methods).filter(method -> !method.getName().equals("getClass")
                && method.getName().startsWith("get")).collect(Collectors.toList());
//        Map<String,Object> filterFields = new HashMap<>();
        //获取参数不为空的集合 如 username = "张三",password = "123456" age = "null"
        Set<String> nameMethods = new HashSet<>();
        for (DeviceLibrary deviceLibrary : list) {
            for (Method declaredField : deviceLibrary.getClass().getDeclaredMethods()) {
                nameMethods.add(declaredField.getName());
            }
        }
        for (Method useMethod : useMethods) {
            Object invoke = params.getClass().getMethod(useMethod.getName()).invoke(params);
            //判断是否为空
            if (ObjectUtil.isNotNull(invoke)) {
                    if (nameMethods.contains(useMethod.getName())) {
                        list = list.stream().filter(deviceLibrary1 -> {
                            try {
                                Object invoke1 = deviceLibrary1.getClass().getMethod(useMethod.getName())
                                        .invoke(deviceLibrary1);
                                //判断是不是同一个
                                if (ObjectUtil.equal(invoke, invoke1) || ObjectUtil.contains(invoke1, invoke)) {
                                    return true;
                                }
                            } catch (Exception e) {
                            }
                            return false;
                        }).collect(Collectors.toList());
                    }
                }
        }

        return list;
    }

}
