package com.yeejoin.equipmanage.service.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSONArray;
import com.yeejoin.amos.feign.systemctl.Systemctl;
import com.yeejoin.amos.feign.systemctl.model.MessageModel;
import com.yeejoin.equipmanage.common.entity.vo.*;
import com.yeejoin.equipmanage.common.vo.*;
import com.yeejoin.equipmanage.fegin.SystemctlFeign;
import com.yeejoin.equipmanage.mapper.*;
import com.yeejoin.equipmanage.remote.RemoteSecurityService;
import com.yeejoin.equipmanage.service.*;
import org.apache.catalina.util.IOTools;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.core.foundation.utils.Bean;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Sequence;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.equipmanage.common.datasync.entity.FireEquipment;
import com.yeejoin.equipmanage.common.datasync.vo.FireEquipmentVO;
import com.yeejoin.equipmanage.common.dto.EquipmentSpecificDto;
import com.yeejoin.equipmanage.common.dto.UserDto;
import com.yeejoin.equipmanage.common.entity.EquProperty;
import com.yeejoin.equipmanage.common.entity.Equipment;
import com.yeejoin.equipmanage.common.entity.EquipmentCategory;
import com.yeejoin.equipmanage.common.entity.EquipmentDetail;
import com.yeejoin.equipmanage.common.entity.EquipmentIndex;
import com.yeejoin.equipmanage.common.entity.EquipmentSpecific;
import com.yeejoin.equipmanage.common.entity.EquipmentSpecificAlarm;
import com.yeejoin.equipmanage.common.entity.EquipmentSpecificIndex;
import com.yeejoin.equipmanage.common.entity.EquipmentSystemSourceStatistics;
import com.yeejoin.equipmanage.common.entity.FireFightingSystemEntity;
import com.yeejoin.equipmanage.common.entity.FormInstance;
import com.yeejoin.equipmanage.common.entity.Stock;
import com.yeejoin.equipmanage.common.entity.StockBill;
import com.yeejoin.equipmanage.common.entity.StockBillDetail;
import com.yeejoin.equipmanage.common.entity.StockDetail;
import com.yeejoin.equipmanage.common.entity.UploadFile;
import com.yeejoin.equipmanage.common.entity.Video;
import com.yeejoin.equipmanage.common.entity.VideoEquipmentSpecific;
import com.yeejoin.equipmanage.common.entity.Warehouse;
import com.yeejoin.equipmanage.common.entity.WarehouseStructure;
import com.yeejoin.equipmanage.common.entity.dto.EquipmentSpecificDTO;
import com.yeejoin.equipmanage.common.enums.AlarmStatusEnum;
import com.yeejoin.equipmanage.common.enums.BillContentEnum;
import com.yeejoin.equipmanage.common.enums.BitmapEnum;
import com.yeejoin.equipmanage.common.enums.EquipmentRiskTypeEnum;
import com.yeejoin.equipmanage.common.enums.FileTypeEnum;
import com.yeejoin.equipmanage.common.enums.SourceTypeEnum;
import com.yeejoin.equipmanage.common.enums.StockBillTypeEnum;
import com.yeejoin.equipmanage.common.exception.BaseException;
import com.yeejoin.equipmanage.common.utils.DateUtils;
import com.yeejoin.equipmanage.common.utils.QRCodeUtil;
import com.yeejoin.equipmanage.common.utils.StringUtil;
import com.yeejoin.equipmanage.utils.RelationRedisUtil;
import org.typroject.tyboot.core.foundation.utils.DateTimeUtil;
import org.typroject.tyboot.core.restful.utils.ResponseModel;

import static org.typroject.tyboot.core.foundation.utils.DateTimeUtil.ISO8601_DATE_HOUR_MIN_SEC;

/**
 * @author ZeHua Li
 * @date 2020/10/29 16:58
 * @since v2.0
 */
@Service
//@EnableAsync
public class EquipmentSpecificSerivceImpl extends ServiceImpl<EquipmentSpecificMapper, EquipmentSpecific> implements IEquipmentSpecificSerivce {

    @Autowired
    IStockDetailService stockDetailService;
    @Autowired
    @Lazy
    IStockService stockService;
    @Autowired
    IEquPropertyService equPropertyService;
    @Autowired
    private RemoteSecurityService remoteSecurityService;
    @Autowired
    private SystemctlFeign systemctlFeign;
    @Autowired
    @Lazy
    IEquipmentSpecificIndexSerivce equipmentSpecificIndexSerivce;
    @Autowired
    IStockBillDetailService stockBillDetailService;
    @Autowired
    IStockBillService stockBillService;
   
    @Autowired
    EquipmentSpecificAlarmMapper equipmentSpecificAlarmMapper;
    @Autowired
    UploadFileMapper uploadFileMapper;
    @Autowired
    EquipmentIndexMapper equipmentIndexMapper;
    @Autowired
    ISystemDicService iSystemDicService;
    @Autowired
    IEquipmentDetailService equipmentDetailService;
    @Autowired
    IWarehouseService warehouseService;
    @Autowired
    IWarehouseStructureService warehouseStructureService;
    @Autowired
    private Sequence sequence;
    @Autowired
    IEquipmentService equipmentService;
    @Autowired
    IEquipmentCategoryService iEquipmentCategoryService;

    @Autowired
    IFireFightingSystemService iFireFightingSystemService;

    @Autowired
    private IUploadFileService iUploadFileService;

    @Autowired
    private EquipmentSpecificMapper equipmentSpecificMapper;

    @Autowired
    IEquipmentSystemSourceStatisticsService equipmentSystemSourceStatisticsService;

    @Autowired
    IEquipmentCategoryService equipmentCategoryService;

    @Autowired
    IEquipmentIndexService iEquipmentIndexService;

    @Autowired
    private IVideoService videoService;


    @Autowired
    private ICarService carService;
    @Autowired
    private IVideoEquipmentSpecificService videoEquipmentSpecificService;

    @Autowired
    private IFormInstanceService formInstanceService;

    @Value("${systemctl.dict.iot-core-param}")
    private String iotCoreParam;

    @Value("${equipment.filter.code}")
    private String codes;

    @Value("${equipment.type}")
    String equipmentCategoryLeftTypeCode;

    @Value("${equipment.scrap.day}")
    String equipmentScrapDay;

    @Autowired
    private ISyncDataService syncDataService;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private RelationRedisUtil relationRedisUtil;

    @Autowired
    private VideoMapper videoMapper;

    @Autowired
    SignalClassifyMapper signalClassifyMapper;

    @Autowired
    FireFightingSystemMapper fireFightingSystemMapper;

    @Autowired
    @Lazy
    IEquipmentSpecificAlarmService equipmentSpecificAlarmService;

    @Autowired
    WarehouseStructureMapper warehouseStructureMapper;

    @Autowired
    FormInstanceMapper formInstanceMapper;

    @Autowired
    EquipmentSpecificIndexMapper equipmentSpecificIndexMapper;

    @Value("${systemctl.sync.switch}")
    private Boolean syncSwitch;
    
    @Value("${window.vedioFormat}")
    String vedioFormat;


    private final String injection = "{\n" +
            "\n" +
            "        \"items\": [\n" +
            "\n" +
            "          { \"key\": \"巡检点\", \"value\": \"主楼一层 L06D003 烟感探测器\" },\n" +
            "\n" +
            "          { \"key\": \"巡检周期\", \"value\": \"1周\" },\n" +
            "\n" +
            "          { \"key\": \"巡检人员\", \"value\": \"王某某\" },\n" +
            "\n" +
            "          { \"key\": \"巡检单位\", \"value\": \"王某某公司\" },\n" +
            "\n" +
            "           { \"key\": \"巡检依据\", \"value\": \"烟感报警器巡检规范\" }\n" +
            "\n" +
            "        ],\n" +
            "\n" +
            "        \"inspectionApi\": \"http://172.16.11.36:8100/equip/equipSpecific/getMaintenanceInfo\",\n" +
            "\t\t\"inspectionParams\": [\"checkDate\"],\n" +
            "\n" +
            "        \"inspectionPeriod\": {\n" +
            "\n" +
            "          \"items\": [\n" +
            "\n" +
            "            { \"key\": \"巡检时间\", \"value\": \"2020-11-27  10:00:02\" },\n" +
            "\n" +
            "            { \"key\": \"巡检结果\", \"value\": \"正常\" }\n" +
            "\n" +
            "          ],\n" +
            "\n" +
            "          \"modelName\":\"巡检\",\n" +
            "\n" +
            "          \"picUrl\": [\"http://39.98.246.31:8888/group1/M00/00/34/rBq-8F-FHRCAbU9GAAACvViVp0w113.png\"],\n" +
            "\n" +
            "          \"videoUrl\": [\"xxx.xxx\"]\n" +
            "\n" +
            "        },\n" +
            "\n" +
            "        \"colums\": [\n" +
            "\n" +
            "          {\"key\": \"inspectionRequire\", \"value\": \"巡检要求\"},\n" +
            "\n" +
            "          {\"key\": \"inspectionMethod\", \"value\": \"巡检方法\"},\n" +
            "\n" +
            "          {\"key\": \"inspectionResult\", \"value\": \"巡检结果\"}\n" +
            "\n" +
            "        ],\n" +
            "\n" +
            "        \"tableList\": [\n" +
            "\n" +
            "          {\n" +
            "\n" +
            "            \"id\": \"1\",\n" +
            "\n" +
            "            \"inspectionRequire\": \"外观应完好，无明显损伤\",\n" +
            "\n" +
            "            \"inspectionMethod\": \"目测、手动检查\",\n" +
            "\n" +
            "            \"inspectionResult\": \"正常\"\n" +
            "\n" +
            "          },\n" +
            "\n" +
            "          {\n" +
            "\n" +
            "            \"id\": \"2\",\n" +
            "\n" +
            "            \"inspectionRequire\": \"外观应完好，无明显损伤\",\n" +
            "\n" +
            "            \"inspectionMethod\": \"目测、手动检查\",\n" +
            "\n" +
            "            \"inspectionResult\": \"正常\"\n" +
            "\n" +
            "          },\n" +
            "\n" +
            "          {\n" +
            "\n" +
            "            \"id\": \"3\",\n" +
            "\n" +
            "            \"inspectionRequire\": \"外观应完好，无明显损伤\",\n" +
            "\n" +
            "            \"inspectionMethod\": \"目测、手动检查\",\n" +
            "\n" +
            "            \"inspectionResult\": \"正常\"\n" +
            "\n" +
            "          },\n" +
            "\n" +
            "          {\n" +
            "\n" +
            "            \"id\": \"4\",\n" +
            "\n" +
            "            \"inspectionRequire\": \"外观应完好，无明显损伤\",\n" +
            "\n" +
            "            \"inspectionMethod\": \"目测、手动检查\",\n" +
            "\n" +
            "            \"inspectionResult\": \"正常\"\n" +
            "\n" +
            "          }\n" +
            "\n" +
            "        ]\n" +
            "\n" +
            "      }";
    private final String maintenance = "{\n" +
            "\n" +
            "        \"items\": [\n" +
            "\n" +
            "          { \"key\": \"巡检点\", \"value\": \"主楼一层 L06D003 烟感探测器\" },\n" +
            "\n" +
            "          { \"key\": \"巡检周期\", \"value\": \"1周\" },\n" +
            "\n" +
            "          { \"key\": \"巡检人员\", \"value\": \"王某某\" },\n" +
            "\n" +
            "          { \"key\": \"巡检单位\", \"value\": \"王某某公司\" },\n" +
            "\n" +
            "          { \"key\": \"巡检依据\", \"value\": \"烟感报警器巡检规范\" }\n" +
            "\n" +
            "        ],\n" +
            "\n" +
            "        \"inspectionApi\": \"http://172.16.11.36:8100/equip/equipSpecific/getMaintenanceInfo\",\n" +
            "\t\t\"inspectionParams\": [\"checkDate\"],\n" +
            "\n" +
            "        \"inspectionPeriod\": {\n" +
            "\n" +
            "          \"items\": [\n" +
            "\n" +
            "            { \"key\": \"维保时间\", \"value\": \"2020-11-27  10:00:02\" },\n" +
            "\n" +
            "            { \"key\": \"维保结果\", \"value\": \"正常\" }\n" +
            "\n" +
            "          ],\n" +
            "\n" +
            "          \"modelName\":\"维保\",\n" +
            "\n" +
            "          \"picUrl\": [\"http://39.98.246.31:8888/group1/M00/00/34/rBq-8F-FHRCAbU9GAAACvViVp0w113.png\"],\n" +
            "\n" +
            "          \"videoUrl\": [\"xxx.xxx\"]\n" +
            "\n" +
            "        },\n" +
            "\n" +
            "        \"colums\": [\n" +
            "\n" +
            "          {\"key\": \"inspectionRequire\", \"value\": \"维保要求\"},\n" +
            "\n" +
            "          {\"key\": \"inspectionMethod\", \"value\": \"维保方法\"},\n" +
            "\n" +
            "          {\"key\": \"inspectionResult\", \"value\": \"维保结果\"}\n" +
            "\n" +
            "        ],\n" +
            "\n" +
            "        \"tableList\": [\n" +
            "\n" +
            "          {\n" +
            "\n" +
            "            \"id\": \"1\",\n" +
            "\n" +
            "            \"inspectionRequire\": \"外观应完好，无明显损伤\",\n" +
            "\n" +
            "            \"inspectionMethod\": \"目测、手动检查\",\n" +
            "\n" +
            "            \"inspectionResult\": \"正常\"\n" +
            "\n" +
            "          },\n" +
            "\n" +
            "          {\n" +
            "\n" +
            "            \"id\": \"2\",\n" +
            "\n" +
            "            \"inspectionRequire\": \"外观应完好，无明显损伤\",\n" +
            "\n" +
            "            \"inspectionMethod\": \"目测、手动检查\",\n" +
            "\n" +
            "            \"inspectionResult\": \"正常\"\n" +
            "\n" +
            "          },\n" +
            "\n" +
            "          {\n" +
            "\n" +
            "            \"id\": \"3\",\n" +
            "\n" +
            "            \"inspectionRequire\": \"外观应完好，无明显损伤\",\n" +
            "\n" +
            "            \"inspectionMethod\": \"目测、手动检查\",\n" +
            "\n" +
            "            \"inspectionResult\": \"正常\"\n" +
            "\n" +
            "          },\n" +
            "\n" +
            "          {\n" +
            "\n" +
            "            \"id\": \"4\",\n" +
            "\n" +
            "            \"inspectionRequire\": \"外观应完好，无明显损伤\",\n" +
            "\n" +
            "            \"inspectionMethod\": \"目测、手动检查\",\n" +
            "\n" +
            "            \"inspectionResult\": \"正常\"\n" +
            "\n" +
            "          }\n" +
            "\n" +
            "        ]\n" +
            "\n" +
            "      }";

