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

import com.fasterxml.jackson.core.type.TypeReference;
import com.tykj.dev.config.swagger.AutoDocument;
import com.tykj.dev.device.apply.repository.DeviceApplyBillDao;
import com.tykj.dev.device.apply.service.DeviceApplyBillService;
import com.tykj.dev.device.apply.subject.domin.DeviceApplyBill;
import com.tykj.dev.device.apply.subject.vo.ApplyBillDetailVo;
import com.tykj.dev.device.file.entity.FileRet;
import com.tykj.dev.device.file.service.FilesUtil;
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.DeviceLibrarySaveVo;
import com.tykj.dev.device.library.subject.vo.FileVo;
import com.tykj.dev.device.library.utils.DeviceNumberUtils;
import com.tykj.dev.device.packing.service.PackingLibraryService;
import com.tykj.dev.device.packing.subject.domin.PackingLibrary;
import com.tykj.dev.device.storage.repository.StorageBillDao;
import com.tykj.dev.device.storage.service.StorageBillService;
import com.tykj.dev.device.storage.subject.domin.StorageBill;
import com.tykj.dev.device.storage.subject.vo.*;
import com.tykj.dev.device.task.repository.TaskDao;
import com.tykj.dev.device.task.service.TaskLogService;
import com.tykj.dev.device.task.service.TaskService;
import com.tykj.dev.device.task.subject.bto.TaskBto;
import com.tykj.dev.device.task.subject.bto.TaskLogBto;
import com.tykj.dev.device.task.subject.domin.Task;
import com.tykj.dev.device.task.subject.vo.TaskUserVo;
import com.tykj.dev.device.user.read.service.MessageService;
import com.tykj.dev.device.user.read.subject.bto.MessageBto;
import com.tykj.dev.device.user.subject.service.UserPublicService;
import com.tykj.dev.device.user.util.UserUtils;
import com.tykj.dev.misc.base.BusinessEnum;
import com.tykj.dev.misc.base.StatusEnum;
import com.tykj.dev.misc.exception.ApiException;
import com.tykj.dev.misc.utils.*;
import com.tykj.dev.rfid.entity.vo.PrintVo;
import com.tykj.dev.rfid.service.RfidService;
import com.tykj.dev.rfid.service.impl.RfidServiceImpl;
import com.tykj.dev.socket.MyWebSocket;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.concurrent.Executor;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

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

/**
 * @author dengdiyi
 */
@RestController
@RequestMapping(value = "/storage")
@AutoDocument
@Api(tags = "装备入库模块", description = "装备入库接口")
public class StorageBillController {
    @Autowired
    TaskService taskService;
    @Autowired
    private StorageBillService storageBillService;
    @Autowired
    private DeviceLibraryService deviceLibraryService;

    @Autowired
    private UserUtils userUtils;

    @Autowired
    private PackingLibraryService packingLibraryService;

    @Autowired
    private DeviceLogService deviceLogService;

    @Autowired
    private TaskLogService taskLogService;

    @Autowired
    private UserPublicService userPublicService;

    @Autowired
    private MyWebSocket myWebSocket;

    @Autowired
    private MessageService messageService;

    @Autowired
    private DeviceLibraryDao deviceLibraryDao;

    @Autowired
    private Snowflake snowflake;

    @Autowired
    private DeviceApplyBillService deviceApplyBillService;

    @Autowired
    private TaskDao taskDao;

    @Autowired
    private DeviceApplyBillDao deviceApplyBillDao;

    @Autowired
    private StorageBillDao storageBillDao;

    @Autowired
    private RfidService rfidService;

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

    @Autowired
    private DeviceLibraryCacheService cacheLibraryService;

    @ApiOperation(value = "判断序列号是否存在申请任务中", notes = "判断序列号是否存在申请任务中")
    @PostMapping(value = "/existApplyTask")
    public ResponseEntity existApplyTask(@RequestBody List<String> seqs){
        Map<Integer, Task> taskMap = taskDao.findAllByBusinessTypeAndBillStatus(9, StatusEnum.WAIT_CONFIRM_APPLY_DEVICE.id).stream().collect(Collectors.toMap(Task::getId, Function.identity()));
        Map<Integer, DeviceApplyBill> billMap = deviceApplyBillDao.findAll().stream().collect(Collectors.toMap(DeviceApplyBill::getId,Function.identity()));
        List<String> hasTaskSeqs = new ArrayList<>();
        for (Task task:taskMap.values()) {
            DeviceApplyBill deviceApplyBill = billMap.get(task.getBillId());
            if (deviceApplyBill.getApplyType()==1){
                List<ApplyBillDetailVo> applyBillDetailVos = Objects.requireNonNull(JacksonUtil.readValue(deviceApplyBill.getApplyStat(), new TypeReference<List<ApplyBillDetailVo>>() {
                }));
                for (ApplyBillDetailVo a :applyBillDetailVos){
                    List<String> deviceSeqs = DeviceSeqUtil.selectDeviceSeqs(a.getSeqInterval());
                    deviceSeqs.retainAll(seqs);
                    if (deviceSeqs.size()>0){
                        hasTaskSeqs.addAll(deviceSeqs);
                    }
                }
            }
        }
        seqs.removeAll(hasTaskSeqs);
        if (seqs.isEmpty()){
            Map<String,Object> map = new HashMap<>();
            map.put("warn","ok");
            map.put("hasTaskSeqs",hasTaskSeqs);
            return ResponseEntity.ok(map);
        }
        else {
            Map<String,Object> map = new HashMap<>();
            map.put("warn",StringSplitUtil.stringListToString(seqs));
            map.put("hasTaskSeqs",hasTaskSeqs);
            return ResponseEntity.ok(map);
        }
    }

