package com.tykj.dev.device.library.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.TaskBeanConfig;
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.subject.domin.DeviceLibrary;
import com.tykj.dev.device.library.subject.vo.DeviceLibrarySelectVo;
import com.tykj.dev.device.library.subject.vo.DeviceStatisticsVo;
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 org.springframework.beans.factory.annotation.Autowired;
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 javax.persistence.Transient;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors;

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

/**
 * @author dengdiyi
 */
@Service
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;

    @Override
    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()))
                        .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 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();
        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<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
    public void updateLifeStatus(Integer lifeStatus,Integer id) {
        deviceLibraryDao.batchUpdate(lifeStatus,id);
    }

    @Override
    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();
        System.out.println("查询时间为"+(System.currentTimeMillis()-l));
        return all;
    }

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

//    @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
    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
    public void updateDevicesOwnUnit(List<Integer> deviceIds) {
        deviceLibraryDao.updateDevicesOwnUnit(deviceIds);
    }


    @Override
    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
    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());
    }

}