    private StockBill buildStockBills(EquipmentSpecific equipmentSpecific, ReginParams reginParams, AgencyUserModel agencyUserModel) {
        StockBill stockBill = new StockBill();
        stockBill.setCreatorId(Long.valueOf(agencyUserModel.getUserId()));
        stockBill.setCreatorName(agencyUserModel.getRealName());
        stockBill.setCompanyName(reginParams.getCompany().getCompanyName());
        stockBill.setDepartmentName(reginParams.getDepartment().getDepartmentName());
        stockBill.setDepartmentOrgcode(String.valueOf(reginParams.getDepartment().getDeptOrgCode()));
        stockBill.setOrgCode(reginParams.getCompany().getOrgCode());
        stockBill.setWarehouseId(equipmentSpecific.getStockDetail().getWarehouseId());
        stockBill.setBillCode(stockBillService.generateQrCode("RK"));
        stockBill.setBillType(StockBillTypeEnum.DBRK.getValue());
        return stockBill;
    }

    private List<EquipmentDetail> saveEquipmentDetailBatch(EquipmentDetail equipmentDetailVo, int loopTime) {
        List<EquipmentDetail> equipmentDetails = new ArrayList<>();
        for (int i = 0; i < loopTime; i++) {
            EquipmentDetail equipmentDetail = new EquipmentDetail();
            Bean.copyExistPropertis(equipmentDetailVo, equipmentDetail);
            equipmentDetail.setId(equipmentDetail.getId() == null ? sequence.nextId() : equipmentDetail.getId());
            equipmentDetails.add(equipmentDetail);
            List<UploadFile> fileList = new ArrayList<>();
            fileList.addAll(fillFileList(equipmentDetail.getImg(), equipmentDetail.getId(), FileTypeEnum.image.toString()));
            fileList.addAll(fillFileList(equipmentDetail.getVideo(), equipmentDetail.getId(), FileTypeEnum.video.toString()));
            fileList.addAll(fillFileList(equipmentDetail.getCertification(), equipmentDetail.getId(), FileTypeEnum.certificate.toString()));
            fileList.addAll(fillFileList(equipmentDetail.getInstruction(), equipmentDetail.getId(), FileTypeEnum.instruction.toString()));
            fileList.addAll(fillFileList(equipmentDetail.getQuality(), equipmentDetail.getId(), FileTypeEnum.quality.toString()));
            fileList.addAll(fillFileList(equipmentDetail.getOperation(), equipmentDetail.getId(), FileTypeEnum.operation.toString()));
            iUploadFileService.saveBatch(fileList);
        }
        equipmentDetailService.saveOrUpdateBatch(equipmentDetails);
        return equipmentDetails;
    }

    private List<UploadFile> fillFileList(List<UploadFile> list, Long id, String type) {
        if (list == null) {
            return new ArrayList<UploadFile>();
        }
        list.forEach(item -> {
            item.setUrl(item.getUrl());
            item.setId(sequence.nextId());
            item.setFileType(type);
            item.setObjectType(BillContentEnum.ZB.getKey());
            item.setObjectId(id);
        });
        return list;
    }

    @Override
    public IPage<ComplementCodeVO> selectEquipmentSpecific(EquipmentSpecificDTO equipmentSpecific) {
        return this.baseMapper.selectEquipmentSpecific(equipmentSpecific.getPage(), equipmentSpecific);
    }

    @Override
    public EquipmentSpecific updateEquipmentSpecific(EquipmentSpecific equipmentSpecific, ReginParams reginParams, AgencyUserModel agencyUserModel) {
        SimpleDateFormat stf = new SimpleDateFormat("yyyy-MM-dd");
//         @TableField(updateStrategy = FieldStrategy.IGNORED) 置空不生效 为空单独设置 by kongfm 2021-09-10
        this.update(new LambdaUpdateWrapper<EquipmentSpecific>().set(EquipmentSpecific::getAgencyId, equipmentSpecific.getAgencyId()).set(EquipmentSpecific::getTeamId, equipmentSpecific.getTeamId()).eq(EquipmentSpecific::getId, equipmentSpecific.getId()));
        if (equipmentSpecific.getStockDetail() != null && equipmentSpecific.getStockDetail().getWarehouseStructureId() != null) {
            equipmentSpecific.setWarehouseStructureId(equipmentSpecific.getStockDetail().getWarehouseStructureId());

            // 更新alarm表没有复位的装备位置信息
            LambdaQueryWrapper<EquipmentSpecificAlarm> queryWrapper = new LambdaQueryWrapper();
            queryWrapper.eq(EquipmentSpecificAlarm::getEquipmentSpecificId, equipmentSpecific.getId());
            queryWrapper.ne(EquipmentSpecificAlarm::getStatus, AlarmStatusEnum.HF.getCode());
            List<EquipmentSpecificAlarm> alarms = equipmentSpecificAlarmService.getBaseMapper().selectList(queryWrapper);
            if (0 < alarms.size()) {
                alarms.stream().map(x -> x.setLocation(equipmentSpecific.getPosition() + " "
                        +  null == equipmentSpecific.getStockDetail().getDescription() ? "" : equipmentSpecific.getStockDetail().getDescription())).collect(Collectors.toList());
                equipmentSpecificAlarmService.updateBatchById(alarms);
            }
        }
        boolean updateById = this.updateById(equipmentSpecific);
        if (updateById) {
            relationRedisUtil.delSysRedisKey(equipmentSpecific.getSystemId());
        }
        if (syncSwitch) {
            //AST数据同步
            FireEquipment specificDetail = getEquipSpecificDetail(equipmentSpecific);
            syncDataService.syncCreatedEquipmentSpecific(specificDetail);
        }
        if (equipmentSpecific.getStock() != null && equipmentSpecific.getStock().getId() != null) {
            stockService.updateById(equipmentSpecific.getStock());
            stockDetailService.updateById(equipmentSpecific.getStockDetail());
        } else {

            //如果位置不为空，入库
            if (equipmentSpecific.getStockDetail() != null && equipmentSpecific.getStockDetail().getWarehouseStructureId() != null) {

                //没传仓库的情况下，默认单个仓库
                if (equipmentSpecific.getStock().getWarehouseId() == null) {
                    List<Warehouse> warehouseslist = warehouseService.list();
                    if (warehouseslist.size() > 0) {
                        equipmentSpecific.getStock().setWarehouseId(warehouseslist.get(0).getId());
                    } else {
                        equipmentSpecific.getStock().setWarehouseId(0L);
                    }
                }
                List<EquipmentSpecific> list = new ArrayList<>();
                list.add(equipmentSpecific);
                initEquipmentSystemSourceStatistics(list);
                //插入库存
                equipmentSpecific.getStock().setAmount(Double.valueOf(equipmentSpecific.getNum()));
                equipmentSpecific.getStock().setCompanyName(reginParams.getCompany().getCompanyName());
                equipmentSpecific.getStock().setOrgCode(reginParams.getCompany().getOrgCode());
                equipmentSpecific.getStock().setDepartmentOrgcode(reginParams.getDepartment().getOrgCode());
                equipmentSpecific.getStock().setDepartmentName(reginParams.getDepartment().getDepartmentName());
                equipmentSpecific.getStock().setEquipmentDetailId(equipmentSpecific.getEquipmentDetailId());
                equipmentSpecific.getStock().setCreateDate(new Date());
                stockService.save(equipmentSpecific.getStock());

                //库存详情
                equipmentSpecific.getStockDetail().setCompanyName(reginParams.getCompany().getCompanyName());
                equipmentSpecific.getStockDetail().setAmount(Double.valueOf(equipmentSpecific.getNum()));
                equipmentSpecific.getStockDetail().setOrgCode(reginParams.getCompany().getOrgCode());
                equipmentSpecific.getStockDetail().setDepartmentName(reginParams.getDepartment().getDepartmentName());
                equipmentSpecific.getStockDetail().setDepartmentOrgcode(reginParams.getDepartment().getOrgCode());
                equipmentSpecific.getStockDetail().setEquipmentDetailId(equipmentSpecific.getEquipmentDetailId());
                equipmentSpecific.getStockDetail().setStockId(equipmentSpecific.getStock().getId());
                equipmentSpecific.getStockDetail().setStatus(StockBillTypeEnum.DBRK.getValue());
                equipmentSpecific.getStockDetail().setUpdateDate(new Date());
                equipmentSpecific.getStockDetail().setWarehouseId(equipmentSpecific.getStock().getWarehouseId());
                equipmentSpecific.getStockDetail().setQrCode(equipmentSpecific.getQrCode());
                equipmentSpecific.getStockDetail().setEquipmentSpecificId(equipmentSpecific.getId());
                EquipmentDetail detail = equipmentDetailService
                        .getOne(new QueryWrapper<EquipmentDetail>().eq("id", equipmentSpecific.getEquipmentDetailId()));
                equipmentSpecific.getStockDetail().setDescription(detail.getArea());
                stockDetailService.save(equipmentSpecific.getStockDetail());

                //生成入库单
                StockBill stockBill = buildStockBills(equipmentSpecific, reginParams, agencyUserModel);
                stockBillService.save(stockBill);

                StockBillDetail stockBillDetail = new StockBillDetail();
                stockBillDetail.setAmount(equipmentSpecific.getStockDetail().getAmount());
                stockBillDetail.setEquipmentDetailId(equipmentSpecific.getEquipmentDetailId());
                stockBillDetail.setStockDetailId(equipmentSpecific.getStockDetail().getId());
                stockBillDetail.setBatchNum(stf.format(new Date()));
                stockBillDetail.setCreatorId(Long.valueOf(agencyUserModel.getUserId()));
                stockBillDetail.setSingleEquipCode(equipmentSpecific.getStockDetail().getQrCode());
                stockBillDetail.setStockBillId(stockBill.getId());
                stockBillDetail.setWarehouseStructureId(equipmentSpecific.getStockDetail().getWarehouseStructureId());
                stockBillDetailService.save(stockBillDetail);
            }
        }
        return equipmentSpecific;
    }



