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

import com.lowagie.text.pdf.SequenceList;
import com.tykj.dev.config.cache.ConfigCache;
import com.tykj.dev.config.swagger.AutoDocument;
import com.tykj.dev.device.file.entity.FileRet;
import com.tykj.dev.device.file.service.FilesUtil;
import com.tykj.dev.device.library.repository.DeviceLogDao;
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.domin.DeviceLog;
import com.tykj.dev.device.library.subject.vo.*;
import com.tykj.dev.device.matching.repository.MatchingDeviceLibraryDao;
import com.tykj.dev.device.matching.repository.MatchingRepairBillDao;
import com.tykj.dev.device.matching.service.MatchingDeviceBillService;
import com.tykj.dev.device.matching.service.MatchingDeviceLibraryService;
import com.tykj.dev.device.matching.service.MatchingDeviceModelService;
import com.tykj.dev.device.matching.subject.domin.MatchingDeviceBill;
import com.tykj.dev.device.matching.subject.domin.MatchingDeviceLibrary;
import com.tykj.dev.device.matching.subject.domin.MatchingDeviceModel;
import com.tykj.dev.device.matching.subject.domin.MatchingRepairBill;
import com.tykj.dev.device.matching.subject.vo.*;
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.domin.Task;
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.entity.vo.RfidPrintVo;
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.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
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 javax.validation.constraints.Min;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author dengdiyi
 */
@RestController
@RequestMapping(value = "/matchingDevice")
@AutoDocument
@Api(tags = "配套设备模块", description = "配套设备模块")
@Validated
public class MatchingDeviceController {

    @Autowired
    private MatchingDeviceLibraryService matchingDeviceLibraryService;

    @Autowired
    private MatchingDeviceBillService matchingDeviceBillService;

    @Autowired
    private UserUtils userUtils;

    @Autowired
    private TaskService taskService;

    @Autowired
    private TaskLogService taskLogService;

    @Autowired
    private DeviceLogService deviceLogService;

    @Autowired
    private DeviceLibraryService deviceLibraryService;

    @Autowired
    private DeviceLogDao deviceLogDao;

    @Autowired
    private MyWebSocket myWebSocket;

    @Autowired
    private MatchingRepairBillDao matchingRepairBillDao;

    @Autowired
    private ConfigCache configCache;

    @Autowired
    private UserPublicService userPublicService;

    @Autowired
    private MessageService messageService;

    @Autowired
    private RfidService rfidService;

    @Autowired
    private MatchingDeviceModelService matchingDeviceModelService;


    @ApiOperation(value = "将设备进行拆分", notes = "将设备进行拆分")
    @PostMapping(value = "/matchingDeviceSplit")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity matchingDeviceSplit(@RequestBody List<MatchingDeviceSaveVo> matchingDeviceSaveVos) {
        List<MatchingDeviceSaveVo> matchingDeviceSaveVoList = new ArrayList<>();

        //当手动输入序列号的时候  需要进行遍历成集合
        matchingDeviceSaveVos.forEach(matchingDeviceSaveVo -> {
            List<String> deviceSeqs = DeviceSeqUtil.createDeviceSeqs(matchingDeviceSaveVo.getSeqNumber(), matchingDeviceSaveVo.getStorageCount());
            matchingDeviceSaveVo.setSeqList(deviceSeqs);
        });
        //做校验  数量跟序列号
        matchingDeviceSaveVos.forEach(matchingDeviceSaveVo -> {
            if (matchingDeviceSaveVo.getStorageCount()!=matchingDeviceSaveVo.getSeqList().size()){
                throw new ApiException("序列号与入库数量不匹配");
            }
        });

        for (MatchingDeviceSaveVo matchingDeviceSaveVo : matchingDeviceSaveVos) {
            List<String> seqList = matchingDeviceSaveVo.getSeqList();
            for (int i = 0; i < seqList.size(); i++) {
                MatchingDeviceSaveVo matchingDeviceSaveVo1 = new MatchingDeviceSaveVo();
                BeanUtils.copyProperties(matchingDeviceSaveVo,matchingDeviceSaveVo1);
                matchingDeviceSaveVo1.setSeqNumber(seqList.get(i));
                matchingDeviceSaveVoList.add(matchingDeviceSaveVo1);
            }
        }
        return ResponseEntity.ok(matchingDeviceSaveVoList);
    }