    @ApiOperation(value = "自动生成装备序列号", notes = "可以通过这个接口自动生成序列号")
    @PostMapping(value = "/autoCreate/{num}")
    public ResponseEntity autoCreate(@PathVariable("num") int num){
        Long seq = snowflake.creatNextId();
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(seq);
        if (num>1) {
            stringBuffer.append("-");
            stringBuffer.append(seq + num - 1);
        }
        return ResponseEntity.ok(stringBuffer.toString());
    }

    @ApiOperation(value = "自动生成配件序列号", notes = "可以通过这个接口自动生成序列号")
    @PostMapping(value = "/autoCreateForPart")
    public ResponseEntity autoCreateForPart(@RequestBody CreateSeqVo createSeqVo){
        Integer num = createSeqVo.getNum();

        //根据型号查询数据库
//        int maxSeqNumber = deviceLibraryService.getMaxSeqNumber(createSeqVo.getModel());
//        List<String> seqList = IntStream.rangeClosed(maxSeqNumber + 1, num)
//                .mapToObj(DeviceNumberUtils::parseNumber2Seq)
//                .collect(Collectors.toList());
        List<String> strings = deviceLibraryService.getMaxPartSeqNumber(createSeqVo.getModel(), 1);
        int start =0;
        if (!CollectionUtils.isEmpty(strings)){
            //说明数据库中存有该集合中的数字
            String s = strings.get(0);
            start = Integer.parseInt(s);
        }
        List<String> seq2 = createSeq2(start+1, start+1+num);
//        StringJoiner stringBuffer = new StringJoiner("-");
        StringBuilder stringBuilder = new StringBuilder();
        String model = createSeqVo.getModel();
        String type = createSeqVo.getType();
        String style = createSeqVo.getStyle();
        if (style.length()<2){
            style = "0"+style;
        }
        if (type.length()<2){
            type = "0"+type;
        }
        String modelTypeStyle = model+type+style;
        stringBuilder
                .append(modelTypeStyle)
                .append(seq2.get(0))
                .append("-")
                .append(modelTypeStyle)
                .append(seq2.get(seq2.size()-1));
        return ResponseEntity.ok(stringBuilder);
    }

    @ApiOperation(value = "获取序列号区间列表", notes = "可以通过这个接口获取序列号区间列表")
    @GetMapping(value = "/getSeq/{num}/{string}")
    public ResponseEntity getSeq(@PathVariable("string") String s,@PathVariable("num") Integer num){
        List<String> strings = DeviceSeqUtil.createDeviceSeqs(s,num);
        strings.forEach(s1 -> {
            if (deviceLibraryDao.getAllBySeqNumber(s1).size()>0){
                throw new ApiException("序列号"+s1+"已存在");
            }
        });
        return ResultUtil.success(DeviceSeqUtil.createDeviceSeqs(s,num));
    }