    @Override
    public Map<String, Object> getAll(Long id) {
        QueryWrapper<EquipmentSpecificAlarm> wrapper = new QueryWrapper<>();
        wrapper.eq("equipment_specific_id", id);
        wrapper.orderByDesc("create_date");
        List<EquipmentSpecificAlarm> equipmentSpecifics = equipmentSpecificAlarmMapper.selectList(wrapper);

        // 当前告警信息拼接
        CurrAlaramVO currAlaram = new CurrAlaramVO();
        if (equipmentSpecifics.size() > 0) {
            currAlaram.setNum("1");
            currAlaram.setAlarmName(equipmentSpecifics.get(0).getEquipmentSpecificIndexName());
            currAlaram.setAlarmTime(DateUtils.convertDateToString(equipmentSpecifics.get(0).getCreateDate(), DateUtils.DATE_TIME_PATTERN));
        }
        DevInfoVO devInfo = new DevInfoVO();

        Map<String, Object> inspectionMaintenanceMap = new HashMap<>();
        inspectionMaintenanceMap.put("value", "巡检信息");
        inspectionMaintenanceMap.put("inspectionInfo", JSONObject.parseObject(injection));
        devInfo.setInspection(inspectionMaintenanceMap);

        Map<String, Object> MaintenanceMap = new HashMap<>();
        MaintenanceMap.put("value", "维保信息");
        MaintenanceMap.put("maintenanceInfo", JSONObject.parseObject(maintenance));
        devInfo.setMaintenance(MaintenanceMap);

        AlarmInfoVO alarmInfo = new AlarmInfoVO();
        devInfo.setAlarmInfo(alarmInfo);
        alarmInfo.setValue("告警信息");
        List<AlarmVO> alarmVOS = new ArrayList<>();
        equipmentSpecifics.forEach(x -> {
            AlarmVO alarmVO = new AlarmVO();
            alarmVO.setId(x.getId());
            if (EquipmentRiskTypeEnum.HZGJ.getCode().equals(x.getType())) {
                alarmVO.setType(EquipmentRiskTypeEnum.HZGJ.getType());
            } else if (EquipmentRiskTypeEnum.GZ.getCode().equals(x.getType())) {
                alarmVO.setType(EquipmentRiskTypeEnum.GZ.getType());
            } else {
                alarmVO.setType(EquipmentRiskTypeEnum.QT.getType());
            }
            alarmVO.setStatus(x.getStatus() == 0 ? "复位" : "报警");
            alarmVO.setAlarmName(x.getEquipmentSpecificIndexName());
            alarmVO.setAlarmTime(DateUtils.convertDateToString(x.getCreateDate(), DateUtils.DATE_TIME_PATTERN));
            alarmVOS.add(alarmVO);
        });
        alarmInfo.setTableList(alarmVOS);

        List<Map<String, Object>> colums = new ArrayList<>();

        Map<String, Object> alarmcolums2 = new LinkedHashMap<>();
        alarmcolums2.put("key", "alarmTime");
        alarmcolums2.put("value", "告警时间");
        Map<String, Object> alarmcolums3 = new LinkedHashMap<>();
        alarmcolums3.put("key", "alarmName");
        alarmcolums3.put("value", "告警名称");
        Map<String, Object> alarmcolums4 = new LinkedHashMap<>();
        alarmcolums4.put("key", "type");
        alarmcolums4.put("value", "类型");
        colums.add(alarmcolums2);
        colums.add(alarmcolums3);
        colums.add(alarmcolums4);
        alarmInfo.setColums(colums);

        List<EquipmentSpecificIndex> equipmentSpecificIndices = equipmentSpecificIndexSerivce.getEquipmentSpeIndexByEquipmentSecificId(id);
        List<Map<String, Object>> equipmentSpecificIndicesMaps = new ArrayList<>();
        if (equipmentSpecificIndices != null && equipmentSpecificIndices.size() != 0) {
            equipmentSpecificIndices.forEach(x -> {
                Map<String, Object> equipmentSpecificIndicesMap = new HashMap<>();
                if ("故障".equals(x.getNameKey())) {
                    if (("true").equals(x.getValue())) {
                        equipmentSpecificIndicesMap.put("value", "false");
                    } else {
                        equipmentSpecificIndicesMap.put("value", "true");
                    }
                } else if ("火灾告警".equals(x.getNameKey())) {
                    if (("true").equals(x.getValue())) {
                        equipmentSpecificIndicesMap.put("value", "false");
                    } else {
                        equipmentSpecificIndicesMap.put("value", "true");
                    }
                } else {
                    equipmentSpecificIndicesMap.put("value", x.getValue());
                }
                equipmentSpecificIndicesMap.put("key", x.getNameKey());
                equipmentSpecificIndicesMaps.add(equipmentSpecificIndicesMap);
            });
        }
        alarmInfo.setLoTInfo(equipmentSpecificIndicesMaps);

        //周边视频拼接
        List<Video> videos = equipmentSpecificIndexSerivce.getVideoByEquipmentSecificId(id);
        SurrVideoVO surrVideoVO = new SurrVideoVO();
        List<VideoVO> videoVOS = new ArrayList<>();
        videos.forEach(x -> {
            VideoVO video = new VideoVO();
            video.setName(x.getName());
            video.setTokens(x.getToken());
            video.setUrl(x.getUrl());
            video.setIp(x.getIp());
            video.setPort(x.getPort());
            videoVOS.add(video);
        });
        surrVideoVO.setVideos(videoVOS);
        surrVideoVO.setValue("周边视频");
        devInfo.setSurrVideo(surrVideoVO);

        //设备信息
        EquipmentSecificDetailVO equipmentSecificDetail = equipmentSpecificIndexSerivce.getEquipmentDetailBySecificId(id);
        DevOverviewVO devOverview = new DevOverviewVO();
        devOverview.setQrCode(equipmentSecificDetail.getQrCode());
        List<Map<String, Object>> devOverviewMapList = new ArrayList();
        Map<String, Object> devOverviewMap1 = new HashMap<>();
        devOverviewMap1.put("key", "设备名称");
        devOverviewMap1.put("value", equipmentSecificDetail.getEquipmentName());
        devOverviewMapList.add(devOverviewMap1);

        Map<String, Object> devOverviewMap2 = new HashMap<>();
        devOverviewMap2.put("key", "编码");
        devOverviewMap2.put("value", equipmentSecificDetail.getCode());
        devOverviewMapList.add(devOverviewMap2);

        Map<String, Object> devOverviewMap3 = new HashMap<>();
        devOverviewMap3.put("key", "器材分类");
        devOverviewMap3.put("value", equipmentSecificDetail.getCategoryName());
        devOverviewMapList.add(devOverviewMap3);

        Map<String, Object> devOverviewMap4 = new HashMap<>();
        devOverviewMap4.put("key", "所属系统");
        devOverviewMap4.put("value", equipmentSecificDetail.getSystemName());
        devOverviewMapList.add(devOverviewMap4);

        Map<String, Object> devOverviewMap5 = new HashMap<>();
        devOverviewMap5.put("key", "安装位置");
        devOverviewMap5.put("value", equipmentSecificDetail.getWarehouseName());
        devOverviewMapList.add(devOverviewMap5);

        Map<String, Object> devOverviewMap6 = new HashMap<>();
        devOverviewMap6.put("key", "负责人");
        devOverviewMap6.put("value", "王某某");
        devOverviewMapList.add(devOverviewMap6);

        devOverview.setItems(devOverviewMapList);

        PartDetailVO partDetail = new PartDetailVO();
        partDetail.setValue("部件详情");

        devOverview.setOperaState(StringUtil.isNotEmpty(equipmentSecificDetail.getStatus()) ? equipmentSecificDetail.getStatus() : "1");
        Map<String, Object> operaStateMap = new HashMap<>();
        operaStateMap.put("1", "正常");
        operaStateMap.put("2", "报警");
        operaStateMap.put("3", "故障");
        operaStateMap.put("4", "无信号");
        devOverview.setOperaStateObj(operaStateMap);

        devOverview.setInjectionState("1");
        Map<String, Object> injectionStateMap = new HashMap<>();
        injectionStateMap.put("1", "正常");
        injectionStateMap.put("2", "逾期");
        injectionStateMap.put("3", "临近");
        devOverview.setInjectionStateObj(injectionStateMap);
        Map<String, Object> maintenanceStateMap = new HashMap<>();
        maintenanceStateMap.put("1", "正常");
        maintenanceStateMap.put("2", "逾期");
        maintenanceStateMap.put("3", "临近");
        devOverview.setMaintenanceState("1");
        devOverview.setMaintenanceStateObj(maintenanceStateMap);
        partDetail.setDevOverview(devOverview);

        ProductInfoVO productInfo = new ProductInfoVO();
        List<Map<String, Object>> productInfoMapList = new ArrayList<>();
        Map<String, Object> productInfoMap1 = new HashMap<>();
        productInfoMap1.put("key", "名称");
        productInfoMap1.put("value", equipmentSecificDetail.getEquipmentName());
        productInfoMapList.add(productInfoMap1);
        Map<String, Object> productInfoMap2 = new HashMap<>();
        productInfoMap2.put("key", "规格型号");
        productInfoMap2.put("value", equipmentSecificDetail.getBrand());
        productInfoMapList.add(productInfoMap2);
        Map<String, Object> productInfoMap3 = new HashMap<>();
        productInfoMap3.put("key", "进口/国产");
        productInfoMap3.put("value", Boolean.valueOf(equipmentSecificDetail.getIsImport()) == true ? "进口" : "国产");
        productInfoMapList.add(productInfoMap3);
        Map<String, Object> productInfoMap4 = new HashMap<>();
        productInfoMap4.put("key", "维保周期");
        productInfoMap4.put("value", equipmentSecificDetail.getMaintenanceCycle() + "月");
        productInfoMapList.add(productInfoMap4);
        Map<String, Object> productInfoMap5 = new HashMap<>();
        productInfoMap5.put("key", "报废年限");
        productInfoMap5.put("value", "5年");
        productInfoMapList.add(productInfoMap5);
        Map<String, Object> productInfoMap6 = new HashMap<>();
        productInfoMap6.put("key", "计量单位");
        productInfoMap6.put("value", equipmentSecificDetail.getUnitName());
        productInfoMapList.add(productInfoMap6);
        Map<String, Object> productInfoMap7 = new HashMap<>();
        productInfoMap7.put("key", "品牌");
        productInfoMap7.put("value", equipmentSecificDetail.getStandard());
        productInfoMapList.add(productInfoMap7);
        Map<String, Object> productInfoMap8 = new HashMap<>();
        productInfoMap8.put("key", "国别");
        productInfoMap8.put("value", equipmentSecificDetail.getCountry());
        productInfoMapList.add(productInfoMap8);
        Map<String, Object> productInfoMap9 = new HashMap<>();
        productInfoMap9.put("key", "巡检频率");
        productInfoMap9.put("value", "每天");
        productInfoMapList.add(productInfoMap9);
        Map<String, Object> productInfoMap10 = new HashMap<>();
        productInfoMap10.put("key", "备注");
        productInfoMap10.put("value", equipmentSecificDetail.getRemark());
        productInfoMapList.add(productInfoMap10);
        QueryWrapper<UploadFile> imgUploadFileQueryWrapper = new QueryWrapper<>();
        imgUploadFileQueryWrapper.eq("file_type", "image");
        imgUploadFileQueryWrapper.eq("object_type", "equipment");
        imgUploadFileQueryWrapper.eq("object_id", equipmentSecificDetail.getEquipDetailId());
        List<UploadFile> imgUploadFiles = uploadFileMapper.selectList(imgUploadFileQueryWrapper);
        List<String> images = new ArrayList<>();
        imgUploadFiles.forEach(x -> {
            images.add(x.getUrl());
        });
        productInfo.setItems(productInfoMapList);
        productInfo.setPic(images);
        productInfo.setPicName("产品图片");
        partDetail.setProductInfo(productInfo);

        //资料
        TechInfoVO techInfo = new TechInfoVO();
        QueryWrapper<UploadFile> instructionUploadFileQueryWrapper = new QueryWrapper<>();
        instructionUploadFileQueryWrapper.eq("file_type", "instruction");
        instructionUploadFileQueryWrapper.eq("object_type", "equipment");
        instructionUploadFileQueryWrapper.eq("object_id", equipmentSecificDetail.getEquipId());
        List<UploadFile> instructionUploadFiles = uploadFileMapper.selectList(instructionUploadFileQueryWrapper);
        List<TechInfoListVO> techInfoListVOS = new ArrayList<>();
        instructionUploadFiles.forEach(x -> {
            TechInfoListVO techInfoListVO = new TechInfoListVO();
            techInfoListVO.setName(x.getName());
            techInfoListVO.setUrl(x.getUrl());
            techInfoListVOS.add(techInfoListVO);
        });
        techInfo.setInfoLists(techInfoListVOS);
        QueryWrapper<UploadFile> videoUploadFileQueryWrapper = new QueryWrapper<>();
        videoUploadFileQueryWrapper.eq("file_type", "video");
        videoUploadFileQueryWrapper.eq("object_type", "equipment");
        videoUploadFileQueryWrapper.eq("object_id", equipmentSecificDetail.getEquipId());
        UploadFile videoUploadFiles = uploadFileMapper.selectOne(videoUploadFileQueryWrapper);
        if (videoUploadFiles != null) {
            techInfo.setVideoName(videoUploadFiles.getName());
            List<String> videoUrls = new ArrayList<>();
            videoUrls.add(videoUploadFiles.getUrl());
            techInfo.setVideoUrl(videoUrls);
        }

        //核心参数
        partDetail.setCoreParams(equipmentSpecificIndexSerivce.selectEquProperty(id));

        ManufacturerVO manufacturerVO = new ManufacturerVO();
        manufacturerVO.setPic(equipmentSecificDetail.getImg());
        manufacturerVO.setCompanyName(equipmentSecificDetail.getManufacturerName());
        List<Map<String, Object>> manufacturerMapList = new ArrayList<>();
        Map<String, Object> manufacturerMap1 = new HashMap<>();
        manufacturerMap1.put("key", "杜广锋");
        manufacturerMap1.put("value", "杜广锋");

        Map<String, Object> manufacturerMap2 = new HashMap<>();
        manufacturerMap2.put("key", "手机号");
        manufacturerMap2.put("value", equipmentSecificDetail.getSalesTel());

        Map<String, Object> manufacturerMap3 = new HashMap<>();
        manufacturerMap3.put("key", "固定电话");
        manufacturerMap3.put("value", equipmentSecificDetail.getServiceTel());

        Map<String, Object> manufacturerMap4 = new HashMap<>();
        manufacturerMap4.put("key", "邮箱");
        manufacturerMap4.put("value", "duguangfeng@yeejoin.com");

        Map<String, Object> manufacturerMap5 = new HashMap<>();
        manufacturerMap5.put("key", "网址");
        manufacturerMap5.put("value", "http://www.yeejoin.com");

        Map<String, Object> manufacturerMap6 = new HashMap<>();
        manufacturerMap6.put("key", "地址");
        manufacturerMap6.put("value", equipmentSecificDetail.getAddress());

        manufacturerMapList.add(manufacturerMap1);
        manufacturerMapList.add(manufacturerMap2);
        manufacturerMapList.add(manufacturerMap3);
        manufacturerMapList.add(manufacturerMap4);
        manufacturerMapList.add(manufacturerMap5);
        manufacturerMapList.add(manufacturerMap6);
        manufacturerVO.setItems(manufacturerMapList);
        partDetail.setManufacturer(manufacturerVO);

        ManufacturerVO supplier = new ManufacturerVO();
        manufacturerVO.setPic(equipmentSecificDetail.getImg());
        manufacturerVO.setCompanyName(equipmentSecificDetail.getManufacturerName());
        List<Map<String, Object>> supplierMapList = new ArrayList<>();
        Map<String, Object> supplierMap1 = new HashMap<>();
        supplierMap1.put("key", "联系人");
        supplierMap1.put("value", "杜广锋");

        Map<String, Object> supplierMap2 = new HashMap<>();
        supplierMap2.put("key", "手机号");
        supplierMap2.put("value", "18092840417");

        Map<String, Object> supplierMap3 = new HashMap<>();
        supplierMap3.put("key", "固定电话");
        supplierMap3.put("value", "010-67889346");

        Map<String, Object> supplierMap4 = new HashMap<>();
        supplierMap4.put("key", "邮箱");
        supplierMap4.put("value", "duguangfeng@yeejoin.com");

        Map<String, Object> supplierMap5 = new HashMap<>();
        supplierMap5.put("key", "网址");
        supplierMap5.put("value", "http://www.yeejoin.com");

        Map<String, Object> supplierMap6 = new HashMap<>();
        supplierMap6.put("key", "地址");
        supplierMap6.put("value", "北京市北京经济技术开发区中和街16好5号楼1层、5层");

        supplierMapList.add(supplierMap1);
        supplierMapList.add(supplierMap2);
        supplierMapList.add(supplierMap3);
        supplierMapList.add(supplierMap4);
        supplierMapList.add(supplierMap5);
        supplierMapList.add(supplierMap6);
        supplier.setItems(supplierMapList);
        partDetail.setSupplier(supplier);

        ManufacturerVO maintenanceUnit = new ManufacturerVO();
        manufacturerVO.setPic(equipmentSecificDetail.getImg());
        manufacturerVO.setCompanyName(equipmentSecificDetail.getManufacturerName());
        List<Map<String, Object>> maintenanceUnitList = new ArrayList<>();
        Map<String, Object> maintenanceUnitMap1 = new HashMap<>();
        maintenanceUnitMap1.put("key", "联系人");
        maintenanceUnitMap1.put("value", "杜广锋");

        Map<String, Object> maintenanceUnitMap2 = new HashMap<>();
        maintenanceUnitMap2.put("key", "手机号");
        maintenanceUnitMap2.put("value", "18092840417");

        Map<String, Object> maintenanceUnitMap3 = new HashMap<>();
        maintenanceUnitMap3.put("key", "固定电话");
        maintenanceUnitMap3.put("value", "010-67889346");

        Map<String, Object> maintenanceUnitMap4 = new HashMap<>();
        maintenanceUnitMap4.put("key", "邮箱");
        maintenanceUnitMap4.put("value", "duguangfeng@yeejoin.com");

        Map<String, Object> maintenanceUnitMap5 = new HashMap<>();
        maintenanceUnitMap5.put("key", "网址");
        maintenanceUnitMap5.put("value", "http://www.yeejoin.com");

        Map<String, Object> maintenanceUnitMap6 = new HashMap<>();
        maintenanceUnitMap6.put("key", "地址");
        maintenanceUnitMap6.put("value", "北京市北京经济技术开发区中和街16好5号楼1层、5层");

        maintenanceUnitList.add(maintenanceUnitMap1);
        maintenanceUnitList.add(maintenanceUnitMap2);
        maintenanceUnitList.add(maintenanceUnitMap3);
        maintenanceUnitList.add(maintenanceUnitMap4);
        maintenanceUnitList.add(maintenanceUnitMap5);
        maintenanceUnitList.add(maintenanceUnitMap6);
        maintenanceUnit.setItems(maintenanceUnitList);
        partDetail.setManufacturer(maintenanceUnit);
        devInfo.setPartDetail(partDetail);
        //全部信息
        Map<String, Object> res = new LinkedHashMap<>();

        res.put("currAlaram", currAlaram);
        res.put("devInfo", devInfo);

        return res;
    }