    @ApiOperation(value = "添加配套设备", notes = "可以通过这个接口添加配套设备")
    @PostMapping(value = "/add")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity addStorageBill(@RequestBody @Validated MatchingDeviceBillSaveVo matchingDeviceBillSaveVo) {
        Boolean isPrint = matchingDeviceBillSaveVo.getIsPrint() != 0;
        //添加账单
//        MatchingDeviceBill matchingDeviceBillEntity = matchingDeviceBillSaveVo.toDo();
//        matchingDeviceBillEntity.setFileRets(FilesUtil.stringFileToList(matchingDeviceBillSaveVo.getFileRets()));
//        MatchingDeviceBill m = matchingDeviceBillService.addEntity(matchingDeviceBillEntity);
        //校验
        List<String> seqNumList = matchingDeviceBillSaveVo.getMatchingDeviceSaveVoList().stream().
                map(MatchingDeviceSaveVo::getSeqNumber).collect(Collectors.toList());
        //所有的入库配套设备的序列号
        List<String> matchingDeviceLibraryListSeqNumberList = matchingDeviceLibraryService.getAllMatchingDeviceLibraryListSeqNumberList();
        matchingDeviceLibraryListSeqNumberList.retainAll(seqNumList);
        if (matchingDeviceLibraryListSeqNumberList.size()>0){
            throw new ApiException("序列号"+matchingDeviceLibraryListSeqNumberList+"已存在");
        }
        //做校验  入库的配套设备的序列号不能一样
        //先去重
        List<String> distinctSeqNumList = seqNumList.stream().distinct().collect(Collectors.toList());
        distinctSeqNumList.forEach(s -> {
            int frequency = Collections.frequency(seqNumList, s);
            if (frequency>1){
                throw new ApiException("序列号不能相同");
            }
        });
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("x");
        Integer userId = userUtils.getCurrentUserId();
        //发起任务
        List<Integer> userIds = new ArrayList<>();
        userIds.add(userId);
        //保存后的task
        TaskBto taskBto1;
        //更新后的MatchingDeviceBill
        MatchingDeviceBill updateMatchingDeviceBill;
        //处理账单
        if (matchingDeviceBillSaveVo.getTaskId() != null){
            //从草稿进来的
            taskBto1 = taskService.get(matchingDeviceBillSaveVo.getTaskId());
            MatchingDeviceBill matchingDeviceBill = matchingDeviceBillService.getOne(taskBto1.getBillId());
            MatchingDeviceBill matchingDeviceBill1 = matchingDeviceBillSaveVo.toDo();
            matchingDeviceBill.setFileRets(FilesUtil.stringFileToList(matchingDeviceBillSaveVo.getFileRets()));
            BeanUtils.copyProperties(matchingDeviceBill1,matchingDeviceBill);
            updateMatchingDeviceBill = matchingDeviceBillService.update(matchingDeviceBill);
            //结束Task
            taskService.addInvolveUser(taskBto1,userId);
            taskService.moveToEnd(taskBto1);
        }else {
            //发起新的任务
            updateMatchingDeviceBill = matchingDeviceBillService.addEntity(matchingDeviceBillSaveVo.toDo());
            TaskBto taskBto = new TaskBto(StatusEnum.END.id, "新增配套", null, ".",
                    updateMatchingDeviceBill.getId(), 19, userUtils.getCurrentUnitId(),
                    0, null, userIds);
            taskBto1 = taskService.start(taskBto);
        }
        //日志文件
        List<FileVo> fileVoList = new ArrayList<>();
        fileVoList.add(new FileVo("新增确认单", updateMatchingDeviceBill.getFileName(), updateMatchingDeviceBill.getFileUrl()));

        List<PrintVo> printVos = new ArrayList<>();
        List<MatchingDeviceLibrary> matchingDeviceLibraries = new ArrayList<>();
        String logMessage;
        if (isPrint){
            logMessage = "新增配套设备入库(打印标签)";
        }
        else {
            logMessage = "新增配套设备入库(未打印标签)";
        }
        //存储配套设备
        for (MatchingDeviceSaveVo matchingDeviceSaveVo : matchingDeviceBillSaveVo.getMatchingDeviceSaveVoList()) {
            MatchingDeviceLibrary matchingDeviceLibraryEntity = matchingDeviceSaveVo.toDo();
            MatchingDeviceLibrary matchingDeviceLibrary = matchingDeviceLibraryService.addEntity(matchingDeviceLibraryEntity);
            matchingDeviceLibraries.add(matchingDeviceLibrary);
            matchingDeviceLibraryService.update(matchingDeviceLibrary);
            stringBuffer.append(matchingDeviceLibrary.getId());
            stringBuffer.append("x");
            //存装备日志
            DeviceLogDto deviceLogDto = new DeviceLogDto(1, matchingDeviceLibrary.getId(), logMessage, fileVoList,taskBto1.getId());
            deviceLogService.addLog(deviceLogDto);
        }
        //是否打印标签
        if (matchingDeviceBillSaveVo.getIsPrint() == 1){
            for (MatchingDeviceLibrary matchingDeviceLibrary : matchingDeviceLibraries) {
                printVos.add(new PrintVo(String.valueOf(matchingDeviceLibrary.getId()),  matchingDeviceLibrary.getModel(),
                        matchingDeviceLibrary.getName(),matchingDeviceLibrary.getSeqNumber()));
                matchingDeviceLibrary.setRfidCardId(RfidServiceImpl.completeRfidStr2(String.valueOf(matchingDeviceLibrary.getId())));
                matchingDeviceLibraryService.update(matchingDeviceLibrary);
            }
            rfidService.printString(printVos);
        }

        //set账单新增设备详情
        updateMatchingDeviceBill.setDeviceDetail(stringBuffer.toString());
        matchingDeviceBillService.update(updateMatchingDeviceBill);
        //发送阅知信息
        List<Integer> ids = userPublicService.findOtherUser(userId);
        MessageBto messageBto = new MessageBto(taskBto1.getId(),taskBto1.getBusinessType(),"发起配套设备入库",ids,1);
        messageService.add(messageBto);
        myWebSocket.sendMessage1();
        return ResponseEntity.ok("ok");
    }

//    @ApiOperation(value = "添加配套设备", notes = "可以通过这个接口添加配套设备")
//    @PostMapping(value = "/add")
//    @Transactional(rollbackFor = Exception.class)
//    public ResponseEntity addStorageBill(@RequestBody @Validated MatchingDeviceBillSaveVo matchingDeviceBillSaveVo) {
//        List<String> existSeqs = matchingDeviceLibraryDao.findAll().stream().map(MatchingDeviceLibrary::getSeqNumber).collect(Collectors.toList());
//        List<String> addSeqs = matchingDeviceBillSaveVo.getMatchingDeviceSaveVoList().stream().map(MatchingDeviceSaveVo::getSeqNumber).collect(Collectors.toList());
//        existSeqs.retainAll(addSeqs);
//        if (existSeqs.size()>0){
//            return ResponseEntity.ok(StringSplitUtil.stringListToString(existSeqs));
//        }
//        //添加账单
//        MatchingDeviceBill matchingDeviceBillEntity = matchingDeviceBillSaveVo.toDo();
//        matchingDeviceBillEntity.setFileRets(FilesUtil.stringFileToList(matchingDeviceBillSaveVo.getFileRets()));
//        MatchingDeviceBill m = matchingDeviceBillService.addEntity(matchingDeviceBillEntity);
//        StringBuffer stringBuffer = new StringBuffer();
//        stringBuffer.append("x");
//        Integer userId = userUtils.getCurrentUserId();
//        //发起任务
//        List<Integer> userIds = new ArrayList<>();
//        userIds.add(userId);
////        userIds.add(matchingDeviceBillSaveVo.getUserbId());
//        TaskBto taskBto = new TaskBto(StatusEnum.END.id, "新增配套", null, ".", m.getId(), 19, userUtils.getCurrentUnitId(), 0, null, userIds);
//        TaskBto taskBto1 = taskService.start(taskBto);
//        //日志文件
//        List<FileVo> fileVoList = new ArrayList<>();
//        fileVoList.add(new FileVo("新增确认单", matchingDeviceBillEntity.getFileName(), matchingDeviceBillEntity.getFileUrl()));
//        //添加业务日志
////        TaskLogBto taskLogBto2 = new TaskLogBto(taskBto1.getId(), "发起新增配套", fileVoList);
////        taskLogService.addLog(taskLogBto2);
//        List<PrintVo> printVos = new ArrayList<>();
//        for (MatchingDeviceSaveVo matchingDeviceSaveVo : matchingDeviceBillSaveVo.getMatchingDeviceSaveVoList()) {
//            MatchingDeviceLibrary matchingDeviceLibraryEntity = matchingDeviceSaveVo.toDo();
//            MatchingDeviceLibrary d = matchingDeviceLibraryService.addEntity(matchingDeviceLibraryEntity);
//            printVos.add(new PrintVo(String.valueOf(d.getId()),  d.getModel(), d.getName(),d.getSeqNumber()));
//            d.setRfidCardId(RfidServiceImpl.completeRfidStr2(String.valueOf(d.getId())));
//            matchingDeviceLibraryService.update(d);
//            stringBuffer.append(d.getId());
//            stringBuffer.append("x");
//            //存装备日志
//            DeviceLogDto deviceLogDto = new DeviceLogDto(1, d.getId(), "发起新增配套", fileVoList,taskBto1.getId());
//            deviceLogService.addLog(deviceLogDto);
//        }
////        rfidService.printString(printVos);
//        //set账单新增设备详情
//        m.setDeviceDetail(stringBuffer.toString());
//        matchingDeviceBillService.update(m);
//        //发送阅知信息
//        List<Integer> ids = userPublicService.findOtherUser(userId);
//        MessageBto messageBto = new MessageBto(taskBto1.getId(),taskBto1.getBusinessType(),"业务办结",ids,1);
//        messageService.add(messageBto);
//        myWebSocket.sendMessage1();
//        return ResponseEntity.ok("ok");
//    }