    @ApiOperation(value = "选择入库型号数量", notes = "可以通过这个接口选择入库型号数量")
    @PostMapping(value = "/addStorageDetail")
    public ResponseEntity addStorageDetail(@RequestBody List<StorageBillDetailVo> list) {
        //存放所有的列装
        List<PackingLibrary> libraryEntities = new ArrayList<>();

        Map<Integer, List<PackingLibrary>> map = new HashMap<>();
        //所有的序列号
        List<String> seqs = new ArrayList<>();
        for (StorageBillDetailVo s : list) {
            if (s.getStorageCount()>0) {
                //序列号区间
                List<String> strings = DeviceSeqUtil.createDeviceSeqs(s.getSeqInterval(), s.getStorageCount());
                //生产号区间
                List<String> strings3 = DeviceSeqUtil.createDeviceSeqs(s.getProdInterval(), s.getStorageCount());
                List<List<String>> sons = new ArrayList<>();
                List<List<String>> sons2 = new ArrayList<>();
                List<List<String>> sons3 = new ArrayList<>();
                List<List<String>> sons4 = new ArrayList<>();
                int count = 1;
                //入库的数量
                Integer deviceNum = s.getStorageCount();

                while (deviceNum >= count) {
                    PackingLibrary packingLibraryEntity = new PackingLibrary();
                    BeanUtils.copyProperties(packingLibraryService.getOne(s.getPackingId()), packingLibraryEntity);
                    packingLibraryEntity.setCorresponding(count);
                    packingLibraryEntity.setIsSinglePart(1);
                    if (!strings3.isEmpty()) {
                        packingLibraryEntity.setProdNumber(strings3.get(0));
                        strings3.remove(0);
                    }
                    if (!strings.isEmpty()) {
                        if (deviceLibraryDao.getAllBySeqNumber(strings.get(0)).size() > 0) {
                            throw new ApiException("序列号" + strings.get(0) + "已存在");
                        }
                        if (seqs.contains(strings.get(0))){
                            throw new ApiException("序列号" + strings.get(0) + "不能重复");
                        }
                        packingLibraryEntity.setSeq(strings.get(0));
                        strings.remove(0);
                    }
                    seqs.add(packingLibraryEntity.getSeq());
                    libraryEntities.add(packingLibraryEntity);
                    if (s.getList() != null && s.getList().size() != 0) {
                        for (int j = 0; j < s.getList().size(); j++) {
                            StorageBillDetailVo s2 = s.getList().get(j);
                            if (j >= sons.size()) {
                                sons.add(DeviceSeqUtil.createDeviceSeqs(s2.getSeqInterval(), s2.getStorageCount()));
                                sons2.add(DeviceSeqUtil.createDeviceSeqs(s2.getProdInterval(), s2.getStorageCount()));
                            }
                            packingLibraryEntity = packingLibraryService.getOne(s2.getPackingId());
                            List<String> strings2 = sons.get(j);
                            List<String> strings1 = sons2.get(j);
                            if (s2.getStorageCount() >= count) {
                                packingLibraryEntity.setIsSinglePart(0);
                                packingLibraryEntity.setCorresponding(count);
                                if (!strings2.isEmpty()) {
                                    if (deviceLibraryDao.getAllBySeqNumber(strings2.get(0)).size() > 0) {
                                        throw new ApiException("序列号" + strings2.get(0) + "已存在");
                                    }
                                    if (seqs.contains(strings2.get(0))){
                                        throw new ApiException("序列号" + strings2.get(0) + "不能重复");
                                    }
                                    packingLibraryEntity.setSeq(strings2.get(0));
                                    strings2.remove(0);
                                }
                                if (!strings1.isEmpty()) {
                                    packingLibraryEntity.setProdNumber(strings1.get(0));
                                    strings1.remove(0);
                                }
                                seqs.add(packingLibraryEntity.getSeq());
                                libraryEntities.add(packingLibraryEntity);
                            }
                            if (s2.getStorageCount() - strings2.size() == deviceNum) {
                                List<PackingLibrary> packingLibraries = new ArrayList<>();
                                for (int i = 0; i < s2.getStorageCount() - deviceNum; i++) {
                                    packingLibraryEntity = packingLibraryService.getOne(s2.getPackingId());
                                    packingLibraryEntity.setCorresponding(0);
                                    packingLibraryEntity.setIsSinglePart(1);

                                    if (!strings2.isEmpty()) {
                                        if (deviceLibraryDao.getAllBySeqNumber(strings2.get(0)).size() > 0) {
                                            throw new ApiException("序列号" + strings2.get(0) + "已存在");
                                        }
                                        if (seqs.contains(strings2.get(0))){
                                            throw new ApiException("序列号" + strings2.get(0) + "不能重复");
                                        }
                                        packingLibraryEntity.setSeq(strings2.get(0));
                                        strings2.remove(0);
                                    }
                                    if (!strings1.isEmpty()) {
                                        packingLibraryEntity.setProdNumber(strings1.get(0));
                                        strings1.remove(0);
                                    }
                                    seqs.add(packingLibraryEntity.getSeq());
                                    packingLibraries.add(packingLibraryEntity);
                                }
                                map.put(s2.getPackingId(), packingLibraries);
                            }
                            if (s2.getList() != null && s2.getList().size() != 0) {
                                for (int k = 0; k < s2.getList().size(); k++) {
                                    StorageBillDetailVo s3 = s2.getList().get(k);
                                    if (k >= sons3.size()) {
                                        sons3.add(DeviceSeqUtil.createDeviceSeqs(s3.getSeqInterval(), s3.getStorageCount()));
                                        sons4.add(DeviceSeqUtil.createDeviceSeqs(s3.getProdInterval(), s3.getStorageCount()));
                                    }
                                    packingLibraryEntity = packingLibraryService.getOne(s3.getPackingId());
                                    List<String> strings4 = sons3.get(k);
                                    List<String> strings5 = sons4.get(k);
                                    if (s3.getStorageCount() >= count) {
                                        packingLibraryEntity.setIsSinglePart(0);
                                        packingLibraryEntity.setCorresponding(count);

                                        if (!strings4.isEmpty()) {
                                            if (deviceLibraryDao.getAllBySeqNumber(strings4.get(0)).size() > 0) {
                                                throw new ApiException("序列号" + strings4.get(0) + "已存在");
                                            }
                                            if (seqs.contains(strings4.get(0))){
                                                throw new ApiException("序列号" + strings4.get(0) + "不能重复");
                                            }
                                            packingLibraryEntity.setSeq(strings4.get(0));
                                            strings4.remove(0);
                                        }
                                        if (!strings5.isEmpty()) {
                                            packingLibraryEntity.setProdNumber(strings5.get(0));
                                            strings5.remove(0);
                                        }
                                        seqs.add(packingLibraryEntity.getSeq());
                                        libraryEntities.add(packingLibraryEntity);
                                    }
                                    if (s3.getStorageCount() - strings4.size() == deviceNum) {
                                        List<PackingLibrary> packingLibraries = new ArrayList<>();
                                        for (int i = 0; i < s3.getStorageCount() - deviceNum; i++) {
                                            packingLibraryEntity = packingLibraryService.getOne(s3.getPackingId());
                                            packingLibraryEntity.setCorresponding(0);
                                            packingLibraryEntity.setIsSinglePart(1);


                                            if (!strings4.isEmpty()) {
                                                if (deviceLibraryDao.getAllBySeqNumber(strings4.get(0)).size() > 0) {
                                                    throw new ApiException("序列号" + strings4.get(0) + "已存在");
                                                }
                                                if (seqs.contains(strings4.get(0))){
                                                    throw new ApiException("序列号" + strings4.get(0) + "不能重复");
                                                }
                                                packingLibraryEntity.setSeq(strings4.get(0));
                                                strings4.remove(0);
                                            }
                                            if (!strings5.isEmpty()) {
                                                packingLibraryEntity.setProdNumber(strings5.get(0));
                                                strings5.remove(0);
                                            }
                                            seqs.add(packingLibraryEntity.getSeq());
                                            packingLibraries.add(packingLibraryEntity);
                                        }
                                        map.put(s3.getPackingId(), packingLibraries);
                                    }
                                }

                            }
                        }

                    }
                    count = count + 1;
                }
            }
        }
        for (Integer i : map.keySet()) {
            libraryEntities.addAll(map.get(i));
        }
        return ResultUtil.success(libraryEntities);
    }