    @Override
    public Map<String, Object> getMaintenanceInfo(String checkDate) {
        return JSONObject.parseObject(maintenance);
    }

    /**
     * 或者设备id判断装备是否单件录入 false:批量 true单件
     *
     * @param qrCode
     * @return
     */
    @Override
    public boolean equipmentgetIsSingleByQrcode(String qrCode, Long equipmentSpecifticId) {
        EquipmentSpecific equipmentSpecific;
        if (StringUtils.isBlank(qrCode)) {
            QueryWrapper<EquipmentSpecific> wrapper = new QueryWrapper<>();
            wrapper.eq("equipment_specific_id", equipmentSpecifticId);
            equipmentSpecific = this.baseMapper.selectOne(wrapper);
        } else {
            QueryWrapper<EquipmentSpecific> wrapper = new QueryWrapper<>();
            wrapper.eq("qr_code", qrCode);
            equipmentSpecific = this.baseMapper.selectOne(wrapper);

        }
        if (equipmentSpecific == null) {
            return false;
        } else {
            return equipmentSpecific.getSingle();
        }

    }

    @Override
    public EquipmentSpecific equipmentByQrcode(String qrCode) {
        EquipmentSpecific equipmentSpecific;
        QueryWrapper<EquipmentSpecific> wrapper = new QueryWrapper<>();
        wrapper.eq("qr_code", qrCode);
        equipmentSpecific = this.baseMapper.selectOne(wrapper);
        return equipmentSpecific;
    }

    @Override
    public Boolean delEquipmentSpecific(Long id) {
        EquipmentSpecific equipmentSpecific = this.baseMapper.selectById(id);
        QueryWrapper<StockDetail> stockDetailQueryWrapper = new QueryWrapper<>();
        stockDetailQueryWrapper.eq("equipment_specific_id", equipmentSpecific.getId());
        if (stockDetailService.count(stockDetailQueryWrapper) > 0) {
            throw new RuntimeException("设备已入库，无法删除");
        }
        String code = this.getSystemCodeBySpeId(equipmentSpecific.getSystemId());
        int res = this.baseMapper.deleteById(id);
        if (StringUtil.isNotEmpty(code)) {
            this.integrationPageSysDataRefresh(code);
        }
        if (res > 0 && syncSwitch) {
            //数据同步
        	delEquipmentSpecificSyncData(id);
        }
        //判断装备表剩余数量，无剩余删除模板
        QueryWrapper<EquipmentSpecific> wrapper = new QueryWrapper<>();
        wrapper.eq("equipment_detail_id", equipmentSpecific.getEquipmentDetailId());
        List<String> sys = this.baseMapper.selectSystemList(id);
        List<String> build = this.baseMapper.selectBuildList(id);
        String sysErrorMeg = "";
        String buildErrorMeg = "";
        if (sys.size() > 0 || build.size() > 0) {
            for (String s : sys) {
                sysErrorMeg = sysErrorMeg.equals("") ? s : sysErrorMeg + "," + s;
            }
            for (String s : build) {
                buildErrorMeg = buildErrorMeg.equals("") ? s : buildErrorMeg + "," + s;
            }
            sysErrorMeg = sysErrorMeg.equals("") ? sysErrorMeg : "系统：" + sysErrorMeg + ",";
            buildErrorMeg = buildErrorMeg.equals("") ? buildErrorMeg : "建筑：" + buildErrorMeg + ",";
            throw new RuntimeException("设备与" + sysErrorMeg + buildErrorMeg + "存在绑定关系，无法删除");
        }
        if (this.baseMapper.selectCount(wrapper) == 0) {
            equipmentDetailService.removeById(equipmentSpecific.getEquipmentDetailId());
        }
        if (res > 0) {
            // 删除设备动态表单扩展属性
            return formInstanceService.deleteInstanceById(id);
        } else {
            return false;
        }
    }