    @ApiOperation(value = "添加配套设备审核", notes = "可以通过这个接口添加配套设备审核")
    @PostMapping(value = "/confirm")//不用了
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity confirm(@RequestBody @Validated MatchingDeviceBillConfirmVo matchingDeviceBillConfirmVo) {
        TaskBto taskBto = taskService.get(matchingDeviceBillConfirmVo.getTaskId());
        //1.审核成功,入库任务结束,改变装备状态
        if (matchingDeviceBillConfirmVo.getStatus() == 0) {
            taskService.update(taskService.moveToEnd(taskBto));
            //更新账单状态
            MatchingDeviceBill matchingDeviceBillEntity = matchingDeviceBillService.getOne(taskBto.getBillId());
            matchingDeviceBillEntity.setBillStatus(2);
            matchingDeviceBillService.update(matchingDeviceBillEntity);
            //改变设备状态，增加日志
            List<Integer> list = StringSplitUtil.userIdSplit(matchingDeviceBillEntity.getDeviceDetail());
            if (!list.isEmpty()) {
                for (Integer d : list) {
                    MatchingDeviceLibrary deviceLibraryEntity = matchingDeviceLibraryService.getOne(d);
                    deviceLibraryEntity.setLifeStatus(2);
                    DeviceLogDto deviceLogDto = new DeviceLogDto(1, deviceLibraryEntity.getId(), "添加配套设备审核成功", null,taskBto.getId());
                    deviceLogService.addLog(deviceLogDto);
                    matchingDeviceLibraryService.update(deviceLibraryEntity);
                }
            }
            myWebSocket.sendMessage1();
            return ResponseEntity.ok("审核通过新增成功");
        }
        //2.审核失败
        if (matchingDeviceBillConfirmVo.getStatus() == 1) {
            taskService.update(taskService.moveToArchive(taskBto));
            //更新账单状态
            MatchingDeviceBill matchingDeviceBillEntity = matchingDeviceBillService.getOne(taskBto.getBillId());
            matchingDeviceBillEntity.setBillStatus(1);
            matchingDeviceBillService.update(matchingDeviceBillEntity);
            //改变设备状态，增加日志
            List<Integer> list = StringSplitUtil.userIdSplit(matchingDeviceBillEntity.getDeviceDetail());
            if (!list.isEmpty()) {
                for (Integer d : list) {
                    MatchingDeviceLibrary deviceLibraryEntity = matchingDeviceLibraryService.getOne(d);
                    deviceLibraryEntity.setLifeStatus(1);
                    DeviceLogDto deviceLogDto = new DeviceLogDto(1, deviceLibraryEntity.getId(), "添加配套设备审核失败", null,taskBto.getId());
                    deviceLogService.addLog(deviceLogDto);
                    matchingDeviceLibraryService.update(deviceLibraryEntity);
                }
            }
            myWebSocket.sendMessage1();
            return ResponseEntity.ok("入库审核失败");
        } else {
            return ResponseEntity.ok("status只能为0或1");
        }
    }