    @ApiOperation(value = "办结后添加其他单据", notes = "办结后添加其他单据")
    @PostMapping(value = "/addOtherFiles/{taskId}")
    public ResponseEntity addOtherFiles(@PathVariable("taskId") int taskId, @RequestBody List<FileRet> fileRets){
        //获取业务
        TaskBto taskBto = taskService.get(taskId);
        //获取单据
        StorageBill storageBill = storageBillService.getOne(taskBto.getBillId());
        //set 其他单据
        storageBill.setOtherFiles(FilesUtil.stringFileToList(fileRets));
        storageBillService.update(storageBill);
        //添加业务日志
        taskLogService.addLog(new TaskLogBto(taskId,"上传补充单据",null));
        return ResponseEntity.ok("ok");
    }

    @ApiOperation(value = "添加入库单", notes = "可以通过这个接口发起入库业务")
    @PostMapping(value = "/addStorageBill")
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "devicesLibraryList",key = "'device'",allEntries = true)
    public ResponseEntity addStorageBill(@RequestBody @Validated StorageBillSaveVo storageBillSaveVo) {
        //是否申请业务导入
        List<DeviceApplyBill> deviceApplyBills = new ArrayList<>();
        Map<Integer, ApplyBillDetailVo> map = new HashMap<>();
        Boolean isPrint = storageBillSaveVo.getIsPrint() != 0;
        if (storageBillSaveVo.getApplyTaskIds()!=null){
            if (storageBillSaveVo.getApplyTaskIds().size()>0) {
                for (Integer id : storageBillSaveVo.getApplyTaskIds()) {
                    TaskBto taskBto1 = taskService.get(id);
                    DeviceApplyBill deviceApplyBill = deviceApplyBillService.getOne(taskBto1.getBillId());
                    if (deviceApplyBill.getApplyStat() != null) {
                        List<ApplyBillDetailVo> applyBillDetailVos = Objects.requireNonNull(JacksonUtil.readValue(deviceApplyBill.getApplyStat(), new TypeReference<List<ApplyBillDetailVo>>() {
                        }));
                        deviceApplyBill.setApplyBillDetailVos(applyBillDetailVos);
                        map.putAll(applyBillDetailVos.stream().collect(toMap(ApplyBillDetailVo::getPackingId, Function.identity())));
                    }
                    deviceApplyBills.add(deviceApplyBill);
                }
            }
        }
        //1.存入库单
        Integer userId = userUtils.getCurrentUserId();
        List<Integer> userIds = new ArrayList<>();
        userIds.add(userId);
        StorageBill storageBillEntity;
        TaskBto taskEntity1;
        if (storageBillSaveVo.getTaskId()==null) {
            storageBillEntity = storageBillService.addEntity(storageBillSaveVo.toDo());
            //2.发起入库任务
            TaskBto taskBto = new TaskBto(StatusEnum.END.id, "入库型号为"+storageBillSaveVo.getStorageBillDetails().stream().map(StorageBillDetail::getModel).collect(Collectors.toList())+"入库业务", null, ".", storageBillEntity.getId(), 2, userUtils.getCurrentUnitId(), 0, null, userIds);
            taskEntity1 = taskService.start(taskBto);
        }
        else {
            //从草稿进来的
            taskEntity1 = taskService.get(storageBillSaveVo.getTaskId());
            StorageBill storageBill = storageBillService.getOne(taskEntity1.getBillId());
            StorageBill storageBill1 = storageBillSaveVo.toDo();
            MapperUtils.copyNoNullProperties(storageBill1,storageBill);
            storageBillEntity = storageBillService.update(storageBill);
            //结束Task
            taskService.addInvolveUser(taskEntity1,userId);
            taskService.moveToEnd(taskEntity1);
        }
        Integer storageBillId = storageBillEntity.getId();
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("x");
        //存业务日志
        List<FileVo> fileVoList = new ArrayList<>();
        fileVoList.add(new FileVo("配发单", storageBillEntity.getFileName(), storageBillEntity.getFileUrl()));
        //3.存装备
//        Integer parentId = null;
        Integer parentPackingId = null;
        List<DeviceLogDto> deviceLogDtos = new ArrayList<>();
        List<DeviceLibrary> saveEntities = new ArrayList<>();
        String logMessage;
        if (isPrint){
            logMessage = "发起装备入库(打印标签)";
        }
        else {
            logMessage = "发起装备入库(未打印标签)";
        }
        //存放所有save的装备
        List<DeviceLibrary> saveDevices = new ArrayList<>();
        for (DeviceLibrarySaveVo d : storageBillSaveVo.getDeviceLibrarySaveVoList()) {
            if (d.getRfidCardId()==null|| "".equals(d.getRfidCardId()) ||deviceLibraryDao.getAllByRfidCardId(d.getRfidCardId()).size()==0) {
                DeviceLibrary saveEntity = new DeviceLibrary();
                DeviceLibrary deviceLibraryEntity = new DeviceLibrary();
                PackingLibrary packingLibraryEntity = packingLibraryService.getOne(d.getPackingId());
                BeanUtils.copyProperties(packingLibraryEntity, deviceLibraryEntity);
                deviceLibraryEntity.setId(null);
                deviceLibraryEntity.setLifeStatus(2);//设置为在库状态
                BeanUtils.copyProperties(d, deviceLibraryEntity);
                deviceLibraryEntity.setStorageBillId(storageBillId);
                deviceLibraryEntity.setLocationUnit(userUtils.getCurrentUserUnitName());
                deviceLibraryEntity.setOwnUnit(userUtils.getCurrentUserUnitName());
                deviceLibraryEntity.setPartParentId(null);

                //如果不是单独的配件，设置父装备id为上一个装备的id 0-不是,1-是
                if (d.getIsBinding() == 0){
                    if (d.getIsSinglePart() == 0) {
                        //0 不是，1:是
                        if (deviceLibraryEntity.getIsPart() == 0) {
                            saveEntity = deviceLibraryService.addEntity(deviceLibraryEntity);
                        }
                        if (deviceLibraryEntity.getIsPart() == 1) {
                            if (parentPackingId!=null) {
                                for (int i = saveDevices.size()-1;i>=0;i--){
                                    if (packingLibraryEntity.getPartParentId().equals(saveDevices.get(i).getPackingId())){
                                        deviceLibraryEntity.setPartParentId(saveDevices.get(i).getId());
                                        break;
                                    }
                                }
                            }
                            saveEntity = deviceLibraryService.addEntity(deviceLibraryEntity);
                        }
                    }
                    else {
                        saveEntity = deviceLibraryService.addEntity(deviceLibraryEntity);
                    }
                }
//                if (d.getIsSinglePart() == 0) {
//                    //0 不是，1:是
//                    if (deviceLibraryEntity.getIsPart() == 0) {
//                        saveEntity = deviceLibraryService.addEntity(deviceLibraryEntity);
//                    }
//                    if (deviceLibraryEntity.getIsPart() == 1) {
//                        if (parentPackingId!=null) {
//                            for (int i = saveDevices.size()-1;i>=0;i--){
//                                if (packingLibraryEntity.getPartParentId().equals(saveDevices.get(i).getPackingId())){
//                                    deviceLibraryEntity.setPartParentId(saveDevices.get(i).getId());
//                                }
//                            }
//                        }
//                        saveEntity = deviceLibraryService.addEntity(deviceLibraryEntity);
//                    }
//                }
                //如果是单独的配件，不用设置父装备id
                else {
                    saveEntity = deviceLibraryService.addEntity(deviceLibraryEntity);
                }
                saveDevices.add(saveEntity);
//                parentId = saveEntity.getId();
                parentPackingId = packingLibraryEntity.getId();
                saveEntities.add(saveEntity);
                stringBuffer.append(saveEntity.getId());
                //存装备日志
                DeviceLogDto deviceLogDto = new DeviceLogDto(saveEntity.getId(), logMessage, fileVoList,null,taskEntity1.getId());
//                DeviceLogDto deviceLogDto = new DeviceLogDto(saveEntity.getId(), logMessage, fileVoList,null,null);
                deviceLogDtos.add(deviceLogDto);
                stringBuffer.append("x");
                //申请业务列装入库数量+1
                if (map.get(d.getPackingId())!=null){
                    ApplyBillDetailVo applyBillDetailVo = map.get(d.getPackingId());
                    applyBillDetailVo.setCompleteCount(applyBillDetailVo.getCompleteCount()+1);
                    map.put(d.getPackingId(),applyBillDetailVo);
                }
            }
            else {
                throw new ApiException("系统中已存在rfid卡号为"+d.getRfidCardId()+"的装备！");
            }
        }
        //若要打印标签
        if(storageBillSaveVo.getIsPrint()==1){
            List<PrintVo> printVos = new ArrayList<>();
            for (DeviceLibrary d : saveEntities) {
                printVos.add(new PrintVo(String.valueOf(d.getId()),  d.getModel(), d.getName(),d.getSeqNumber()));
                d.setRfidCardId(RfidServiceImpl.completeRfidStr(String.valueOf(d.getId())));
                deviceLibraryService.update(d);
            }
            rfidService.printString(printVos);
        }

        //更新申请业务入库数量
        if (deviceApplyBills.size()>0){
            deviceApplyBills.forEach(deviceApplyBill -> {
                List<ApplyBillDetailVo> applyBillDetailVos = deviceApplyBill.getApplyBillDetailVos();
                boolean isEnd = true;
                for (int i = 0;i<applyBillDetailVos.size();i++){
                    ApplyBillDetailVo applyBillDetailVo = applyBillDetailVos.get(i);
                    if (map.get(applyBillDetailVo.getPackingId())!=null){
                        applyBillDetailVo.setCompleteCount(map.get(applyBillDetailVo.getPackingId()).getCompleteCount());
                        //更新序列号
                        String seqInterval = applyBillDetailVo.getSeqInterval();
                        List<String> seqs = DeviceSeqUtil.selectDeviceSeqs(seqInterval);
                        List<DeviceLibrarySaveVo> deviceLibrarySaveVoList = storageBillSaveVo.getDeviceLibrarySaveVoList();
                        List<String> storageSeq = deviceLibrarySaveVoList.stream().map(DeviceLibrarySaveVo::getSeqNumber).collect(Collectors.toList());
                        seqs.removeAll(storageSeq);
                        //根据试用装备的id查询序列号
                        List<Integer> deviceIds = storageBillSaveVo.getDeviceIds();
                        if (deviceIds.size()>0){
                            List<DeviceLibrary> byIds = deviceLibraryService.findByIds(deviceIds);
                            //获取序列号
                            List<String> seqNumbers = byIds.stream().map(DeviceLibrary::getSeqNumber).collect(Collectors.toList());
                            seqs.removeAll(seqNumbers);
                        }
                        applyBillDetailVo.setSeqInterval(StringSplitUtil.stringListToString(seqs));
                        applyBillDetailVos.set(i,applyBillDetailVo);
                        if (!applyBillDetailVo.getWaitNum().equals(applyBillDetailVo.getCompleteCount())){
                            isEnd = false;
                        }
                    }
                }

                if (isEnd) {
                    TaskBto taskBto1 = taskService.get(deviceApplyBill.getId(), 9);
                    taskService.addInvolveUser(taskBto1,userUtils.getCurrentUserId());
                    taskService.moveToEnd(taskBto1);
                    //发送阅知信息
                    MessageBto messageBto = new MessageBto();
                    messageBto.setContent("申请业务完结");
                    messageBto.setTaskId(taskBto1.getId());
                    messageBto.setIsHighLight(0);
                    messageBto.setInvolveUserIdList(userPublicService.findOtherUser(userId));
                    messageBto.setBusinessType(taskBto1.getBusinessType());
                    messageService.add(messageBto);
                }
                deviceApplyBill.setApplyStat(JacksonUtil.toJSon(applyBillDetailVos));
                deviceApplyBillService.update(deviceApplyBill);
            });
        }

        deviceLogService.addAllLog(deviceLogDtos);
        //4.更新入库单入库详情
        storageBillEntity.setStorageDetail(stringBuffer.toString());
        storageBillService.update(storageBillEntity);
        //发送阅知信息
        MessageBto messageBto = new MessageBto();
        messageBto.setContent("完成装备入库");
        messageBto.setTaskId(taskEntity1.getId());
        messageBto.setIsHighLight(1);
        messageBto.setInvolveUserIdList(userPublicService.findOtherUser(userId));
        messageBto.setBusinessType(taskEntity1.getBusinessType());
        messageService.add(messageBto);
        //判断是否有申请任务序列号  未导入申请任务但是序列号是申请任务的序列号
        if (storageBillSaveVo.getApplyTaskIds()==null||storageBillSaveVo.getApplyTaskIds().isEmpty()){
            if (storageBillSaveVo.getHasTaskSeqs()!=null&&storageBillSaveVo.getHasTaskSeqs().size()>0){
                List<String> hasTaskSeqs = storageBillSaveVo.getHasTaskSeqs();
                Map<Integer, Task> taskMap = taskDao.findAllByBusinessTypeAndBillStatus(9, StatusEnum.WAIT_CONFIRM_APPLY_DEVICE.id).stream().collect(Collectors.toMap(Task::getId, Function.identity()));
                Map<Integer, DeviceApplyBill> billMap = deviceApplyBillDao.findAll().stream().collect(Collectors.toMap(DeviceApplyBill::getId,Function.identity()));
                Boolean isComplete = true;
                for (Task task:taskMap.values()) {
                    DeviceApplyBill deviceApplyBill = billMap.get(task.getBillId());
                    if (deviceApplyBill.getApplyType()==1){
                        List<ApplyBillDetailVo> applyBillDetailVos = Objects.requireNonNull(JacksonUtil.readValue(deviceApplyBill.getApplyStat(), new TypeReference<List<ApplyBillDetailVo>>() {
                        }));
                        for (ApplyBillDetailVo a :applyBillDetailVos){
                            List<String> deviceSeqs = DeviceSeqUtil.selectDeviceSeqs(a.getSeqInterval());
                            deviceSeqs.retainAll(hasTaskSeqs);
                            if (deviceSeqs.size()>0){
                                a.setCompleteCount(a.getCompleteCount()+deviceSeqs.size());
                                if (!a.getCompleteCount().equals(a.getStorageCount())) {
                                    isComplete = false;
                                }
                            }
                        }
                        deviceApplyBill.setApplyStat(JacksonUtil.toJSon(applyBillDetailVos));
                        deviceApplyBillService.update(deviceApplyBill);
                        if (isComplete){
                            taskService.moveToEnd(task.parse2Bto());
                            //发送阅知信息
                            MessageBto messageBto2 = new MessageBto();
                            messageBto2.setContent("业务办结");
                            messageBto2.setTaskId(task.getId());
                            messageBto2.setIsHighLight(0);
                            messageBto2.setInvolveUserIdList(userPublicService.findOtherUser(userUtils.getCurrentUserId()));
                            messageBto2.setBusinessType(task.getBusinessType());
                            messageService.add(messageBto2);
                        }
                    }
                }
            }
        }

        //完成更新试用修改为正式
        if (storageBillSaveVo.getTryOutDevice() == 0 ){
            if (storageBillSaveVo.getDeviceIds().size()>0){
                List<DeviceLibrary> deviceLibraries = deviceLibraryService.findByIds(storageBillSaveVo.getDeviceIds());
                if (deviceLibraries.size()>0){
                    deviceLibraryService.updateTry(deviceLibraries);
                    List<DeviceLogDto> deviceLogDtoList = new ArrayList<>();
                    storageBillSaveVo.getDeviceIds().forEach(integer -> {
                        DeviceLogDto deviceLogDto = new DeviceLogDto(integer,"试用装备改为正式装备",
                                null,userId,null);
                        deviceLogDtoList.add(deviceLogDto);
                    });
                    executor.execute(()->{
                        deviceLogService.addAllLog(deviceLogDtoList);
                    });
                }
            }
        }

        //异步去查询数据库
        executor.execute(
                ()->{
                    cacheLibraryService.getAllDeviceLibraryList();
                }
        );
        myWebSocket.sendMessage1();
        return ResultUtil.success(taskEntity1);
    }

    @ApiOperation(value = "入库审核", notes = "可以通过这个接口入库审核")
    @PostMapping(value = "/confirmStorageBill")//不用了
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity confirmStorageBill(@RequestBody @Validated StorageBillConfirmVo storageBillConfirmVo) {
        TaskBto taskBto = taskService.get(storageBillConfirmVo.getTaskId());
        //1.审核成功,入库任务结束，发起新的确认任务,改变装备状态
        if (storageBillConfirmVo.getStatus() == 0) {
            taskService.update(taskService.moveToEnd(taskBto));
            StorageBill storageBillEntity = storageBillService.getOne(taskBto.getBillId());
            storageBillEntity.setStorageStatus(2);
            storageBillService.update(storageBillEntity);
            List<DeviceLibrary> libraryEntities = deviceLibraryService.getListByBillId(taskBto.getBillId());
            //改变装备状态，添加装备日志
            for (DeviceLibrary d : libraryEntities) {
                d.setLifeStatus(2);
                deviceLibraryService.update(d);
                DeviceLogDto deviceLogDto = new DeviceLogDto(d.getId(), "入库审核成功", null);
                deviceLogService.addLog(deviceLogDto);
            }
            myWebSocket.sendMessage1();
            return ResultUtil.success("审核通过入库成功");
        }
        //2.审核失败
        if (storageBillConfirmVo.getStatus() == 1) {
            taskService.update(taskService.moveToArchive(taskBto));
            StorageBill storageBillEntity = storageBillService.getOne(taskBto.getBillId());
            storageBillEntity.setStorageStatus(1);
            storageBillService.update(storageBillEntity);
            List<DeviceLibrary> libraryEntities = deviceLibraryService.getListByBillId(taskBto.getBillId());
            //改变装备状态，添加装备日志
            for (DeviceLibrary d : libraryEntities) {
                d.setLifeStatus(1);
                deviceLibraryService.update(d);
                DeviceLogDto deviceLogDto = new DeviceLogDto(d.getId(), "入库审核失败", null);
                deviceLogService.addLog(deviceLogDto);
            }
            myWebSocket.sendMessage1();
            return ResultUtil.success("入库审核失败");
        } else {
            return ResultUtil.failed("status只能为0或1");
        }
    }

    @ApiOperation(value = "查询入库详情", notes = "可以通过这个接口查询入库详情")
    @GetMapping(value = "/detail/{billId}")
    public ResponseEntity selectDetail(@PathVariable("billId") int billId) {
        Map<Integer,DeviceLibrary> deviceLibraryMap = deviceLibraryService.getAllDeviceMap();
        StorageDetailVo storageDetailVo = new StorageDetailVo();
        //获取taskBto和账单
        TaskBto taskBto = taskService.get(billId, BusinessEnum.STORAGE.id);
        StorageBill storageBillEntity = storageBillService.getOne(billId);
        if (storageBillEntity.getReceiveUseraId()!=null) {
            storageBillEntity.setReceiveUserA(userPublicService.getOne(storageBillEntity.getReceiveUseraId()).getName());
        }
        if (storageBillEntity.getReceiveUserbId()!=null) {
            storageBillEntity.setReceiveUserB(userPublicService.getOne(storageBillEntity.getReceiveUserbId()).getName());
        }
        storageDetailVo.setStorageBill(storageBillEntity);
        String str = storageBillEntity.getStorageDetail();
        List<Integer> list1 = StringSplitUtil.userIdSplit(str);
        //获取入库装备
        List<DeviceLibrary> libraryEntities = new ArrayList<>();
        for (Integer deviceId : list1) {
            DeviceLibrary deviceLibraryEntity = deviceLibraryMap.get(deviceId);
            libraryEntities.add(deviceLibraryEntity);
        }
        storageDetailVo.setDeviceLibraryList(libraryEntities);
        //获取业务日志
        storageDetailVo.setTaskLogUserVos(taskLogService.getByTaskId(taskBto.getId()));
        return ResultUtil.success(storageDetailVo);
    }

    @ApiOperation(value = "保存入库单", notes = "可以通过这个接口保存入库单")
    @PostMapping(value = "/saveStorageBill")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity saveStorageBill(@RequestBody StorageBillSaveVo storageBillSaveVo) {
        //第一次保存
        if (storageBillSaveVo.getTaskId()==null){
            //保存入库单
            Integer userId = userUtils.getCurrentUserId();
            List<Integer> userIds = new ArrayList<>();
            userIds.add(userId);
            StorageBill storageBill1 = storageBillSaveVo.toDo();
            storageBill1.setStorageStatus(0);
            StorageBill storageBill = storageBillService.addEntity(storageBill1);
            //发起任务
            TaskBto taskBto = new TaskBto(StatusEnum.WAIT_STORAGE.id, storageBillSaveVo.getSendUnit()+"进行了入库业务", null, ".", storageBill.getId(), 2, userUtils.getCurrentUnitId(), 0, null, userIds);
            TaskBto taskBto1 = taskService.start(taskBto);
            myWebSocket.sendMessage1();
            return ResponseEntity.ok("保存成功"+taskBto1.getId());
        }
        else {
            //更新账单
            TaskBto taskBto = taskService.get(storageBillSaveVo.getTaskId());
            StorageBill storageBill = storageBillService.getOne(taskBto.getBillId());
            StorageBill storageBill1 = storageBillSaveVo.toDo();
            storageBill1.setStorageStatus(0);
            MapperUtils.copyNoNullProperties(storageBill1,storageBill);
            storageBillService.update(storageBill);
            return ResponseEntity.ok("更新成功"+taskBto.getId());
        }
    }

    @ApiOperation(value = "删除入库单草稿", notes = "可以通过这个接口删除入库单草稿")
    @PostMapping(value = "/deleteStorageBill/{taskId}")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity deleteStorageBill(@PathVariable("taskId") int taskId) {
        //任务封存
        TaskBto taskBto = taskService.get(taskId);
        TaskBto taskBto1 = taskService.addInvolveUser(taskBto,userUtils.getCurrentUserId());
        taskService.moveToArchive(taskBto1);
        myWebSocket.sendMessage1();
        return ResponseEntity.ok("删除成功");
    }

    @ApiOperation(value = "查询待入库详情", notes = "可以通过这个接口查询待入库详情")
    @PostMapping(value = "/selectStorageDetail/{taskId}")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity selectStorageDetail(@PathVariable("taskId") int taskId) {
        TaskBto taskBto = taskService.get(taskId);
        StorageBill storageBillEntity = storageBillService.getOne(taskBto.getBillId());
        storageBillEntity.setReceiveUserA(userPublicService.getOne(storageBillEntity.getReceiveUseraId()).getName());
        storageBillEntity.setReceiveUserB(userPublicService.getOne(storageBillEntity.getReceiveUserbId()).getName());
        storageBillEntity.setReplyFileList(FilesUtil.stringFileToList(storageBillEntity.getReplyFiles()));
        storageBillEntity.setApplyFileList(FilesUtil.stringFileToList(storageBillEntity.getApplyFiles()));
        List<StorageBillDetail> storageBillDetails = JacksonUtil.readValue(storageBillEntity.getPackingDetail(), new TypeReference<List<StorageBillDetail>>() {
        });
//        if (storageBillDetailVos != null) {
//            setPackingLibrary(storageBillDetailVos);
//        }
        storageBillEntity.setStorageBillDetails(storageBillDetails);
        return ResponseEntity.ok(storageBillEntity);
    }

    @ApiOperation(value = "查询未打印标签入库任务", notes = "查询未打印标签入库任务")
    @GetMapping(value = "/selectUnPrintStorageTask")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity selectUnPrintStorageTask() {
        //storageStatus 入库状态(0:草稿，1:审核失败，2:已入库)
        List<StorageBill> storageBills = storageBillDao.findAllByStorageStatusAndIsPrint(2,0);
        List<Task> tasks = taskDao.findAllByBusinessTypeAndBillIdIn(2,storageBills.stream().map(StorageBill::getId).collect(Collectors.toList()));
        return ResponseEntity.ok(tasks.stream().map(Task::parse2Bto).map(TaskBto::toVo).sorted(Comparator.comparing(TaskUserVo::getUpdateTime)).collect(Collectors.toList()));
    }

    @ApiOperation(value = "入库任务完成打印标签后改变任务打印状态", notes = "入库任务完成打印标签后改变任务打印状态")
    @PostMapping(value = "/completePrint/{id}")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity completePrint(@PathVariable("taskId") int taskId) {
//        Map<Integer,DeviceLibrary> deviceLibraryMap = deviceLibraryService.getAllDeviceMap();
        TaskBto taskBto = taskService.get(taskId);
        StorageBill storageBillEntity = storageBillService.getOne(taskBto.getBillId());
        storageBillEntity.setIsPrint(1);
        storageBillService.update(storageBillEntity);
//        List<Integer> ids = StringSplitUtil.userIdSplit(storageBillEntity.getStorageDetail());
//        deviceLibraryDao.upDateRfidSurfaceIdAsSeqNumber(ids);
        return ResponseEntity.ok("ok");
    }