    private String getSystemCodeBySpeId(String sysIds) {
        if (StringUtil.isNotEmpty(sysIds)) {
            List<FireFightingSystemEntity> sys = fireFightingSystemMapper.getFightingSysByIds(sysIds.split(","));
            return sys.stream().map(FireFightingSystemEntity::getCode).collect(Collectors.joining(","));
        } else {
            return null;
        }
    }

    
    public void delEquipmentSpecificSyncData(Long id){
    	 //数据同步
        syncDataService.syncDeletedEquipmentSpecific(Arrays.asList(id));
        List<EquipmentIndexVO> indexBySpecificIdIn = equipmentSpecificIndexSerivce.getEquipIndexBySpecificIdIn(Arrays.asList(String.valueOf(id)));
        if (!indexBySpecificIdIn.isEmpty()) {
            List<Long> fireEquipmentInfoCollect = indexBySpecificIdIn.stream().filter(vo -> 0 == vo.getIsIot()).map(EquipmentIndexVO::getId).collect(Collectors.toList());
            List<Long> fireEquipMeasurementCollect = indexBySpecificIdIn.stream().filter(vo -> 1 == vo.getIsIot()).map(EquipmentIndexVO::getId).collect(Collectors.toList());
            syncDataService.syncDeletedEquipmentSpecificInfo(fireEquipmentInfoCollect);
            syncDataService.syncDeletedFireEquipMeasurement(fireEquipMeasurementCollect);
        }
    }
    @Override
    public Object getOneCard(Long id, String type) {
        if (BitmapEnum.video.getKey().equals(type)) {
            AlamVideoVO video = videoMapper.getVideoById(id);
            if (!ObjectUtils.isEmpty(video)) {
                video.setUrl(videoService.getVideoUrl(video.getName().toString(), video.getPresetPosition(), video.getUrl(), video.getCode()));
                video.setId(id);
                video.setVedioFormat(vedioFormat);
            }
            return video;
        } else {
            DetailPaneVO detailPaneVO = new DetailPaneVO();
            Map<String, String> map = this.baseMapper.getQrCodeAndPic(id);
            if (ObjectUtils.isEmpty(map)) {
                return detailPaneVO;
            }
            detailPaneVO.setQrCode(map.get("qrCode"));
            detailPaneVO.setPic(map.get("pic"));
            detailPaneVO.setItems(this.baseMapper.getOneCard(id));
            return detailPaneVO;
        }
    }

    @Override
    public SourceNameByEquipSpeIdVO getSourceNameByEquipSpeId(Long id) {
        return this.baseMapper.getSourceNameByEquipSpeId(id);
    }

    @Override
    public IPage<SourceNameByEquipSpeIdVO> getSourceNameList(IPage page, Long warehouseStructureId, Long sourceId, String equipmentName, String equipmentCode) {
        return this.baseMapper.getSourceNameList(page, warehouseStructureId, sourceId, equipmentName, equipmentCode);
    }

    @Override
    public List<FireEquipment> getEquipSpecificDetailsByEquipmentId(Long equipmentId) {
        List<FireEquipment> detailsByEquipmentId = equipmentSpecificMapper.getEquipSpecificDetailsByEquipmentId(equipmentId);
        if (detailsByEquipmentId != null && !detailsByEquipmentId.isEmpty()) {
            return detailsByEquipmentId;
        }
        return Lists.newArrayList();
    }

    @Override
    public List<EquipmentSpecific3dVo> get3dFightingSysEquipList(Long id, Integer status, String name) {
        List<EquipmentSpecific3dVo> list = equipmentSpecificMapper.get3dFightingSysEquipList(id, name);
        if (!CollectionUtils.isEmpty(list)) {
            if (status != null) {
                return list.stream().filter(x -> status.equals(x.getStatus())).collect(Collectors.toList());
            }
            return list;
        }
        return Lists.newArrayList();
    }

    @Override
    public Page<EquipmentSpecific3dVo> listPage(Page<EquipmentSpecific3dVo> pageBean, EquipFor3DVO equipment) {
        List<EquipmentSpecific3dVo> list = equipmentSpecificMapper.listPage(equipment, pageBean.offset(), pageBean.getSize());
        int count = equipmentSpecificMapper.listCount(equipment);
        Page<EquipmentSpecific3dVo> page = new Page<>(pageBean.getCurrent(), pageBean.getSize());
        page.setRecords(list);
        page.setTotal(count);
        return page;
    }

    @Override
    public List<LinkedHashMap> get3dFightingSysEquipCount(Long id, Integer status, String name) {
        List<LinkedHashMap> map = equipmentSpecificMapper.get3dFightingSysEquipCount(id, status, name);
        if (!CollectionUtils.isEmpty(map)) {
            return map;
        }
        return Lists.newArrayList();
    }

    @Override
    public List<EquipmentOnCarVo> getAirEquipSpecificList(String like, String notLike, Integer status) {
        String[] split = null;
        if (StringUtil.isNotEmpty(notLike)) {
            split = notLike.split(",");
        }
        List<EquipmentOnCarVo> list = equipmentSpecificMapper.getAirEquipSpecificList(like, split, status);
        if (!CollectionUtils.isEmpty(list)) {
            return list;
        }
        return Lists.newArrayList();
    }

    @Override
    public IPage<EquipmentOnCarVo> onCarVoIPage(EquipmentSpecificDto equipmentSpecificDto) {
        String[] strs = null;
        if (StringUtil.isNotEmpty(codes)) {
            strs = codes.split(",");
        }
        equipmentSpecificDto.setCodes(strs);
        String categoryCode = equipmentSpecificDto.getCategoryCode();
//        List<String> categoryCodeList = null;
//        if (StringUtils.isNotEmpty(categoryCode)) {
//            QueryWrapper<EquipmentCategory> queryWrapper = new QueryWrapper<>();
//            EquipmentCategory categoryEntity = iEquipmentCategoryService.getOne(queryWrapper.eq("code", categoryCode).eq("industry_code", equipmentCategoryLeftTypeCode));
//            List<EquipmentCategory> categoryList = equipmentCategoryService.getEquipmentCategoryList(Integer.valueOf(equipmentCategoryLeftTypeCode));
//            Collection<EquipmentCategory> categorieTree = TreeBuilder.buildByRecursive(categoryList, categoryEntity.getId());
//            List<EquipmentCategory> categorieChildren = TreeUtil.getAllChildren(categorieTree);
//            categoryCodeList = categorieChildren.stream().map(category -> category.getCode()).collect(Collectors.toList());
//            categoryCodeList.add(categoryCode);
//        }
//        String str = org.apache.commons.lang.StringUtils.join(categoryCodeList.toArray(), ",");
//        equipmentSpecificDto.setCategories("(" + str + ")");
        equipmentSpecificDto.setCategories(categoryCode);
        return this.baseMapper.onCarVoIPage(equipmentSpecificDto.getPage(), equipmentSpecificDto);
    }

    @Override
    public EquipmentDetailVo getAirEquipSpecificDetail(Long stockDetailId) {
        return equipmentSpecificMapper.getAirEquipSpecificDetail(stockDetailId);
    }

    @Override
    public List<UserDto> getEquipSpecificLocationInfo(Long equipmentSpecificId, String[] fieldName) {
        return equipmentSpecificMapper.getEquipSpecificLocationInfo(equipmentSpecificId, fieldName);
    }

    public Map<String,Double> getEquipLocationInfo(Long equipmentSpecificId) {
        return equipmentSpecificMapper.getEquipLocationInfo(equipmentSpecificId);
    }

    @Override
    @Async("equipAsyncExecutor")
    public void equipSpecificDataSync(Long equipmentId) {
        //  TODO 放大范围，根据equipment_id同步
        List<FireEquipment> specificDetails = getEquipSpecificDetailsByEquipmentId(equipmentId);
        if (specificDetails.size() > 0) {
            syncDataService.syncCreatedEquipmentSpecific(specificDetails);
            List<String> specificIds = new ArrayList<>();
            specificDetails.stream().forEach(x -> specificIds.add(x.getId()));
            List<EquipmentIndexVO> specificIndexList = equipmentSpecificIndexSerivce.getEquipIndexBySpecificIdIn(specificIds);
            List<EquipmentIndexVO> fireEquipmentInfoCollect = specificIndexList.stream().filter(vo -> 0 == vo.getIsIot()).collect(Collectors.toList());
            List<EquipmentIndexVO> fireEquipMeasurementCollect = specificIndexList.stream().filter(vo -> 1 == vo.getIsIot()).collect(Collectors.toList());
            syncDataService.syncCreatedEquipmentSpecificInfo(fireEquipmentInfoCollect);
            syncDataService.syncCreatedFireEquipMeasurement(fireEquipMeasurementCollect);
        }
    }