    @ApiOperation(value = "模糊查询配套装备分页", notes = "可以通过这个接口查询装备列表")
    @PostMapping("/feature/summary")
    public ResponseEntity getAll(@RequestBody MatchingDeviceSelectVo matchingDeviceSelectVo) {
//        Page<MatchingDeviceLibrary> page = matchingDeviceLibraryService.getPage(matchingDeviceSelectVo, matchingDeviceSelectVo.getPageable());
        //set关联装备的表面号
//        for (MatchingDeviceLibrary m : page.getContent()) {
//            if (m.getDeviceId() > 0) {
//                m.setRelateDevice(deviceLibraryService.getOne(m.getDeviceId()).getRfidSurfaceId());
//            }
//            m.setConfigName();
//        }
//        return ResponseEntity.ok(page);
        List<MatchingDeviceLibrary> matchingDeviceLibraryList = matchingDeviceLibraryService.getMatchingDevicePage(matchingDeviceSelectVo);
        //处理装备的序列号
        matchingDeviceLibraryList.forEach(matchingDeviceLibrary -> {
            if (matchingDeviceLibrary.getDeviceId()!=null && matchingDeviceLibrary.getDeviceId() !=0){
                String seqNumber = deviceLibraryService.getOne(matchingDeviceLibrary.getDeviceId()).getSeqNumber();
                matchingDeviceLibrary.setDeviceSeqNumber(seqNumber);
            }

        });
//        List<Integer> ids = matchingDeviceLibraryList.stream().map(MatchingDeviceLibrary::getDeviceId).collect(Collectors.toList());
//        List<DeviceLibrary> deviceLibraries = deviceLibraryService.findAllByIds(ids);
//        List<String> seqList = deviceLibraries.stream().map(DeviceLibrary::getSeqNumber).collect(Collectors.toList());

        Boolean hasModelDim = matchingDeviceSelectVo.getModelDim()!=null;
        Boolean hasNameDim = matchingDeviceSelectVo.getNameDim()!=null;
        Boolean hasSeqDim = matchingDeviceSelectVo.getSeqDim()!=null;
        SimpleDateFormat sdf =  new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
        if (hasModelDim||hasNameDim||hasSeqDim) {
            matchingDeviceLibraryList = matchingDeviceLibraryList.stream().filter(deviceLibrary -> {
                Boolean containModelDim = !hasModelDim||deviceLibrary.getModel().contains(matchingDeviceSelectVo.getModelDim());
                Boolean containNameDim = !hasNameDim||deviceLibrary.getName().contains(matchingDeviceSelectVo.getNameDim());
                Boolean containSeqDim = !hasSeqDim||deviceLibrary.getSeqNumber().contains(matchingDeviceSelectVo.getSeqDim());
                return containModelDim&&containNameDim&&containSeqDim;
            }).collect(Collectors.toList());
        }
//        List<DeviceVo> deviceVos = matchingDeviceLibraryList.stream().map(DeviceLibrary::parseVo).collect(Collectors.toList());
        Page<MatchingDeviceLibrary> deviceLibraryEntities = PageUtil.getPerPage(matchingDeviceSelectVo.getPage(),
                matchingDeviceSelectVo.getSize(), matchingDeviceLibraryList, matchingDeviceSelectVo.getPageable());
        Map<String,Object> map = new HashMap<>();
        matchingDeviceLibraryList = matchingDeviceLibraryList.stream().map(MatchingDeviceLibrary::setConfigName).collect(Collectors.toList());
        map.put("pages",deviceLibraryEntities);
        ConfigCache configCache = SpringUtils.getBean("initConfigCache");
        List<String> types = matchingDeviceLibraryList.stream().map(MatchingDeviceLibrary::getType).collect(Collectors.toList());
        List<String> finalTypes = types.stream().distinct().collect(Collectors.toList());
        assert configCache != null;
        Map<Integer, String> matchingTypeMap = configCache.getMatchingTypeMap().entrySet().stream().filter(map1->finalTypes.contains(map1.getKey().toString())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        map.put("type",matchingTypeMap);
        //修改 增加排序
        //做一下去重
        List<String> models = matchingDeviceLibraryList.stream().map(MatchingDeviceLibrary::getModel).collect(Collectors.toList());
        List<String> finalModels = models.stream().distinct().collect(Collectors.toList());
        List<String> modelToSort = DeviceModelSort.modelToSort(finalModels);
        map.put("models",modelToSort);
        List<String> names = matchingDeviceLibraryList.stream().map(MatchingDeviceLibrary::getName).collect(Collectors.toList());
        List<String> nameList = names.stream().distinct().sorted(Comparator.comparing(s -> s)).collect(Collectors.toList());
        map.put("names",nameList);
        return ResponseEntity.ok(map);
    }


    @ApiOperation(value = "查询配套装备详情", notes = "可以通过这个接口查询配套装备详情")
    @GetMapping("/feature/detail/{id}")
    public ResponseEntity getDetail(@PathVariable("id") @Min(value = 1,message = "id不能小于1") int id) {
        List<Object> list = new ArrayList<>();
        Map<String,List<Object>> map = new HashMap<>();
        //添加配套设备详情
        MatchingDeviceLibrary m = matchingDeviceLibraryService.getOne(id);
        list.add(m);
        //添加关联装备详情
        if(m.getDeviceId()!=null){
            if (m.getDeviceId() != 0) {
                List<Object> deviceLibraryList = new ArrayList<>();
                DeviceLibrary deviceLibrary = deviceLibraryService.getOne(m.getDeviceId());
                deviceLibraryList.add(deviceLibrary);
                map.put("deviceLibrary",deviceLibraryList);
            } else {
                map.put("deviceLibrary",new ArrayList<>());
            }
        }

        //添加设备履历日志
        List<DeviceLogUserVo> deviceLogs = deviceLogDao.getAllByDeviceIdAndType(id, 1).stream()
                .map(DeviceLog::parse2Dto)
                .map(DeviceLogDto::toVo)
                .sorted(Comparator.comparing(DeviceLogUserVo::getCreateTime,
                        Comparator.nullsLast(Date::compareTo).reversed()))
                .collect(Collectors.toList());
        list.add(deviceLogs);
        map.put("list",list);
        return ResponseEntity.ok(map);
    }


    @ApiOperation(value = "更新配套设备", notes = "可以通过这个接口更新配套设备")
    @PostMapping("/update")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity update(@RequestBody @Validated MatchingDeviceEditVo matchingDeviceEditVo) {
        //查询所有的配套设备
        List<String> seqNumberList = matchingDeviceLibraryService.getAllMatchingDeviceLibraryListSeqNumberList();
        MatchingDeviceLibrary m = matchingDeviceLibraryService.getOne(matchingDeviceEditVo.getMatchingDeviceId());
        if (matchingDeviceEditVo.getCreateUnit() != null && !m.getCreateUnit().equals(matchingDeviceEditVo.getCreateUnit())) {
            //添加设备日志
            String remark = "将设备的创建单位由" + m.getCreateUnit() + "改为" + matchingDeviceEditVo.getCreateUnit();
            DeviceLogDto deviceLogDto = new DeviceLogDto(1, matchingDeviceEditVo.getMatchingDeviceId(), remark, null,null);
            deviceLogService.addLog(deviceLogDto);
            m.setCreateUnit(matchingDeviceEditVo.getCreateUnit());
            m.setCreateUnitId(matchingDeviceEditVo.getCreateUnitId());
        }
        if (matchingDeviceEditVo.getLifeStatus() != null && !m.getLifeStatus().equals(matchingDeviceEditVo.getLifeStatus())) {
            //添加设备日志
            String remark = "将设备的生命状态由" + configCache.getLifeStatusMap().getOrDefault(m.getLifeStatus(),"空") + "改为" + configCache.getLifeStatusMap().get(matchingDeviceEditVo.getLifeStatus());
            DeviceLogDto deviceLogDto = new DeviceLogDto(1, matchingDeviceEditVo.getMatchingDeviceId(), remark, null,null);
            deviceLogService.addLog(deviceLogDto);
            m.setLifeStatus(matchingDeviceEditVo.getLifeStatus());
        }
        if (matchingDeviceEditVo.getDeviceId() != null && m.getDeviceId() == 0) {
            //添加设备日志
            DeviceLibrary deviceLibrary = deviceLibraryService.getOne(matchingDeviceEditVo.getDeviceId());
            String remark = "将该设备与装备序列号为" + deviceLibrary.getRfidSurfaceId() + "的装备绑定";
            DeviceLogDto deviceLogDto = new DeviceLogDto(1, matchingDeviceEditVo.getMatchingDeviceId(), remark, null,null);
            deviceLogService.addLog(deviceLogDto);
            m.setDeviceId(matchingDeviceEditVo.getDeviceId());
        }
        if (matchingDeviceEditVo.getModel() != null && !m.getModel().equals(matchingDeviceEditVo.getModel())) {
            //添加设备日志
            String remark = "将设备的型号由" + m.getModel() + "改为" + matchingDeviceEditVo.getModel();
            DeviceLogDto deviceLogDto = new DeviceLogDto(1, matchingDeviceEditVo.getMatchingDeviceId(), remark, null,null);
            deviceLogService.addLog(deviceLogDto);
            m.setModel(matchingDeviceEditVo.getModel());
        }
        if (matchingDeviceEditVo.getName() != null && !m.getName().equals(matchingDeviceEditVo.getName())) {
            //添加设备日志
            String remark = "将设备的名称由" + m.getName() + "改为" + matchingDeviceEditVo.getName();
            DeviceLogDto deviceLogDto = new DeviceLogDto(1, matchingDeviceEditVo.getMatchingDeviceId(), remark, null,null);
            deviceLogService.addLog(deviceLogDto);
            m.setName(matchingDeviceEditVo.getName());
        }
        if (matchingDeviceEditVo.getSeqNumber() != null && !m.getSeqNumber().equals(matchingDeviceEditVo.getSeqNumber())) {
            //添加设备日志
            String remark = "将设备的序列号由" + m.getSeqNumber() + "改为" + matchingDeviceEditVo.getSeqNumber();
            DeviceLogDto deviceLogDto = new DeviceLogDto(1, matchingDeviceEditVo.getMatchingDeviceId(), remark, null,null);
            deviceLogService.addLog(deviceLogDto);
            if (seqNumberList.contains(matchingDeviceEditVo.getSeqNumber())){
                throw new ApiException("序列号"+matchingDeviceEditVo.getSeqNumber()+"已经存在");
            }else {
                m.setSeqNumber(matchingDeviceEditVo.getSeqNumber());
            }
        }
        if (matchingDeviceEditVo.getType() != null && !m.getType().equals(matchingDeviceEditVo.getType())) {
            //添加设备日志  需要前端同时传递type和typeName
//            String remark = "将设备类型由" + m.getType() + "改为" + matchingDeviceEditVo.getType();
            String remark = "将设备类型由" + m.getTypeName() + "改为" + matchingDeviceEditVo.getTypeName();
            DeviceLogDto deviceLogDto = new DeviceLogDto(1, matchingDeviceEditVo.getMatchingDeviceId(), remark, null,null);
            deviceLogService.addLog(deviceLogDto);
            m.setType(matchingDeviceEditVo.getType());
        }
        //添加绑定和解绑装备
        //添加
        if (matchingDeviceEditVo.getAddDeviceId() != null && !matchingDeviceEditVo.getAddDeviceId().equals(m.getDeviceId())){

            DeviceLibrary deviceLibrary = deviceLibraryService.getOne(matchingDeviceEditVo.getAddDeviceId());
            String remark = "将序列号为" + m.getSeqNumber() + "的配套装备与序列号为" + deviceLibrary.getSeqNumber() + "的装备绑定";
            DeviceLogDto deviceLogDto = new DeviceLogDto(1,m.getId(), remark, null,null);
            deviceLogService.addLog(deviceLogDto);
            m.setDeviceId(matchingDeviceEditVo.getAddDeviceId());
        }
        //删除
        if (matchingDeviceEditVo.getDeleteDeviceId() != null){
            DeviceLibrary deviceLibrary = deviceLibraryService.getOne(matchingDeviceEditVo.getDeleteDeviceId());
            String remark = "将序列号为" + m.getSeqNumber() + "的配套装备与序列号为" + deviceLibrary.getSeqNumber() + "的装备进行解除绑定";
            DeviceLogDto deviceLogDto = new DeviceLogDto(1,m.getId(), remark,null,null);
            deviceLogService.addLog(deviceLogDto);
            m.setDeviceId(0);

        }
        matchingDeviceLibraryService.update(m);
        return ResponseEntity.ok("修改成功");
    }

    @ApiOperation(value = "查询新增配套任务详情", notes = "可以通过这个接口查询新增配套任务详情")
    @GetMapping(value = "/detail/{billId}")
    public ResponseEntity selectDetail(@PathVariable("billId") int billId) {
        MacthingDetailVo macthingDetailVo = new MacthingDetailVo();
        //获取业务
        TaskBto taskBto = taskService.get(billId, BusinessEnum.ADD_MATCHING_DEVICE.id);
        //获取账单
        MatchingDeviceBill matchingDeviceBillEntity = matchingDeviceBillService.getOne(billId);
        matchingDeviceBillEntity.setFileRetList(FilesUtil.stringFileToList(matchingDeviceBillEntity.getFileRets()));
        macthingDetailVo.setMatchingDeviceBill(matchingDeviceBillEntity);
        //获取设备
        List<Integer> integerList = StringSplitUtil.userIdSplit(matchingDeviceBillEntity.getDeviceDetail());
        List<MatchingDeviceLibrary> matchingDeviceLibraryEntities = new ArrayList<>();
        if (integerList.size() > 0) {
            for (Integer id : integerList) {
                if (id > 0) {
                    matchingDeviceLibraryEntities.add(matchingDeviceLibraryService.getOne(id));
                }
            }
        }
        macthingDetailVo.setMatchingDeviceLibraries(matchingDeviceLibraryEntities);
        //获取业务日志
        macthingDetailVo.setTaskLogUserVos(taskLogService.getByTaskId(taskBto.getId()));
        return ResponseEntity.ok(macthingDetailVo);
    }


    @ApiOperation(value = "根据任务id查询相关单据", notes = "根据任务id查询相关单据")
    @GetMapping(value = "/fileMap/{taskId}")
    public ResponseEntity selectFileRetMap(@PathVariable("taskId") int taskId) {
        Map<String,List<FileRet>> map=new HashMap<>();
        //获取业务
        TaskBto taskBto = taskService.get(taskId);
        //获取账单
        MatchingDeviceBill matchingDeviceBillEntity = matchingDeviceBillService.getOne(taskBto.getBillId());
        //获取设备
        map.put("配发单",FilesUtil.stringFileToList(matchingDeviceBillEntity.getFileRets()));
        return ResponseEntity.ok(map);
    }

    @ApiOperation(value = "查询所有配套设备型号", notes = "查询所有配套设备型号")
    @GetMapping(value = "/selectAllModel")
    public ResponseEntity selectAllModel() {
        return ResponseEntity.ok(matchingDeviceLibraryService.getAllModel());
    }

    @ApiOperation(value = "查询所有配套设备名称", notes = "查询所有配套设备名称")
    @GetMapping(value = "/selectAllName")
    public ResponseEntity selectAllName() {
        return ResponseEntity.ok(matchingDeviceLibraryService.getAllName());
    }

    @ApiOperation(value = "上传维修单", notes = "上传维修单")
    @PostMapping(value = "/repair")
    public ResponseEntity uploadRepairBill(@RequestBody @Validated MatchingRepairVo matchingRepairVo){
        MatchingRepairBill matchingRepairBill = new MatchingRepairBill();
        BeanUtils.copyProperties(matchingRepairVo,matchingRepairBill);
        return ResponseEntity.ok(matchingRepairBillDao.save(matchingRepairBill));
    }


    @ApiOperation(value = "自动生成配套设备的序列号", notes = "可以通过这个接口自动生成配套设备序列号")
    @PostMapping(value = "/autoCreateForMatchingDevice")
    public ResponseEntity autoCreateForMatchingDevice(@RequestBody MatchingDeviceCreateSeqVo createSeqVo){
        Integer num = createSeqVo.getNum();
        //查询该型号是否是第一次生成(需要保证后4位数唯一)
        List<String> byModelForSeqNumber = matchingDeviceLibraryService.findByModelForSeqNumber(createSeqVo.getModel());
        int start =0;
        if (!CollectionUtils.isEmpty(byModelForSeqNumber)){
            //说明数据库中存有该集合中的数字  取出最大的
            String s = byModelForSeqNumber.get(0);
            start = Integer.parseInt(s);
        }
        List<String> seq2 = createSeq(start+1, start+1+num);

        String model = createSeqVo.getModel();
        //通过型号查询对应的id
//        MatchingDeviceModel matchingDeviceModel = matchingDeviceModelService.findByModel(model);
        MatchingDeviceModel matchingDeviceModel = matchingDeviceModelService.findByModelAndName(model, createSeqVo.getName());
        String idString;
        if (matchingDeviceModel != null){
            idString = matchingDeviceModel.getId().toString();
        }else {
            MatchingDeviceModel matchingDeviceModel1 = new MatchingDeviceModel();
            matchingDeviceModel1.setModel(model);
            MatchingDeviceModel addEntity = matchingDeviceModelService.addEntity(matchingDeviceModel1);
            idString = addEntity.getId().toString();
        }
        switch (idString.length()){
            case 1:
                idString = "000"+idString;
                break;
            case 2:
                idString = "00"+idString;
                break;
            case 3:
                idString = "0"+idString;
                break;
            default:
                break;
        }
        String type = "02";
        String style = createSeqVo.getStyle();
        if (style.length()<2){
            style = "0"+style;
        }
        StringBuilder stringBuilder = new StringBuilder();
        String modelTypeStyle = idString+type+style;
        if (num == 1){
            stringBuilder
                    .append(modelTypeStyle)
                    .append(seq2.get(0));
        }else {
            stringBuilder
                    .append(modelTypeStyle)
                    .append(seq2.get(0))
                    .append("-")
                    .append(modelTypeStyle)
                    .append(seq2.get(seq2.size()-1));
        }
        List<String> updateSeq2 = seq2.stream().map(str -> modelTypeStyle + str).collect(Collectors.toList());
        MatchingDeviceSeqVo matchingDeviceSeqVo = new MatchingDeviceSeqVo(model, createSeqVo.getName(),
                style,num,stringBuilder.toString(),updateSeq2);
        return ResponseEntity.ok(matchingDeviceSeqVo);
    }

    @ApiOperation(value = "保存配套设备单", notes = "可以通过这个接口保存配套设备单")
    @PostMapping(value = "/saveMatchingDeviceBill")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity saveStorageBill(@RequestBody MatchingDeviceBillSaveVo matchingDeviceBillSaveVo) {
        //第一次保存
        if (matchingDeviceBillSaveVo.getTaskId()==null){
            //保存入库单
            Integer userId = userUtils.getCurrentUserId();
            List<Integer> userIds = new ArrayList<>();
            userIds.add(userId);
            MatchingDeviceBill matchingDeviceBill = matchingDeviceBillSaveVo.toDo();
            matchingDeviceBill.setBillStatus(0);
            MatchingDeviceBill matchingDeviceBill1 = matchingDeviceBillService.addEntity(matchingDeviceBill);
            //发起任务
            TaskBto taskBto = new TaskBto(StatusEnum.WAIT_STORAGE.id,
                    matchingDeviceBillSaveVo.getUseraId()+"进行了新增配套设备业务", null,
                    ".", matchingDeviceBill.getId(), 19,
                    userUtils.getCurrentUnitId(), 0, null, userIds);
            TaskBto taskBto1 = taskService.start(taskBto);
            myWebSocket.sendMessage1();
            return ResponseEntity.ok("保存成功"+taskBto1.getId());
        }
        else {
            //更新账单
            TaskBto taskBto = taskService.get(matchingDeviceBillSaveVo.getTaskId());
            MatchingDeviceBill matchingDeviceBill = matchingDeviceBillService.getOne(taskBto.getBillId());
            MatchingDeviceBill matchingDeviceBill1 = matchingDeviceBillSaveVo.toDo();
            matchingDeviceBill1.setBillStatus(0);
            MapperUtils.copyNoNullProperties(matchingDeviceBill1,matchingDeviceBill);
            matchingDeviceBillService.update(matchingDeviceBill);
            return ResponseEntity.ok("更新成功"+taskBto.getId());
        }
    }
    @ApiOperation(value = "查询可绑定的装备", notes = "查询可绑定的装备")
    @PostMapping("/selectDevices")
    public ResponseEntity selectPartDevice(@RequestBody DeviceLibrarySelectVo deviceLibrarySelectVo){
        Boolean hasModelDim = deviceLibrarySelectVo.getModelDim()!=null;
        Boolean hasNameDim = deviceLibrarySelectVo.getNameDim()!=null;
        Boolean hasSeqDim = deviceLibrarySelectVo.getSeqDim()!=null;
        Boolean hasLocationUnitDim = deviceLibrarySelectVo.getLocationUnitDim()!=null;
        Boolean hasOwnUnitDim = deviceLibrarySelectVo.getOwnUnitDim()!=null;
        Boolean hasLifeStatusDim = deviceLibrarySelectVo.getLifeStatusDim()!=null;
        Boolean hasUpdateTimeDim = deviceLibrarySelectVo.getUpdateTimeDim()!=null;
        Boolean hasRfidCardDim = deviceLibrarySelectVo.getRfidCardDim()!=null;
        //库存位置
        Boolean hasStorageLocationDim  = deviceLibrarySelectVo.getRfidCardDim()!=null;
        SimpleDateFormat sdf =  new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
        List<DeviceLibrary> resultList = deviceLibraryService.getCoreDevicePage(deviceLibrarySelectVo);
        resultList = resultList.stream().filter(deviceLibrary -> deviceLibrary.getIsPart() == 0).collect(Collectors.toList());
        if (hasModelDim||hasLifeStatusDim||hasLocationUnitDim||hasNameDim||hasOwnUnitDim||hasSeqDim) {
            resultList = resultList.stream().filter(deviceLibrary -> {
                Boolean containModelDim = !hasModelDim||deviceLibrary.getModel().contains(deviceLibrarySelectVo.getModelDim());
                Boolean containNameDim = !hasNameDim||deviceLibrary.getName().contains(deviceLibrarySelectVo.getNameDim());
                Boolean containSeqDim = !hasSeqDim||deviceLibrary.getSeqNumber().contains(deviceLibrarySelectVo.getSeqDim());
                Boolean containLocationUnitDim = !hasLocationUnitDim||deviceLibrary.getLocationUnit().contains(deviceLibrarySelectVo.getLocationUnitDim());
                Boolean containOwnUnitDim = !hasOwnUnitDim||deviceLibrary.getOwnUnit().contains(deviceLibrarySelectVo.getOwnUnitDim());
                Boolean containLifeStatusDim = !hasLifeStatusDim||deviceLibrary.getLifeStatusName().contains(deviceLibrarySelectVo.getLifeStatusDim());
                Boolean containUpdateTimeDim = !hasUpdateTimeDim||sdf.format(deviceLibrary.getUpdateTime()).contains(deviceLibrarySelectVo.getUpdateTimeDim());
                Boolean containRfidCardDim = !hasRfidCardDim||(deviceLibrary.getRfidCardId()!=null&&deviceLibrary.getRfidCardId().contains(deviceLibrarySelectVo.getRfidCardDim()));
                Boolean containStorageLocationDim = !hasStorageLocationDim||deviceLibrary.getStorageLocation().contains(deviceLibrarySelectVo.getStorageLocationDim());
//                Boolean containTypeDim = !hasTypeDim||deviceLibrary.getType().contains(deviceLibrarySelectVo.getTypeDim());
                return containModelDim&&containNameDim&&containSeqDim&&containLocationUnitDim&&containOwnUnitDim&&containLifeStatusDim&&containUpdateTimeDim&&containRfidCardDim&&containStorageLocationDim;
            }).collect(Collectors.toList());
        }
//        List<DeviceVo> deviceVos = resultList.stream().map(DeviceLibrary::parseVo).collect(Collectors.toList());
        Page<DeviceLibrary> deviceLibraryEntities = PageUtil.getPerPage(deviceLibrarySelectVo.getPage(), deviceLibrarySelectVo.getSize(), resultList, deviceLibrarySelectVo.getPageable());
        Map<String,Object> map = new HashMap<>();
        Map<Integer,String> lifeStatusMap = configCache.getLifeStatusMap();
        //
        Map<Integer, String> styleMap = configCache.getStyleMap();

        Set<Integer> status = new HashSet<>();
        List<String> models = new ArrayList<>();
        List<String> names = new ArrayList<>();
        List<String> ownUnits = new ArrayList<>();
        List<String> locationUnits = new ArrayList<>();
        Set<String> storageLocation = new HashSet<>();
        //形态
        List<Integer> types = new ArrayList<>();
        resultList.forEach(deviceVo -> {
            deviceVo.setConfigName();
            status.add(deviceVo.getLifeStatus());
            models.add(deviceVo.getModel());
            names.add(deviceVo.getName());
            ownUnits.add(deviceVo.getOwnUnit());
            locationUnits.add(deviceVo.getLocationUnit());
            storageLocation.add(deviceVo.getStorageLocation());
            types.add(deviceVo.getType());
        });

        map.put("pages",deviceLibraryEntities);
        //修改 增加排序
        //做一下去重
        List<String> finalModels = models.stream().distinct().collect(Collectors.toList());
        List<String> modelToSort = DeviceModelSort.modelToSort(finalModels);
        map.put("models",modelToSort);
        List<String> nameList = names.stream().distinct().sorted(Comparator.comparing(s -> s)).collect(Collectors.toList());
        map.put("names",nameList);
        List<String> finalOwnUnits = DeviceModelSort.unitToSort(ownUnits);
        map.put("ownUnits",finalOwnUnits.stream().distinct().collect(Collectors.toList()));
        List<String> finalLocationUnits = DeviceModelSort.unitToSort(locationUnits);
        map.put("locationUnits",finalLocationUnits.stream().distinct().collect(Collectors.toList()));
        map.put("lifeStatus",status.stream().map(integer -> new LifeStatusVo(integer,lifeStatusMap.get(integer))).collect(Collectors.toList()));
        map.put("storageLocation",storageLocation);
        //形态
        List<TypeVo> typeVoList = types.stream().distinct().map(integer -> new TypeVo(integer, styleMap.get(integer))).sorted(Comparator.comparing(TypeVo::getType)).collect(Collectors.toList());
        map.put("types",typeVoList);
        return ResultUtil.success(map);
    }


    @ApiModelProperty(value = "关联装备",notes = "关联装备")
    @PostMapping("/relationDevice")
    private ResponseEntity relationDevice(@RequestBody RelationDeviceVo relationDeviceVo){
        matchingDeviceLibraryService.relationDevice(relationDeviceVo);
        return ResponseEntity.ok("关联成功");
    }

    @ApiOperation(value = "配套设备库打印标签", notes = "可以通过这个接口打印RFID")
    @PostMapping(value = "/print")
    @org.springframework.transaction.annotation.Transactional(rollbackFor = Exception.class)
    public ResponseEntity printRfid(@RequestBody List<RfidPrintVo> rfid) {
        matchingDeviceLibraryService.printRfid(rfid);
        return ResultUtil.success("打印成功");
    }

    @ApiOperation(value = "打印或者更新rfid", notes = "打印rfid")
    @GetMapping("/print/matchingDeviceId")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity printRfid(Integer id) {
        MatchingDeviceLibrary matchingDeviceLibrary = matchingDeviceLibraryService.printRfid(id);
        return ResponseEntity.ok(matchingDeviceLibrary.getRfidCardId());
    }
    /**
     * @return 生成配套设备附件的序列号
     */
    private List<String> createSeq(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;
    }


}