//    private void setPackingLibrary(List<StorageBillDetailVo> storageBillDetailVos){
//        storageBillDetailVos.forEach(storageBillDetailVo -> {
//            storageBillDetailVo.setPackingLibrary(packingLibraryService.getOne(storageBillDetailVo.getPackingId()));
//            if (storageBillDetailVo.getList()!=null&&storageBillDetailVo.getList().size()>0){
//                setPackingLibrary(storageBillDetailVo.getList());
//            }
//        });
//    }


    /**
     * 根据任务id 查询单据
     */
    @ApiOperation("根据任务id获取单据集合")
    @GetMapping("/getFileList")
    public ResponseEntity getFiles(Integer taskId){
        return ResponseEntity.ok(storageBillService.getFileList(taskId));
    }

    /**
     * @return 生成装备附件的序列号
     */
    private List<String> createSeq() {
        Set<String> set = new HashSet<>();
        for (int i = 0; i < 10000; i++) {
            String s = String.format("%04d", i);
            set.add(s);
        }
        return set.stream().sorted(Comparator.comparing(String::toString)).skip(1).collect(Collectors.toList());
    }

    /**
     * @return 生成装备附件的序列号
     */
    private List<String> createSeq2(int start,int num) {
        List<String> list = new ArrayList<>();
        for (int i = start; i < num; i++) {
            String s = String.format("%04d", i);
            list.add(s);
        }
        return list;
    }



}