    @Override
    @Transactional
    public EquipmentDate equipmentSpecificCreate(EquipmentDate equipmentData, ReginParams reginParams, AgencyUserModel agencyUserModel) {
        StringBuilder fireFightSysIdsBuffer = new StringBuilder();
        EquipmentSpecific equipmentSpecific = equipmentData.getEquipmentSpecific();
        equipmentSpecific.setStock(new Stock().setWarehouseId(0L));
        EquipmentDetail equipmentDetail = equipmentData.getEquipmentDetail();
        Equipment equipment = equipmentService.getById(equipmentDetail.getEquipmentId());
        if (equipment != null) {
            String equipmentCode = equipment.getCode();
            equipmentDetail.setCode(equipmentCode);
            equipmentDetail.setEquipmentName(equipment.getName());
            equipmentSpecific.setEquipmentCode(equipmentCode);
            equipmentSpecific.setName(equipmentDetail.getName());

            if (StringUtil.isNotEmpty(equipmentDetail.getArea())) {
                String[] addressData = equipmentDetail.getArea().split("@address@");
                if (addressData.length > 1) {
                    equipmentDetail.setArea(addressData[0]);
                    JSONObject langLatObj = JSON.parseObject(addressData[1]);
                    if (StringUtil.isNotEmpty(langLatObj.getString("longitude"))) {
                        equipmentDetail.setLongitude(Double.valueOf(langLatObj.getString("longitude")));
                    }
                    if (StringUtil.isNotEmpty(langLatObj.getString("latitude"))) {
                        equipmentDetail.setLatitude(Double.valueOf(langLatObj.getString("latitude")));
                    }
                }
            }
        }
        Long warehouseStructureId = null;
        if (!ObjectUtils.isEmpty(equipmentSpecific.getStockDetail())) {
            warehouseStructureId = equipmentSpecific.getStockDetail().getWarehouseStructureId();
        }
        if (warehouseStructureId != null) {
            WarehouseStructure warehouseStructure = warehouseStructureService.getById(warehouseStructureId);
            if (!ObjectUtils.isEmpty(warehouseStructure)) {
                equipmentSpecific.setPosition(warehouseStructure.getFullName());
            }
        }
        if (!equipmentSpecific.getSingle()) {
            //TODO 非单件管理逻辑
            //1.数据制码
            equipmentDetail = equipmentDetailService.saveOne(equipmentDetail);
            String qrCode = QRCodeUtil.generateQRCode();
            //2.插入设备数据
            equipmentSpecific.setStock(new Stock().setWarehouseId(0L));
            equipmentSpecific.setEquipmentDetailId(equipmentDetail.getId());
            equipmentSpecific.setQrCode(qrCode);
            equipmentSpecific.setOrgCode(reginParams.getCompany().getOrgCode());
            if (equipmentSpecific.getStockDetail() != null && equipmentSpecific.getStockDetail().getWarehouseStructureId() != null) {
                equipmentSpecific.setWarehouseStructureId(equipmentSpecific.getStockDetail().getWarehouseStructureId());
            }
            boolean save = this.save(equipmentSpecific);
            if (save) {
                fireFightSysIdsBuffer.append(equipmentSpecific.getSystemId() + ",");
            }
            List<EquipmentSpecific> equipmentSpecifics = Collections.singletonList(equipmentSpecific);
            //没传仓库的情况下，默认单个仓库
            if (equipmentSpecific.getStock().getWarehouseId() == null) {
                List<Warehouse> list = warehouseService.list();
                if (list.size() > 0) {
                    equipmentSpecific.getStock().setWarehouseId(list.get(0).getId());
                } else {
                    equipmentSpecific.getStock().setWarehouseId(0L);
                }
            }

            //4.如果位置不为空，入库
            if (equipmentSpecific.getStockDetail() != null && equipmentSpecific.getStockDetail().getWarehouseStructureId() != null) {

                //3.初始化物理监控查询数据
                initEquipmentSystemSourceStatistics(equipmentSpecifics);

                //4.1插入库存
                equipmentSpecific.getStock().setAmount(Double.valueOf(equipmentSpecific.getNum()));
                equipmentSpecific.getStock().setCompanyName(reginParams.getCompany().getCompanyName());
                equipmentSpecific.getStock().setOrgCode(reginParams.getCompany().getOrgCode());
                equipmentSpecific.getStock().setDepartmentOrgcode(reginParams.getDepartment().getOrgCode());
                equipmentSpecific.getStock().setDepartmentName(reginParams.getDepartment().getDepartmentName());
                equipmentSpecific.getStock().setEquipmentDetailId(equipmentSpecific.getEquipmentDetailId());
                stockService.save(equipmentSpecific.getStock());

                //4.2库存详情
                equipmentSpecific.getStockDetail().setCompanyName(reginParams.getCompany().getCompanyName());
                equipmentSpecific.getStockDetail().setOrgCode(reginParams.getCompany().getOrgCode());
                equipmentSpecific.getStockDetail().setDepartmentName(reginParams.getDepartment().getDepartmentName());
                equipmentSpecific.getStockDetail().setDepartmentOrgcode(reginParams.getDepartment().getOrgCode());
                equipmentSpecific.getStockDetail().setEquipmentDetailId(equipmentSpecific.getEquipmentDetailId());
                equipmentSpecific.getStockDetail().setAmount(Double.valueOf(equipmentSpecific.getNum()));
                equipmentSpecific.getStockDetail().setStockId(equipmentSpecific.getStock().getId());
                equipmentSpecific.getStockDetail().setStatus(StockBillTypeEnum.DBRK.getValue());
                equipmentSpecific.getStockDetail().setUpdateDate(new Date());
                equipmentSpecific.getStockDetail().setWarehouseId(equipmentSpecific.getStock().getWarehouseId());
                equipmentSpecific.getStockDetail().setEquipmentSpecificId(equipmentSpecific.getId());
                equipmentSpecific.getStockDetail().setQrCode(qrCode);
                equipmentSpecific.getStockDetail().setBatchNum(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
                equipmentSpecific.getStockDetail().setDescription(equipmentDetail.getArea());
                stockDetailService.save(equipmentSpecific.getStockDetail());

                //4.3生成入库单
                StockBill stockBill = buildStockBills(equipmentSpecific, reginParams, agencyUserModel);
                stockBillService.save(stockBill);
                //4.3生成入库单详情
                StockBillDetail stockBillDetail = new StockBillDetail();
                stockBillDetail.setAmount(equipmentSpecific.getStockDetail().getAmount());
                stockBillDetail.setEquipmentDetailId(equipmentSpecific.getEquipmentDetailId());
                stockBillDetail.setStockDetailId(equipmentSpecific.getStockDetail().getId());
                buildStockBatchNo(agencyUserModel, equipmentSpecific, stockBill, stockBillDetail);
            }

            //装备实例对应的性能指标保存
            equipmentSpecificIndexSave(equipmentData, equipmentSpecific);
        } else {
            //TODO 单件管理逻辑
            List<EquipmentSpecific> equipmentSpecifics = new ArrayList<>();
            //如果多个二维码说明单项管理，批量录入
            if (equipmentSpecific.getNum() > 1) {
                //TODO 1.去掉模板概念了，把EquipmentDetail当成EquipmentSpecific一对一子表,有多少二维码生成就有多少个EquipmentDetail
                List<EquipmentDetail> equipmentDetails = this.saveEquipmentDetailBatch(equipmentData.getEquipmentDetail(), equipmentSpecific.getNum());
                //2.生成二维码数据
                List<String> list = genQrCode(equipmentDetails);
                //3.插入设备实例基本表
                for (int i = 0; i < list.size(); i++) {
                    EquipmentSpecific equipmentSpecificBatch = new EquipmentSpecific();
                    BeanUtils.copyProperties(equipmentSpecific, equipmentSpecificBatch);
                    equipmentSpecificBatch.setQrCode(list.get(i));
                    equipmentSpecificBatch.setOrgCode(reginParams.getCompany().getOrgCode());
                    equipmentSpecificBatch.setEquipmentDetailId(equipmentDetails.get(i).getId());
                    if (equipmentSpecific.getStockDetail() != null && equipmentSpecific.getStockDetail().getWarehouseStructureId() != null) {
                        equipmentSpecificBatch.setWarehouseStructureId(equipmentSpecific.getStockDetail().getWarehouseStructureId());
                    }
                    equipmentSpecifics.add(equipmentSpecificBatch);
                    fireFightSysIdsBuffer.append(equipmentSpecificBatch.getSystemId() + ",");
                }
                this.saveBatch(equipmentSpecifics);


                //4.初始化统计表
                initEquipmentSystemSourceStatistics(equipmentSpecifics);
                //没传仓库的情况下，默认单个仓库
                if (equipmentSpecific.getStock().getWarehouseId() == null) {
                    List<Warehouse> warehouseslist = warehouseService.list();
                    if (warehouseslist.size() > 0) {
                        equipmentSpecific.getStock().setWarehouseId(warehouseslist.get(0).getId());
                    } else {
                        equipmentSpecific.getStock().setWarehouseId(0L);
                    }
                }
                //5.如果位置不为空,入库
                if (equipmentSpecific.getStockDetail() != null && equipmentSpecific.getStockDetail().getWarehouseStructureId() != null) {
                    //5.1批量插入库存信息
                    List<Stock> stocks = new ArrayList<>();
                    equipmentSpecifics.forEach(y -> {
                        Stock stock = new Stock();
                        BeanUtils.copyProperties(y.getStock(), stock);
                        stock.setAmount(1d);
                        stock.setCompanyName(reginParams.getCompany().getCompanyName());
                        stock.setOrgCode(reginParams.getCompany().getOrgCode());
                        stock.setDepartmentOrgcode(reginParams.getDepartment().getOrgCode());
                        stock.setDepartmentName(reginParams.getDepartment().getDepartmentName());
                        stock.setEquipmentDetailId(y.getEquipmentDetailId());
                        stocks.add(stock);
                    });
                    stockService.saveBatch(stocks);

                    //5.2批量插入库存详情
                    List<StockDetail> stockDetails = new ArrayList<>();
                    for (int i = 0; i < stocks.size(); i++) {
                        StockDetail stockDetail = new StockDetail();
                        BeanUtils.copyProperties(equipmentSpecifics.get(i).getStockDetail(), stockDetail);
                        stockDetail.setCompanyName(reginParams.getCompany().getCompanyName());
                        stockDetail.setOrgCode(reginParams.getCompany().getOrgCode());
                        stockDetail.setDepartmentName(reginParams.getDepartment().getDepartmentName());
                        stockDetail.setDepartmentOrgcode(reginParams.getDepartment().getOrgCode());
                        stockDetail.setEquipmentDetailId(stocks.get(i).getEquipmentDetailId());
                        stockDetail.setStockId(stocks.get(i).getId());
                        stockDetail.setStatus(StockBillTypeEnum.DBRK.getValue());
                        stockDetail.setAmount(1d);
                        stockDetail.setWarehouseId(stocks.get(i).getWarehouseId());
                        stockDetail.setUpdateDate(new Date());
                        stockDetail.setQrCode(list.get(i));
                        stockDetail.setEquipmentSpecificId(equipmentSpecifics.get(i).getId());
                        stockDetail.setDescription(equipmentDetail.getArea());
                        stockDetails.add(stockDetail);
                        stockDetail.setBatchNum(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
                    }
                    stockDetailService.saveBatch(stockDetails);
                    //5.3生成入库单
                    List<StockBill> stockBills = new ArrayList<>();
                    for (int i = 0; i < stockDetails.size(); i++) {
                        stockBills.add(buildStockBills(equipmentSpecific, reginParams, agencyUserModel));
                    }
                    stockBillService.saveBatch(stockBills);
                    //5.4生成入库单详情
                    List<StockBillDetail> stockBillDetails = new ArrayList<>();
                    for (int i = 0; i < stockBills.size(); i++) {
                        StockBillDetail stockBillDetail = new StockBillDetail();
                        stockBillDetail.setAmount(1d);
                        //TODO 顺序一致，所以按照下标取
                        stockBillDetail.setEquipmentDetailId(stockDetails.get(i).getEquipmentDetailId());
                        stockBillDetail.setStockDetailId(stockDetails.get(i).getId());
                        try {
                            stockBillDetail.setBatchNum(DateUtils.dateFormat(new Date(), DateUtils.DATE_PATTERN));
                        } catch (ParseException e) {
                            log.error(e.getMessage(), e);
                            throw new BaseException("格式化失败");
                        }
                        stockBillDetail.setCreatorId(Long.valueOf(agencyUserModel.getUserId()));
                        stockBillDetail.setSingleEquipCode(stockDetails.get(i).getQrCode());
                        stockBillDetail.setStockBillId(stockBills.get(i).getId());
                        stockBillDetail.setWarehouseStructureId(stockDetails.get(i).getWarehouseStructureId());
                        stockBillDetails.add(stockBillDetail);
                    }
                    stockBillDetailService.saveBatch(stockBillDetails);
                }
                //6.装备实例对应的性能指标保存
                List<EquipmentSpecificIndex> equipmentSpecificIndices = new ArrayList<>();
                List<EquProperty> equProperties = equipmentData.getEquipmentDetail().getEquPropertyList();
                for (EquipmentSpecific specific : equipmentSpecifics) {
                    buildEquipmentSpecificIndices(equipmentSpecificIndices, equProperties, specific, equipmentData.getEquipmentDetail().getName());
                }
                equipmentSpecificIndexSerivce.saveBatch(equipmentSpecificIndices);

                //页面参数返回数据处理
                EquipmentSpecific resultEquipSpec = equipmentSpecifics.get(0);
                resultEquipSpec.setNum(1);
                equipmentData.setEquipmentDetail(equipmentDetails.get(0));
                equipmentData.setEquipmentSpecific(resultEquipSpec);
            } else {
                //单项管理,逐个录入
                equipmentDetail = equipmentDetailService.saveOne(equipmentDetail);
                String qrCode = QRCodeUtil.generateQRCode();
                equipmentSpecific.setQrCode(qrCode);
                equipmentSpecific.setOrgCode(reginParams.getCompany().getOrgCode());
                equipmentSpecific.setEquipmentDetailId(equipmentDetail.getId());
                equipmentSpecific.setCreateDate(new Date());
                if (equipmentSpecific.getStockDetail() != null && equipmentSpecific.getStockDetail().getWarehouseStructureId() != null) {
                    equipmentSpecific.setWarehouseStructureId(equipmentSpecific.getStockDetail().getWarehouseStructureId());
                }
                //插入设备数据
                int insert = this.baseMapper.insert(equipmentSpecific);
                if (insert > 0) {
                    fireFightSysIdsBuffer.append(equipmentSpecific.getSystemId() + ",");
                }
                equipmentSpecifics.add(equipmentSpecific);
                initEquipmentSystemSourceStatistics(equipmentSpecifics);
                //没传仓库的情况下，默认单个仓库
                if (equipmentSpecific.getStock().getWarehouseId() == null) {
                    List<Warehouse> warehouseslist = warehouseService.list();
                    if (warehouseslist.size() > 0) {
                        equipmentSpecific.getStock().setWarehouseId(warehouseslist.get(0).getId());
                    } else {
                        equipmentSpecific.getStock().setWarehouseId(0L);
                    }
                }
                //如果位置不为空,入库
                if (equipmentSpecific.getStockDetail() != null && equipmentSpecific.getStockDetail().getWarehouseStructureId() != null) {
                    //插入库存
                    equipmentSpecific.getStock().setAmount(Double.valueOf(equipmentSpecific.getNum()));
                    equipmentSpecific.getStock().setCompanyName(reginParams.getCompany().getCompanyName());
                    equipmentSpecific.getStock().setCompanyName(reginParams.getCompany().getOrgCode());
                    equipmentSpecific.getStock().setDepartmentOrgcode(reginParams.getDepartment().getOrgCode());
                    equipmentSpecific.getStock().setCompanyName(reginParams.getDepartment().getDepartmentName());
                    equipmentSpecific.getStock().setEquipmentDetailId(equipmentSpecific.getEquipmentDetailId());
                    stockService.save(equipmentSpecific.getStock());

                    //插入库存详情
                    equipmentSpecific.getStockDetail().setCompanyName(reginParams.getCompany().getCompanyName());
                    equipmentSpecific.getStockDetail().setOrgCode(reginParams.getCompany().getOrgCode());
                    equipmentSpecific.getStockDetail().setAmount(Double.valueOf(equipmentSpecific.getNum()));
                    equipmentSpecific.getStockDetail().setDepartmentName(reginParams.getDepartment().getDepartmentName());
                    equipmentSpecific.getStockDetail().setDepartmentOrgcode(reginParams.getDepartment().getOrgCode());
                    equipmentSpecific.getStockDetail().setEquipmentDetailId(equipmentSpecific.getEquipmentDetailId());
                    equipmentSpecific.getStockDetail().setStockId(equipmentSpecific.getStock().getId());
                    equipmentSpecific.getStockDetail().setStatus(StockBillTypeEnum.DBRK.getValue());
                    equipmentSpecific.getStockDetail().setUpdateDate(new Date());
                    equipmentSpecific.getStockDetail().setQrCode(qrCode);
                    equipmentSpecific.getStockDetail().setWarehouseId(equipmentSpecific.getStock().getWarehouseId());
                    equipmentSpecific.getStockDetail().setEquipmentSpecificId(equipmentSpecific.getId());
                    equipmentSpecific.getStockDetail().setBatchNum(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
                    equipmentSpecific.getStockDetail().setDescription(equipmentDetail.getArea());
                    stockDetailService.save(equipmentSpecific.getStockDetail());
                    //生成入库单
                    StockBill stockBill = buildStockBills(equipmentSpecific, reginParams, agencyUserModel);
                    stockBillService.save(stockBill);
                    StockBillDetail stockBillDetail = new StockBillDetail();
                    stockBillDetail.setAmount(equipmentSpecific.getStockDetail().getAmount());
                    stockBillDetail.setEquipmentDetailId(equipmentSpecific.getEquipmentDetailId());
                    stockBillDetail.setStockDetailId(equipmentSpecific.getStockDetail().getId());
                    buildStockBatchNo(agencyUserModel, equipmentSpecific, stockBill, stockBillDetail);
                }
                //装备实例对应的性能指标保存
                equipmentSpecificIndexSave(equipmentData, equipmentSpecific);
            }
        }
        relationRedisUtil.delSysRedisKey(fireFightSysIdsBuffer.toString());
        return equipmentData;
    }

    @Override
    public FireEquipment getEquipSpecificDetail(EquipmentSpecific equipmentSpecific) {
        FireEquipment fireEquipment = equipmentSpecificMapper.getEquipSpecificDetail(equipmentSpecific.getId());
        String fullName = fireEquipment.getFullName();
        if (StringUtils.isNotBlank(fullName) && fullName.indexOf("-") != -1){
            fireEquipment.setBuildName(fullName.split("-")[0]);
        }
        return fireEquipment;
    }

    @Override
    public FireEquipmentVO getInstanceIdAndOrgCode(Long sourceId) {
        FireEquipmentVO finalVo = new FireEquipmentVO();
        WarehouseStructure warehouseStructure = warehouseStructureMapper.selectById(sourceId);
        if (0 == warehouseStructure.getParentId()) {
            finalVo.setInstanceId(String.valueOf(warehouseStructure.getSourceId()));
            finalVo.setBizOrgCode(warehouseStructure.getBizOrgCode());
        } else {
            warehouseStructure = getWarehouseStructure(warehouseStructureMapper.selectById(warehouseStructure.getParentId()));
            finalVo.setInstanceId(String.valueOf(warehouseStructure.getSourceId()));
            finalVo.setBizOrgCode(warehouseStructure.getBizOrgCode());
        }
        QueryWrapper<FormInstance> qw = new QueryWrapper<>();
        qw.lambda().eq(FormInstance::getInstanceId, sourceId)
                .eq(FormInstance::getFieldName, "bizOrgCode");
        FormInstance formInstance = formInstanceMapper.selectOne(qw);
        finalVo.setBizOrgCode(formInstance.getFieldValue());
        return finalVo;
    }

    public WarehouseStructure getWarehouseStructure(WarehouseStructure warehouseStructure) {
        if (0 == warehouseStructure.getParentId()) {
            return warehouseStructure;
        } else {
           warehouseStructure = warehouseStructureMapper.selectById(warehouseStructure.getParentId());
           return getWarehouseStructure(warehouseStructure);
        }
    }

    @Override
    public String getEquipSpeTypeByQrcode(String qrCode) {
        List<EquipmentCategory> list = this.baseMapper.getEquipSpeTypeByQrcode(qrCode);
        if (list != null && list.size() > 0) {
            EquipmentCategory equipmentCategory = list.get(0);
            String pre = equipmentCategory.getCode().substring(0, 1);
            if ("4".equals(pre)) {
                return "agent";
            } else {
                return "equipment";
            }
        } else {
            throw new RuntimeException("请输入正确编码！");
        }
    }

    private List<String> genQrCode(List<EquipmentDetail> equipmentDetails) {
        List<String> all = new ArrayList<>();
        equipmentDetails.forEach(e -> {
            all.add(QRCodeUtil.generateQRCode());
        });
        return all;
    }

    private void buildEquipmentSpecificIndices(List<EquipmentSpecificIndex> equipmentSpecificIndices,
                                               List<EquProperty> equProperties, EquipmentSpecific specific, String equipName) {
        equProperties.forEach(x -> {
            EquipmentSpecificIndex equipmentSpecificIndex = new EquipmentSpecificIndex();
            equipmentSpecificIndex.setId(null);
            equipmentSpecificIndex.setValue(x.getValue());
            equipmentSpecificIndex.setEquipmentIndexId(x.getEquipmentIndexId());
            equipmentSpecificIndex.setEquipmentSpecificId(specific.getId());
            EquipmentIndex index = iEquipmentIndexService.getById(x.getEquipmentIndexId());
            equipmentSpecificIndex.setEquipmentSpecificName(equipName);
            equipmentSpecificIndex.setEquipmentIndexName(index.getPerfQuotaName());
            equipmentSpecificIndex.setEquipmentIndexKey(index.getPerfQuotaDefinitionId());
            equipmentSpecificIndex.setEmergencyLevelColor(index.getEmergencyLevelColor());
            equipmentSpecificIndex.setIsAlarm(index.getIsAlarm());
            equipmentSpecificIndex.setEmergencyLevel(index.getEmergencyLevel());
            equipmentSpecificIndex.setEmergencyLevelDescribe(index.getEmergencyLevelDescribe());
            equipmentSpecificIndices.add(equipmentSpecificIndex);
        });
    }

    private void buildStockBatchNo(AgencyUserModel agencyUserModel, EquipmentSpecific equipmentSpecific, StockBill stockBill, StockBillDetail stockBillDetail) {
        try {
            stockBillDetail.setBatchNum(DateUtils.dateFormat(new Date(), DateUtils.DATE_PATTERN));
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
            throw new BaseException("格式化失败");
        }
        stockBillDetail.setCreatorId(Long.valueOf(agencyUserModel.getUserId()));
        stockBillDetail.setSingleEquipCode(equipmentSpecific.getStockDetail().getQrCode());
        stockBillDetail.setStockBillId(stockBill.getId());
        stockBillDetail.setWarehouseStructureId(equipmentSpecific.getStockDetail().getWarehouseStructureId());
        stockBillDetailService.save(stockBillDetail);
    }

    public void equipmentSpecificIndexSave(EquipmentDate equipmentData, EquipmentSpecific equipmentSpecific) {
        List<EquipmentSpecificIndex> equipmentSpecificIndices = new ArrayList<>();
        List<EquProperty> equProperties = equipmentData.getEquipmentDetail().getEquPropertyList();
        buildEquipmentSpecificIndices(equipmentSpecificIndices, equProperties, equipmentSpecific, equipmentData.getEquipmentDetail().getName());
        equipmentSpecificIndexSerivce.saveBatch(equipmentSpecificIndices);
    }

    @Async("equipAsyncExecutor")
    void initEquipmentSystemSourceStatistics(List<EquipmentSpecific> equipmentSpecifics) {
        List<EquipmentSystemSourceStatistics> list = new ArrayList<>();
        equipmentSpecifics.parallelStream().forEach(x -> {
            //插入统计区域设备关表，初始化数据
            EquipmentSystemSourceStatistics equipmentSystemSourceStatistics = new EquipmentSystemSourceStatistics();
            equipmentSystemSourceStatistics.setEquipmentSpecificId(x.getId());
            equipmentSystemSourceStatistics.setStatus(1);
            if (x.getStockDetail() != null && x.getStockDetail().getWarehouseStructureId() != null) {
                WarehouseStructure warehouseStructure = warehouseStructureService.getById(x.getStockDetail().getWarehouseStructureId());
                while (warehouseStructure.getParentId() != null && !warehouseStructure.getParentId().equals(warehouseStructure.getWarehouseId())) {
                    warehouseStructure = warehouseStructureService.getById(warehouseStructure.getParentId());
                }
                equipmentSystemSourceStatistics.setSourceId(warehouseStructure.getId());
            }
            list.add(equipmentSystemSourceStatistics);
        });
        equipmentSystemSourceStatisticsService.saveBatch(list);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delEquipmentBySpecificId(Long specificId) {
        // 1.删除相关主表数据
        this.baseMapper.deleteEquipDataBySpecificId(specificId);

        // 2.删除已入库相关数据
        QueryWrapper<StockDetail> stockDetailQueryWrapper = new QueryWrapper<>();
        stockDetailQueryWrapper.eq("equipment_specific_id", specificId);
        StockDetail stockDetail = stockDetailService.getOne(stockDetailQueryWrapper);
        if (!ObjectUtils.isEmpty(stockDetail)) {
            // 已入库
            this.baseMapper.deleteEquipDataByStockDetailId(stockDetail.getId(), specificId);
        }
        
        if (syncSwitch) {
            //数据同步
        	delEquipmentSpecificSyncData(specificId);
        }

        return Boolean.TRUE;
    }

    /**
     * 刷新数字化大屏缓存数据及推送
     *
     * @param systemTypeCode
     */
    @Async("equipAsyncExecutor")
    @Override
    public void integrationPageSysDataRefresh(String systemTypeCode) {
        if (ObjectUtils.isEmpty(systemTypeCode)) {
            return;
        }
        String[] systemTypeCodes = systemTypeCode.split(",");
        for (String code : systemTypeCodes) {
            iFireFightingSystemService.integrationPageSysData(code, true);
        }
    }


    @Override
    public List<EquipmentSpecificVo> getEquipAndCarIotcodeByIotcode(String iotCode) {
        // TODO Auto-generated method stub
        List<EquipmentSpecificVo> data;
        if (redisUtils.hasKey("equipAndCarIotCodes")) {
            data = JSON.parseArray(redisUtils.get("equipAndCarIotCodes").toString(), EquipmentSpecificVo.class);
        } else {
            data = equipmentSpecificMapper.getEquipOrCarByIotCode(null);
            redisUtils.set("equipAndCarIotCodes", JSONObject.toJSONString(data));
        }
        if (ObjectUtils.isEmpty(data)) {
            return data;
        }
        List<EquipmentSpecificVo> resultData = data.stream().filter(a -> a.getIotCode().equals(iotCode)).collect(Collectors.toList());
        return resultData;
    }

    @Override
    public void updateEquipmentSpecIndexRealtimeData(EquipmentSpecificIndex index) {
        // TODO Auto-generated method stub
        if (!ObjectUtils.isEmpty(index)) {
            EquipmentSpecific es = equipmentSpecificMapper.selectById(index.getEquipmentSpecificId());
            es.setRealtimeIotEsIndexId(index.getId());
            es.setRealtimeIotIndexKey(index.getNameKey());
            es.setRealtimeIotIndexName(index.getEquipmentSpecificIndexName());
            es.setRealtimeIotIndexValue(index.getValue());
            es.setRealtimeIotIndexId(index.getEquipmentIndexId());
            es.setRealtimeIotIndexUpdateDate(index.getUpdateDate());
            es.setValueLabel(index.getValueLabel());
            equipmentSpecificMapper.updateById(es);
        }
    }

    @Override
    public Map<String, List<Map<String, String>>> getFessIndexDetails() {
        Map<String, List<Map<String, String>>> map = new HashMap<>();
        List<Map<String, String>> rainRoomIndexDetails = equipmentSpecificMapper.getRainRoomIndexDetails();
        List<Map<String, String>> choiceRoomIndexDetails = equipmentSpecificMapper.getChoiceRoomIndexDetails();
        List<Map<String, String>> boxTropicsIndexDetails = equipmentSpecificMapper.getBoxTropicsIndexDetails();
        List<Map<String, String>> tropicsIndexDetails = equipmentSpecificMapper.getTropicsIndexDetails();
        map.put("rainRoom", rainRoomIndexDetails);
        map.put("choiceRoom", choiceRoomIndexDetails);
        map.put("boxTropics", boxTropicsIndexDetails);
        map.put("tropics", tropicsIndexDetails);
        return map;
    }

    @Override
    public void refreshStaData() {
        List<Map<String, Object>> result = this.baseMapper.queryCompanyStaData();
        result.forEach(m -> redisUtils.set((buildKey(m)), m.get("total"), 86400));

        carService.iotrefreshStaData();
    }

    private String buildKey(Map<String, Object> row) {
        return SourcesStatisticsImpl.PREFIX_CATEGORY_COUNT + row.get("bizOrgCode").toString() + "_" + SourceTypeEnum.EQUIPMENT.getCode() + "_" + row.get("categoryCode").toString();
    }

    @Override
    public Boolean videoOnEquipmentSpecific(VideoOnEquipmentSpecificVo videoOnEquipmentSpecificVo) {
        Long equipmentSpecificId = videoOnEquipmentSpecificVo.getEquipmentSpecificId();
        List<Long> videoIdList = videoOnEquipmentSpecificVo.getVideoIdList();
        if (equipmentSpecificId != null) {
            EquipmentSpecific equipmentSpecific = this.baseMapper.selectById(equipmentSpecificId);
            if (!ObjectUtils.isEmpty(equipmentSpecific)) {
                QueryWrapper<VideoEquipmentSpecific> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("equipment_specific_id", equipmentSpecificId);
                if (0 == videoIdList.size()) {
                    videoEquipmentSpecificService.remove(queryWrapper);
                    return Boolean.TRUE;
                }
                List<VideoEquipmentSpecific> list = videoEquipmentSpecificService.getBaseMapper().selectList(queryWrapper);
                if (0 < list.size()) {
                    boolean remove = videoEquipmentSpecificService.remove(queryWrapper);
                    if (remove) {
                        this.bingEquipmentRelationshipToVideo(videoIdList, equipmentSpecificId);
                    }
                } else {
                    this.bingEquipmentRelationshipToVideo(videoIdList, equipmentSpecificId);
                }
                return Boolean.FALSE;
            } else {
                throw new RuntimeException("未获取到此设备！");
            }
        } else {
            throw new RuntimeException("设备ID为空！");
        }
    }

    @Override
    public Boolean delVideoOnEquipmentSpecific(Long equipmentSpecificId, Long videoId) {
        QueryWrapper<VideoEquipmentSpecific> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("equipment_specific_id", equipmentSpecificId);
        queryWrapper.eq("video_id", videoId);
        videoEquipmentSpecificService.remove(queryWrapper);
        return true;
    }

    private Boolean bingEquipmentRelationshipToVideo(List<Long> videoIdList, Long equipmentSpecificId) {
        List<VideoEquipmentSpecific> videoSpecificList = new ArrayList<>();
        videoIdList.parallelStream().forEach(x -> {
            VideoEquipmentSpecific videoEquipmentSpecific = new VideoEquipmentSpecific();
            videoEquipmentSpecific.setVideoId(x);
            videoEquipmentSpecific.setEquipmentSpecificId(equipmentSpecificId);
            videoSpecificList.add(videoEquipmentSpecific);
        });
        videoEquipmentSpecificService.saveBatch(videoSpecificList);
        return Boolean.TRUE;
    }

    @Override
    public List<Map<String, Object>> getListByEquipmentCode(String code) {
        List<Map<String, Object>> list = new ArrayList<>();
        if (StringUtil.isNotEmpty(code)) {
            String[] strings = code.split(",");
            list = equipmentSpecificMapper.getFirePumpInfo(strings);
        }
        return list;
    }

    @Override
    public List<IotIndexInfoVo> getIndexInfoList(String iotCode, ResponseModel entity, Integer isTrend, String fieldKey) {
        List<IotIndexInfoVo> infoVoList = new ArrayList<>();
        String json = JSON.toJSONString(entity.getResult());
        List<Map<String, String>> listObject = (List<Map<String, String>>) JSONArray.parse(json);
        listObject.sort((t1, t2) -> t2.get("time").compareTo(t1.get("time")));
        List<EquipmentSpecificIndex> indexes = equipmentSpecificIndexMapper.getEquipmentSpeIndexByIotCodeTrend(iotCode, isTrend, fieldKey);
        if (!ObjectUtils.isEmpty(indexes)) {
            Map<String, EquipmentSpecificIndex> collect = indexes.stream().collect(Collectors.toMap(EquipmentSpecificIndex::getNameKey, equipmentSpecificIndex -> equipmentSpecificIndex));
            for(Map<String, String> mapList : listObject){
                String dateStr = null;
                String deviceName = String.valueOf(mapList.get("deviceName"));
                try {
                    String value =  String.valueOf(mapList.get("time"));
                    String strDate = value.substring(0, 19);
                    SimpleDateFormat sdf = new SimpleDateFormat(ISO8601_DATE_HOUR_MIN_SEC);
                    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
                    Date date =sdf.parse(strDate);
                    dateStr = DateTimeUtil.format(date, DateTimeUtil.ISO_DATE_HOUR24_MIN_SEC);
                } catch (Exception e) {
                    log.error("日期转换失败");
                }
                for (Map.Entry entry : mapList.entrySet()){
                    if (!ObjectUtils.isEmpty(entry.getValue()) && !"null".equals(entry.getValue())) {
                        EquipmentSpecificIndex equipmentSpecificIndex = collect.get(entry.getKey());
                        if (!ObjectUtils.isEmpty(equipmentSpecificIndex)) {
                            IotIndexInfoVo iotIndexInfoVo = new IotIndexInfoVo();
                            iotIndexInfoVo.setType(equipmentSpecificIndex.getIndexName());
                            iotIndexInfoVo.setNumber(deviceName);
                            if (equipmentSpecificIndex.getIsTrend() == 1) {
                                iotIndexInfoVo.setContent(equipmentSpecificIndex.getIndexName() + entry.getValue() + equipmentSpecificIndex.getIndexUnitName());
                            } else {
                                iotIndexInfoVo.setContent(equipmentSpecificIndex.getEquipmentIndexName());
                            }

                            iotIndexInfoVo.setSendTime(dateStr);
                            infoVoList.add(iotIndexInfoVo);
                        }
                    }
                }
            }
        }
        return infoVoList;
    }

    /**
     * 在设备报废前30日 每日9点执行 系统推送提醒。设备报废后停止消息推送提醒。。
     *
     * @throws Exception
     */
    @Scheduled(cron = "${equipment.scrap.cron}")
    @Transactional(rollbackFor = Exception.class)
    public void equipmentScrap() throws Exception {
        List<Map<String, Object>> equipSpecificScrap = equipmentSpecificIndexMapper.getEquipSpecificScrap();
        equipSpecificScrap.forEach(e->{
            try {
                if(e.get("wesExpiry") != null) {
                    int year =  Integer.parseInt(e.get("wesExpiry").toString());
                    Date productDate = DateUtils.dateParse(e.get("product").toString(),"yyyy-MM-dd'T'HH:mm");
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(productDate);
                    calendar.add(Calendar.YEAR, year);

                    Date now = new Date();
                    String scrapTime = new SimpleDateFormat(DateUtils.DATE_TIME_PATTERN).format(calendar.getTime());

                    long time1 = calendar.getTimeInMillis();
                    calendar.setTime(now);
                    long time2 = calendar.getTimeInMillis();
                    long between_days=(time2-time1)/(10003600*24);
                    int day = Integer.parseInt(String.valueOf(between_days));

                    if(day < Integer.parseInt(equipmentScrapDay) && day > -1) {
                        syncSystemctlMsg(e, scrapTime, day);
                    }
                }

            } catch (ParseException parseException) {
                parseException.printStackTrace();
            }
        });

    }

    void syncSystemctlMsg(Map<String, Object> map,String scrapTime, int i) {
        try {
            MessageModel model = new MessageModel();
            model.setTitle("报废到期提醒");

            String equipName = map.get("name").toString();
            String location = map.get("sname").toString() + map.get("position").toString() ;

            String body = String.format("%s-%s于%s报废，请提前更换处理", equipName, location, scrapTime);
            String join = String.format("设备还剩%s天报废，请提前更换", i);
            model.setBody(body);
            model.setMsgType("scrapWarning");
            model.setSendTime(new Date());
            model.setIsSendApp(false);
            model.setTerminal("WEB");
            model.setIsSendWeb(true);
            model.setRelationId(map.get("id").toString());
            model.setCategory(1);
            List<String> receive = new ArrayList<>();
            receive.add("system");
            Map<String, String> ext = new HashMap<>();
            ext.put("content", join);
            ext.put("type", "报废到期");
            ext.put("name", map.get("name").toString());
            ext.put("time", new SimpleDateFormat(DateUtils.DATE_TIME_PATTERN).format(new Date()));
            model.setExtras(ext);
            model.setRecivers(receive);
            // Systemctl.messageClient.create(model);
            Token token = remoteSecurityService.getServerToken();
            systemctlFeign.create(token.getAppKey(), token.getProduct(), token.getToke(), model);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
