package com.ktg.iscs.service.impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ktg.common.core.redis.RedisCache;
import com.ktg.common.utils.SecurityUtils;
import com.ktg.common.utils.StringUtils;
import com.ktg.common.utils.bean.BeanUtils;
import com.ktg.iscs.domain.*;
import com.ktg.iscs.domain.dto.exUpdate.*;
import com.ktg.iscs.domain.dto.hardwareApi.*;
import com.ktg.iscs.domain.enums.*;
import com.ktg.iscs.domain.vo.hardwareApi.*;
import com.ktg.iscs.domain.vo.points.PointDetailVO;
import com.ktg.iscs.domain.vo.ticket.JobTicketDetailVO;
import com.ktg.iscs.domain.vo.ticket.JobTicketUpdateProgressReqVO;
import com.ktg.iscs.domain.vo.ticketPoints.IsJobTicketPointsVO;
import com.ktg.iscs.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.ktg.common.constant.Constants.SYS_ATTR;

/**
 * 硬件Service业务层处理
 *
 * @author cgj
 * @date 2024-10-16
 */
@Slf4j
@Service
public class HardwareApiServiceImpl implements HardwareApiService {
    @Autowired
    private IIsJobTicketService isJobTicketService;
    @Autowired
    private IIsKeyService isKeyService;
    @Autowired
    private IIsJobTicketKeyService iIsJobTicketKeyService;
    @Autowired
    private IIsLockService iIsLockService;
    @Autowired
    private IIsJobTicketLockService iIsJobTicketLockService;
    @Autowired
    private IIsIsolationPointService iIsIsolationPointService;
    @Autowired
    private IIsLocksetService iIsLocksetService;
    @Autowired
    private IIsJobTicketLocksetService iIsJobTicketLocksetService;
    @Autowired
    private IIsHardwareService isHardwareService;
    @Autowired
    private IIsJobTicketPointsService iIsJobTicketPointsService;
    @Autowired
    private IIsJobTicketUserService iIsJobTicketUserService;
    @Autowired
    private IIsJobCardService iIsJobCardService;
    @Autowired
    private IIsSystemAttributeService isSystemAttributeService;
    @Autowired
    private IIsRfidTokenService iIsRfidTokenService;
    @Autowired
    private IIsLockCabinetSlotsService iIsLockCabinetSlotsService;
    @Autowired
    private IIsTicketOperLogService isTicketOperLogService;
    @Autowired
    private IIsJobTicketStepService iIsJobTicketStepService;
    @Autowired
    private RedisCache redisCache;
    // @Value("${ktg-mes.jtcolocker}")
    // private String jtcolocker;


    /**
     * 取出钥匙
     *
     * @param dto
     * @return
     */
    @Override
    public Boolean updateTakeOutKey(TakeOutKeyDTO dto) {
        Assert.notNull(dto.getTicketId(), "请告诉我关于哪个作业票!");
        Assert.notBlank(dto.getKeyNfc(), "请告诉我钥匙的NFC!");
        Assert.notBlank(dto.getSerialNumber(), "请告知归还到哪里!");
        // 1.获取作业票数据
        IsJobTicket jobTicket = isJobTicketService.getById(dto.getTicketId());
        Assert.notNull(jobTicket, "作业票数据丢失啦!");
        // 1.1获取上锁时取出的锁的信息
        IsKey startKey = isKeyService.getOne(Wrappers.<IsKey>lambdaQuery().eq(IsKey::getKeyNfc, dto.getKeyNfc()));
        Assert.notNull(startKey, "钥匙数据丢失啦!");
        // 1.2通过序列号查询柜子信息
        IsHardware isHardware = isHardwareService.getOne(Wrappers.<IsHardware>lambdaQuery()
                .eq(IsHardware::getSerialNumber, dto.getSerialNumber()));
        Assert.notNull(isHardware, "该序列号无对应的硬件信息!");
        // 1.3初始化时间参数
        Date date = new Date();
        // 1.4获取上锁时的数据
        IsJobTicketKey jobTicketKey = iIsJobTicketKeyService.getOne(Wrappers.<IsJobTicketKey>lambdaUpdate()
                .eq(IsJobTicketKey::getTicketId, dto.getTicketId())
                .ne(IsJobTicketKey::getKeyStatus, "2")
                .eq(IsJobTicketKey::getTicketType, "0"));
        // 2.根据作业票判断到了哪一阶段了，如果未归还的上锁数据不为空并且上锁数据中这两个数据有空的，那肯定是上锁阶段还没有完成
        if (jobTicketKey!=null && (jobTicketKey.getCollectTime() == null || jobTicketKey.getGiveBackTime() == null)) {
            // 3.上锁阶段取钥匙
            iIsJobTicketKeyService.update(Wrappers.<IsJobTicketKey>lambdaUpdate()
                    /*.eq(IsJobTicketKey::getTicketId, dto.getTicketId())
                    .eq(IsJobTicketKey::getTicketType, "0")*/
                    .eq(IsJobTicketKey::getRecordId, jobTicketKey.getRecordId())
                    .set(IsJobTicketKey::getKeyId, startKey.getKeyId())
                    .set(IsJobTicketKey::getFromHardwareId, isHardware.getId())
                    .set(IsJobTicketKey::getCollectTime, date)
                    .set(IsJobTicketKey::getKeyStatus, KeyStatusEnum.TAKED.status));
            // 上锁阶段需要变更状态
            JobTicketUpdateProgressReqVO reqVO = new JobTicketUpdateProgressReqVO();
            reqVO.userId = SecurityUtils.getUserId();
            reqVO.ticketId = dto.getTicketId();
            reqVO.equipStatus = 3;
            isJobTicketService.updateTicketProgress(reqVO);
        } else {
            IsJobTicketKey jobTicketKey1 = iIsJobTicketKeyService.getOne(Wrappers.<IsJobTicketKey>lambdaUpdate()
                    .eq(IsJobTicketKey::getTicketId, dto.getTicketId())
                    .ne(IsJobTicketKey::getKeyStatus, "2")
                    .eq(IsJobTicketKey::getTicketType, "1"));
            // 3.1解锁阶段取钥匙
            iIsJobTicketKeyService.update(Wrappers.<IsJobTicketKey>lambdaUpdate()
                    /*.eq(IsJobTicketKey::getTicketId, dto.getTicketId())
                    .eq(IsJobTicketKey::getTicketType, "1")*/
                    .eq(IsJobTicketKey::getRecordId, jobTicketKey1.getRecordId())
                    .set(IsJobTicketKey::getKeyId, startKey.getKeyId())
                    .set(IsJobTicketKey::getFromHardwareId, isHardware.getId())
                    .set(IsJobTicketKey::getCollectTime, date)
                    .set(IsJobTicketKey::getKeyStatus, KeyStatusEnum.TAKED.status));
        }
        return true;
    }

    /**
     * 上锁阶段，取钥匙时更新状态
     *
     * @param ticketId
     */
    private void updateFirstProgress(Long ticketId) {
        // 判断作业票的整体状态，防止状态回退异常
        IsJobTicketUser jobTicketUser = iIsJobTicketUserService.getOne(Wrappers.<IsJobTicketUser>lambdaQuery()
                .eq(IsJobTicketUser::getTicketId, ticketId)
                .eq(IsJobTicketUser::getUserRole, isSystemAttributeService.getIsSystemAttributeByKey("role.jtlocker").getSysAttrValue()));
        Assert.isFalse(Integer.parseInt(jobTicketUser.getJobStatus()) > JobStatusEnum.ACQUIRE_KEY.status, "作业票已完成设备拿取，无法操作！");
        IsJobTicket isJobTicket = isJobTicketService.getOne(Wrappers.<IsJobTicket>lambdaQuery()
                .eq(IsJobTicket::getTicketId, ticketId));
        Assert.isFalse(Integer.parseInt(isJobTicket.getTicketStatus()) > Integer.parseInt(TicketStatusEnum.READY_TO_LOCK.status), "作业票已完成设备拿取，无法进行操作！");
        // 上锁阶段取钥匙，更新is_job_ticket_user和is_job_ticket
        // 1.新更人员状态
        iIsJobTicketUserService.update(Wrappers.<IsJobTicketUser>lambdaUpdate()
                .eq(IsJobTicketUser::getTicketId, ticketId)
                .eq(IsJobTicketUser::getUserRole, isSystemAttributeService.getIsSystemAttributeByKey("role.jtlocker").getSysAttrValue())
                .set(IsJobTicketUser::getJobStatus, JobStatusEnum.ACQUIRE_KEY.status));
        // 2.获取设备取出状态
        boolean b = checkTakeStatus(ticketId);
        // 3.根据设备去除状态更新is_job_ticket
        if (b) {
            isJobTicketService.update(Wrappers.<IsJobTicket>lambdaUpdate()
                    .eq(IsJobTicket::getTicketId, ticketId)
                    .set(IsJobTicket::getTicketStatus, TicketStatusEnum.READY_TO_LOCK.status));
        }
    }

    /**
     * 检查上锁前的设备是否全部取出完毕
     *
     * @param ticketId
     * @return
     */
    private boolean checkTakeStatus(Long ticketId) {
        // 1.检查钥匙是否取出
        int keyCount = (int) iIsJobTicketKeyService.count(Wrappers.<IsJobTicketKey>lambdaQuery()
                .eq(IsJobTicketKey::getTicketId, ticketId)
                .eq(IsJobTicketKey::getKeyStatus, KeyStatusEnum.WAIT_TAKE.status)
                .eq(IsJobTicketKey::getTicketType, 0));
        // 2.检查挂锁是否全部取出
        int lockCount = (int) iIsJobTicketLockService.count(Wrappers.<IsJobTicketLock>lambdaQuery()
                .eq(IsJobTicketLock::getTicketId, ticketId)
                .eq(IsJobTicketLock::getLockStatus, LockStatusEnum.WAIT_TAKE.status));
        // 3.检查辅件是否全部取出
        int locksetCount = (int) iIsJobTicketLocksetService.count(Wrappers.<IsJobTicketLockset>lambdaQuery()
                .eq(IsJobTicketLockset::getJobTicketId, ticketId)
                .eq(IsJobTicketLockset::getLocksetStatus, LocksetStatusEnum.WAIT_TAKE.status));
        if (keyCount == 0 && lockCount == 0 && locksetCount == 0) {
            return true;
        }
        return false;
    }

    /**
     * 归还钥匙
     *
     * @param dto
     * @return
     */
    @Transactional
    @Override
    public Boolean updateReturnKey(ReturnKeyDTO dto) {
        Assert.notNull(dto.getTicketId(), "请告诉我关于哪个作业票!");
        Assert.notBlank(dto.getKeyNfc(), "请告诉我钥匙的NFC!");
        Assert.notBlank(dto.getSerialNumber(), "请告知归还到哪里!");
        // 1.获取作业票数据
        IsJobTicket jobTicket = isJobTicketService.getById(dto.getTicketId());
        Assert.notNull(jobTicket, "作业票数据丢失啦!");
        // 1.1获取上锁时取出的锁的信息
        IsKey startKey = isKeyService.getOne(Wrappers.<IsKey>lambdaQuery().eq(IsKey::getKeyNfc, dto.getKeyNfc()));
        Assert.notNull(startKey, "钥匙数据丢失啦!");
        // 1.2通过序列号查询柜子信息
        IsHardware isHardware = isHardwareService.getOne(Wrappers.<IsHardware>lambdaQuery()
                .eq(IsHardware::getSerialNumber, dto.getSerialNumber()));
        Assert.notNull(isHardware, "该序列号无对应的硬件信息!");
        // 1.3初始化时间参数
        Date date = new Date();
        // 1.4获取上锁时的数据
        IsJobTicketKey jobTicketKey = iIsJobTicketKeyService.getOne(Wrappers.<IsJobTicketKey>lambdaUpdate()
                .eq(IsJobTicketKey::getTicketId, dto.getTicketId())
                .ne(IsJobTicketKey::getKeyStatus, "2")
                .eq(IsJobTicketKey::getTicketType, "0"));
        // 2.根据作业票判断到了哪一阶段了，如果未归还的上锁数据不为空并且上锁数据中这两个数据有空的，那肯定是上锁阶段还没有完成
        if (jobTicketKey!=null && (jobTicketKey.getCollectTime() == null || jobTicketKey.getGiveBackTime() == null)) {
            // 3.1上锁阶段还钥匙
            iIsJobTicketKeyService.update(Wrappers.<IsJobTicketKey>lambdaUpdate()
                    /*.eq(IsJobTicketKey::getTicketId, dto.getTicketId())
                    .eq(IsJobTicketKey::getTicketType, "0")*/
                    .eq(IsJobTicketKey::getRecordId, jobTicketKey.getRecordId())
                    .set(IsJobTicketKey::getKeyId, startKey.getKeyId())
                    .set(IsJobTicketKey::getToHardwareId, isHardware.getId())
                    .set(IsJobTicketKey::getGiveBackTime, date)
                    .set(IsJobTicketKey::getKeyStatus, KeyStatusEnum.RETURNED.status));
            // 3.1.1还完钥匙判断点位是不是都上锁完成，如果都上锁完成，则更新作业进度
            List<IsJobTicketPoints> pointsLock = iIsJobTicketPointsService.list(Wrappers.<IsJobTicketPoints>lambdaQuery()
                    .eq(IsJobTicketPoints::getTicketId, dto.getTicketId())
                    .eq(IsJobTicketPoints::getPointStatus, "0"));
            if (pointsLock.isEmpty()) {
                isJobTicketService.update(Wrappers.<IsJobTicket>lambdaUpdate()
                        .eq(IsJobTicket::getTicketId, dto.getTicketId())
                        .set(IsJobTicket::getTicketStatus, "3"));
            } else {
                // 3.1.2如果没上完，允许再次获取一个新钥匙去上锁，所以要在生成一个取钥匙的初始化数据
                IsJobTicketKey isJobTicketKey = new IsJobTicketKey();
                isJobTicketKey.setTicketId(dto.getTicketId());
                isJobTicketKey.setKeyStatus("0");
                isJobTicketKey.setTicketType(0);
                iIsJobTicketKeyService.save(isJobTicketKey);
            }
        } else {
            IsJobTicketKey jobTicketKey1 = iIsJobTicketKeyService.getOne(Wrappers.<IsJobTicketKey>lambdaUpdate()
                    .eq(IsJobTicketKey::getTicketId, dto.getTicketId())
                    .ne(IsJobTicketKey::getKeyStatus, "2")
                    .eq(IsJobTicketKey::getTicketType, "1"));
            // 3.2解锁阶段还钥匙
            iIsJobTicketKeyService.update(Wrappers.<IsJobTicketKey>lambdaUpdate()
                    /*.eq(IsJobTicketKey::getTicketId, dto.getTicketId())
                    .eq(IsJobTicketKey::getTicketType, "1")*/
                    .eq(IsJobTicketKey::getRecordId, jobTicketKey1.getRecordId())
                    .set(IsJobTicketKey::getKeyId, startKey.getKeyId())
                    .set(IsJobTicketKey::getToHardwareId, isHardware.getId())
                    .set(IsJobTicketKey::getGiveBackTime, date)
                    .set(IsJobTicketKey::getKeyStatus, KeyStatusEnum.RETURNED.status));
            // 3.2.1还完钥匙判断点位是不是都解锁完成，如果都解锁完成，则更新作业进度
            List<IsJobTicketPoints> pointsLock = iIsJobTicketPointsService.list(Wrappers.<IsJobTicketPoints>lambdaQuery()
                    .eq(IsJobTicketPoints::getTicketId, dto.getTicketId())
                    .eq(IsJobTicketPoints::getPointStatus, "2"));
            if (pointsLock.isEmpty()) {
                isJobTicketService.update(Wrappers.<IsJobTicket>lambdaUpdate()
                        .eq(IsJobTicket::getTicketId, dto.getTicketId())
                        .set(IsJobTicket::getTicketStatus, "4"));
            } else {
                // 3.1.2如果没解完，允许再次获取一个新钥匙去解锁，所以要在生成一个解锁时取钥匙的初始化数据
                IsJobTicketKey isJobTicketKey = new IsJobTicketKey();
                isJobTicketKey.setTicketId(dto.getTicketId());
                isJobTicketKey.setKeyStatus("0");
                isJobTicketKey.setTicketType(1);
                iIsJobTicketKeyService.save(isJobTicketKey);
            }
        }
        /*JobTicketUpdateProgressReqVO reqVO = new JobTicketUpdateProgressReqVO();
        reqVO.userId = SecurityUtils.getUserId();
        reqVO.ticketId = dto.getTicketId();
        reqVO.equipStatus = 3;
        isJobTicketService.updateTicketProgress(reqVO);*/

        return true;
    }

    /**
     * 取出挂锁时更新数据
     *
     * @param list
     * @return
     */
    @Override
    public synchronized Boolean updateTicketLockTake(List<TakeTicketLockDTO> list) {
        Assert.isFalse(list.isEmpty(), "请取出至少一把挂锁!");
        // 情况复杂，遍历处理吧
        for (TakeTicketLockDTO dto : list) {
            Assert.notBlank(dto.getLockNfc(), "挂锁nfc缺失!");
            Assert.notNull(dto.getTicketId(), "请告诉我关于哪个作业票!");
            Assert.notBlank(dto.getSerialNumber(), "请告知归还到哪一个柜子!");
            // 1.查询挂锁信息
            IsLock lock = iIsLockService.getOne(Wrappers.<IsLock>lambdaQuery()
                    .eq(IsLock::getLockNfc, dto.getLockNfc()));
            Assert.notNull(lock, "该nfc无对应的挂锁信息!");
            // 1.1检查这把锁是不是已经在该作业票中使用
            List<IsJobTicketLock> jobTicketLockList = iIsJobTicketLockService.list(Wrappers.<IsJobTicketLock>lambdaQuery()
                    .eq(IsJobTicketLock::getTicketId, dto.getTicketId())
                    .eq(IsJobTicketLock::getLockId, lock.getLockId()));
            Assert.isFalse(!jobTicketLockList.isEmpty(), lock.getLockName() + "已被取出!");
            // 1.2通过序列号查询柜子信息
            IsHardware isHardware = isHardwareService.getOne(Wrappers.<IsHardware>lambdaQuery()
                    .eq(IsHardware::getSerialNumber, dto.getSerialNumber()));
            Assert.notNull(isHardware, "该序列号无对应的硬件信息!");
            // 2.获取本次作业票产生的和挂锁关联的数据,按照从上到下的顺序，取一个可以使用的
            IsJobTicketLock isJobTicketLock = iIsJobTicketLockService.getOne(Wrappers.<IsJobTicketLock>lambdaQuery()
                    .eq(IsJobTicketLock::getTicketId, dto.getTicketId())
                    .isNull(IsJobTicketLock::getLockId)
                    .orderByAsc(IsJobTicketLock::getRecordId)
                    .last("offset 0 rows fetch next 1 rows only"));
            Assert.notNull(isJobTicketLock, "无初始化数据来提供给该挂锁更新");
            // 1.2开始补充该条数据
            isJobTicketLock.setLockId(lock.getLockId());
            isJobTicketLock.setFromHardwareId(isHardware.getId());
            isJobTicketLock.setLockStatus(LockStatusEnum.NOT_LOCK.status);
            iIsJobTicketLockService.updateById(isJobTicketLock);
        }

        List<IsJobTicketLock> lockList = iIsJobTicketLockService.selectByTicketId(list.get(0).getTicketId());
        // 已取锁数量
        int takeCount = (int) lockList.stream().filter(data -> data.getLockId() != null).count();
        int status = takeCount == lockList.size() ? 2 : 1;

        JobTicketUpdateProgressReqVO reqVO = new JobTicketUpdateProgressReqVO();
        reqVO.ticketId = list.get(0).getTicketId();
        reqVO.userId = SecurityUtils.getUserId();
        reqVO.equipStatus = status;
        isJobTicketService.updateTicketProgress(reqVO);


        /*int size = list.size();
        List<String> nfcList = list.stream().map(TakeTicketLockDTO::getLockNfc).collect(Collectors.toList());
        Assert.isFalse(nfcList.isEmpty() || size != nfcList.size(), "钥匙NFC不可为空!");
        // 1.查询挂锁信息
        List<IsLock> lockList = iIsLockService.list(Wrappers.<IsLock>lambdaQuery()
                .in(IsLock::getLockNfc, nfcList));
        Assert.isFalse(lockList.isEmpty(), "通过nfc查询不到相关挂锁信息!");
        // 2.获取本次作业票产生的和挂锁关联的数据,因为取挂锁可能分批，多以按顺序更新关联数据的前几个
        List<IsJobTicketLock> jobTicketLockList = iIsJobTicketLockService.list(Wrappers.<IsJobTicketLock>lambdaQuery()
                .eq(IsJobTicketLock::getTicketId, list.get(0).getTicketId())
                .isNull(IsJobTicketLock::getLockId)
                .orderByAsc(IsJobTicketLock::getRecordId)
                .last("limit" + size));
        // 3.把查出来的锁id放到对应的dto中,组装查出来的IsJobTicketLock数据
        for (int i = 0; i < list.size(); i++) {
            for (IsLock isLock : lockList) {
                if (list.get(i).getLockNfc().equals(isLock.getLockNfc())) {
                    list.get(i).setLockId(isLock.getLockId());
                }
            }
            // 3.1组装更新的数据
            IsJobTicketLock isJobTicketLock = jobTicketLockList.get(i);
            isJobTicketLock.setLockId(list.get(i).getLockId());
            isJobTicketLock.setFromHardwareId(list.get(i).getFromHardwareId());
            isJobTicketLock.setLockStatus(LockStatusEnum.NOT_LOCK.status);
        }
        // 4.开始批量更新
        iIsJobTicketLockService.updateBatchById(jobTicketLockList);*/
        return true;
    }

    /**
     * 归还挂锁时更新数据
     *
     * @param dto
     * @return
     */
    @Override
    public Boolean updateTicketLockReturn(ReturnTicketLockDTO dto) {
        // Assert.notNull(dto.getTicketId(), "请告诉我关于哪个作业票!");
        Assert.notBlank(dto.getLockNfc(), "挂锁nfc缺失!");
        Assert.notBlank(dto.getSerialNumber(), "请告知归还到哪一个柜子!");
        // 1.通过nfc查询挂锁信息
        IsLock lock = iIsLockService.getOne(Wrappers.<IsLock>lambdaQuery()
                .eq(IsLock::getLockNfc, dto.getLockNfc()));
        Assert.notNull(lock, "该nfc无对应的挂锁信息!");
        // 1.1通过序列号查询柜子信息
        IsHardware isHardware = isHardwareService.getOne(Wrappers.<IsHardware>lambdaQuery().eq(IsHardware::getSerialNumber, dto.getSerialNumber()));
        Assert.notNull(isHardware, "该序列号无对应的硬件信息!");
        // 2.开始更新归还信息
        if (dto.getTicketId() != null) {
            // 2.1登陆后归还， 判断钥匙在哪个阶段，根据不同阶段更新不一样
            Integer lockStateByNfc = getLockStateByNfc(dto.getLockNfc(), dto.getTicketId());
            if (lockStateByNfc.equals(0) || lockStateByNfc.equals(2)) {
                // 0-上锁未取钥匙(可锁-需更改还锁逻辑)
                iIsJobTicketLockService.update(Wrappers.<IsJobTicketLock>lambdaUpdate()
                        .eq(IsJobTicketLock::getTicketId, dto.getTicketId())
                        .eq(IsJobTicketLock::getLockId, lock.getLockId())
                        .set(IsJobTicketLock::getLockId, null)
                        .set(IsJobTicketLock::getFromHardwareId, null)
                        .set(IsJobTicketLock::getLockStatus, LockStatusEnum.WAIT_TAKE.status));
            } else if (lockStateByNfc.equals(1)) {
                // 1-上锁取了钥匙(不可锁)
                return true;
            } else {
                iIsJobTicketLockService.update(Wrappers.<IsJobTicketLock>lambdaUpdate()
                        .eq(IsJobTicketLock::getTicketId, dto.getTicketId())
                        .eq(IsJobTicketLock::getLockId, lock.getLockId())
                        .set(IsJobTicketLock::getToHardwareId, isHardware.getId())
                        .set(IsJobTicketLock::getLockStatus, LockStatusEnum.RETURN_LOCK.status));
            }
        } else {
            // 2.2不登陆状态下归还
            // 查一下哪个作业票用了这个挂锁，而且还没有完成
            /*List<IsJobTicketLock> jobTicketLockList = iIsJobTicketLockService.list(Wrappers.<IsJobTicketLock>lambdaQuery()
                    .eq(IsJobTicketLock::getLockId, lock.getLockId())
                    .ne(IsJobTicketLock::getLockStatus, LockStatusEnum.RETURN_LOCK.status));*/
            /*List<IsJobTicketLock> jobTicketLockList = iIsJobTicketLockService.list(new MPJLambdaWrapperX<IsJobTicketLock>()
                    .eq(IsJobTicketLock::getLockId, lock.getLockId())
                    .ne(IsJobTicketLock::getLockStatus, LockStatusEnum.RETURN_LOCK.status)
                    .leftJoin(IsJobTicket.class, IsJobTicket::getTicketId, IsJobTicketLock::getTicketId)
                    .ne(IsJobTicket::getTicketStatus, "5")
                    .ne(IsJobTicket::getTicketStatus, "6"));*/
            List<IsJobTicketLock> jobTicketLockList = iIsJobTicketLockService.getLockJob(lock.getLockId());
            if (jobTicketLockList.isEmpty()) {
                log.error("当前挂锁未找到关联的作业票, nfc: {}, name : {}", dto.getLockNfc(), lock.getLockName());
                return null;
            } else if (jobTicketLockList.size() == 1) {
                // 2.1登陆后归还， 判断钥匙在哪个阶段，根据不同阶段更新不一样
                Integer lockStateByNfc = getLockStateByNfc(dto.getLockNfc(), jobTicketLockList.get(0).getTicketId());
                if (lockStateByNfc.equals(0) || lockStateByNfc.equals(2)) {
                    // 0-上锁未取钥匙(可锁-需更改还锁逻辑)
                    iIsJobTicketLockService.update(Wrappers.<IsJobTicketLock>lambdaUpdate()
                            .eq(IsJobTicketLock::getTicketId, jobTicketLockList.get(0).getTicketId())
                            .eq(IsJobTicketLock::getLockId, lock.getLockId())
                            .set(IsJobTicketLock::getLockId, null)
                            .set(IsJobTicketLock::getFromHardwareId, null)
                            .set(IsJobTicketLock::getLockStatus, LockStatusEnum.WAIT_TAKE.status));
                } else if (lockStateByNfc.equals(1)) {
                    // 1-上锁取了钥匙(不可锁)
                    return true;
                } else {
                    // 说明找到的就是
                    iIsJobTicketLockService.update(Wrappers.<IsJobTicketLock>lambdaUpdate()
                            .eq(IsJobTicketLock::getLockId, lock.getLockId())
                            .set(IsJobTicketLock::getToHardwareId, isHardware.getId())
                            .set(IsJobTicketLock::getLockStatus, LockStatusEnum.RETURN_LOCK.status));
                }
            } else {
                // 出现了多条对应
                log.error("当前挂锁找到多条关联的作业票, nfc: {}, name : {}", dto.getLockNfc(), lock.getLockName());
            }
            JobTicketUpdateProgressReqVO reqVO = new JobTicketUpdateProgressReqVO();
            reqVO.userId = SecurityUtils.getUserId();
            reqVO.ticketId = jobTicketLockList.get(0).getTicketId();
            reqVO.equipStatus = 3;
            isJobTicketService.updateTicketProgress(reqVO);
        }

        return true;
    }


    /**
     * 批量更新作业票下隔离点的上锁状况
     *
     * @param list
     * @return
     */
    @Transactional
    @Override
    public Boolean updateLockPointBatch(List<LockPointBatchDTO> list) {
        Assert.isFalse(list.isEmpty(), "没有接收到数据啊!");
        // 情况复杂，循环处理
        for (LockPointBatchDTO dto : list) {
            Assert.notNull(dto.getTicketId(), "请告诉我关于哪个作业票!");
            // 1.获取作业票数据
            IsJobTicket jobTicket = isJobTicketService.getById(dto.getTicketId());
            Assert.notNull(jobTicket, "作业票数据丢失啦!");
            Assert.notBlank(dto.getLockNfc(), "挂锁nfc缺失!");
            Assert.notBlank(dto.getPointNfc(), "请告知隔离点信息!");
            Assert.notNull(dto.getTarget(), "请告我是去挂锁还是解锁!");
            Assert.notNull(dto.getStatus(), "请告我任务当前状态!");
            Assert.notBlank(dto.getKeyNfc(), "钥匙信息不可为空!");
            // 1.通过nfc查询挂锁信息
            IsLock lock = iIsLockService.getOne(Wrappers.<IsLock>lambdaQuery()
                    .eq(IsLock::getLockNfc, dto.getLockNfc()));
            Assert.notNull(lock, "该nfc无对应的挂锁信息");
            // 1.1通过nfc查询钥匙信息
            IsKey key = isKeyService.getOne(Wrappers.<IsKey>lambdaQuery()
                    .eq(IsKey::getKeyNfc, dto.getKeyNfc()));
            Assert.notNull(lock, "该nfc无对应的钥匙信息");
            // 2.通过nfc查询隔离点信息
            IsIsolationPoint point = iIsIsolationPointService.getOneByNfc(dto.getPointNfc());
            Assert.notNull(point, "该nfc无对应的隔离点信息");
            Date date = new Date();
            if (dto.getTarget().equals(0)) {
                log.info("--------------开始上锁-----------");
                // 重复点位模式检查
                checkBeforeLockKeyBack(isSystemAttributeService.getIsSystemAttributeByKey("sys.job.lock_type").getSysAttrValue(), point, lock);
                // 2.1更新隔离点上锁信息
                iIsJobTicketPointsService.update(Wrappers.<IsJobTicketPoints>lambdaUpdate()
                        .eq(IsJobTicketPoints::getTicketId, dto.getTicketId())
                        .eq(IsJobTicketPoints::getPointId, point.getPointId())
                        .set(IsJobTicketPoints::getLockId, lock.getLockId())
                        .set(IsJobTicketPoints::getLockedByKeyId, key.getKeyId())
                        .set(IsJobTicketPoints::getLockTime, date)
                        .set(IsJobTicketPoints::getPointStatus, PointStatusEnum.LOCKED.status));
                // 3.开始更新上锁时挂锁信息
                iIsJobTicketLockService.update(Wrappers.<IsJobTicketLock>lambdaUpdate()
                        .eq(IsJobTicketLock::getTicketId, dto.getTicketId())
                        .eq(IsJobTicketLock::getLockId, lock.getLockId())
                        .set(IsJobTicketLock::getIsolationPointId, point.getPointId())
                        .set(IsJobTicketLock::getLockStatus, LockStatusEnum.LOCKED.status));
                // 4.如果隔离点上锁完毕，则更新作业负责人的任务状态
                int count = (int) iIsJobTicketPointsService.count(Wrappers.<IsJobTicketPoints>lambdaQuery()
                        .eq(IsJobTicketPoints::getTicketId, dto.getTicketId())
                        .eq(IsJobTicketPoints::getPointStatus, "0"));
                if (count == 0) {
                    iIsJobTicketUserService.update(Wrappers.<IsJobTicketUser>lambdaUpdate()
                            .eq(IsJobTicketUser::getUserRole, isSystemAttributeService.getIsSystemAttributeByKey("role.jtlocker").getSysAttrValue())
                            .eq(IsJobTicketUser::getTicketId, dto.getTicketId())
                            .set(IsJobTicketUser::getJobStatus, "4"));
                }
            } else {
                log.info("--------------开始解锁-----------");
                // 2.1.1更新隔离点解锁信息
                iIsJobTicketPointsService.update(Wrappers.<IsJobTicketPoints>lambdaUpdate()
                        .eq(IsJobTicketPoints::getTicketId, dto.getTicketId())
                        .eq(IsJobTicketPoints::getPointId, point.getPointId())
                        .set(IsJobTicketPoints::getUnlockedByKeyId, key.getKeyId())
                        .set(IsJobTicketPoints::getUnlockTime, date)
                        .set(IsJobTicketPoints::getPointStatus, PointStatusEnum.REMOVE_LOCK.status));
                // 3.1开始更新解锁时挂锁信息
                iIsJobTicketLockService.update(Wrappers.<IsJobTicketLock>lambdaUpdate()
                        .eq(IsJobTicketLock::getTicketId, dto.getTicketId())
                        .eq(IsJobTicketLock::getLockId, lock.getLockId())
                        .set(IsJobTicketLock::getLockStatus, LockStatusEnum.REMOVED_LOCK.status));
                // 4.1如果都解锁了，则更新作业负责人的任务状态
                int count = (int) iIsJobTicketPointsService.count(Wrappers.<IsJobTicketPoints>lambdaQuery()
                        .eq(IsJobTicketPoints::getTicketId, dto.getTicketId())
                        .ne(IsJobTicketPoints::getPointStatus, "2"));
                if (count == 0) {
                    iIsJobTicketUserService.update(Wrappers.<IsJobTicketUser>lambdaUpdate()
                            .eq(IsJobTicketUser::getUserRole, isSystemAttributeService.getIsSystemAttributeByKey("role.jtlocker").getSysAttrValue())
                            .eq(IsJobTicketUser::getTicketId, dto.getTicketId())
                            .set(IsJobTicketUser::getJobStatus, "5"));
                }
                // 4.2开始更新因为重合点位，当时没有解锁的点位的数据
                // updateConflictPoints(point.getPointId(), key.getKeyId(), date, lock.getLockId());
            }
        }
        /*JobTicketUpdateProgressReqVO reqVO = new JobTicketUpdateProgressReqVO();
        reqVO.userId = SecurityUtils.getUserId();
        reqVO.ticketId = list.get(0).getTicketId();
        reqVO.equipStatus = 3;
        isJobTicketService.updateTicketProgress(reqVO);*/
        // 4.更新下作业票的状态，如果是上锁时的操作
        if (list.get(0).getTarget() != null && list.get(0).getTarget().equals(0)) {
            isJobTicketService.update(Wrappers.<IsJobTicket>lambdaUpdate()
                    .eq(IsJobTicket::getTicketId, list.get(0).getTicketId())
                    .set(IsJobTicket::getTicketStatus, "2"));
        }
        // 完成上锁
        // 完成解锁
        lockLog(list);
        return true;
    }

    private void lockLog(List<LockPointBatchDTO> list) {
        // 上锁日志
        List<LockPointBatchDTO> lockList = list.stream().filter(o -> o.getTarget().equals(0)).collect(Collectors.toList());
        if (!lockList.isEmpty()) {
            IsJobTicket byId = isJobTicketService.getById(lockList.get(0).getTicketId());
            if (byId != null) {
                List<String> nfcList = lockList.stream().map(LockPointBatchDTO::getPointNfc).collect(Collectors.toList());
                List<IsRfidToken> list2 = iIsRfidTokenService.list(Wrappers.<IsRfidToken>lambdaQuery()
                        .in(IsRfidToken::getRfid, nfcList));
                List<Long> collect = list2.stream().map(IsRfidToken::getRfidId).collect(Collectors.toList());
                List<IsIsolationPoint> list1 = iIsIsolationPointService.list(Wrappers.<IsIsolationPoint>lambdaQuery()
                        .in(IsIsolationPoint::getRfidId, collect));
                // String pointNames = list1.stream().map(IsIsolationPoint::getPointName).collect(Collectors.joining(","));
                StringBuilder pointNames = new StringBuilder();
                for (IsIsolationPoint isIsolationPoint : list1) {
                    pointNames.append("<").append(isIsolationPoint.getPointIcon()).append(">").append("[").append(isIsolationPoint.getPointName()).append("] ");
                }
                // 完成上锁
                isTicketOperLogService.addLog5(byId.getTicketId(), byId.getTicketName(), pointNames.toString());
            }
        }
        List<LockPointBatchDTO> unlockList = list.stream().filter(o -> o.getTarget().equals(1)).collect(Collectors.toList());
        if (!unlockList.isEmpty()) {
            IsJobTicket byId = isJobTicketService.getById(unlockList.get(0).getTicketId());
            if (byId != null) {
                List<String> nfcList = unlockList.stream().map(LockPointBatchDTO::getPointNfc).collect(Collectors.toList());
                List<IsRfidToken> list2 = iIsRfidTokenService.list(Wrappers.<IsRfidToken>lambdaQuery()
                        .in(IsRfidToken::getRfid, nfcList));
                List<Long> collect = list2.stream().map(IsRfidToken::getRfidId).collect(Collectors.toList());
                List<IsIsolationPoint> list1 = iIsIsolationPointService.list(Wrappers.<IsIsolationPoint>lambdaQuery()
                        .in(IsIsolationPoint::getRfidId, collect));
                // String pointNames = list1.stream().map(IsIsolationPoint::getPointName).collect(Collectors.joining(","));
                StringBuilder pointNames = new StringBuilder();
                for (IsIsolationPoint isIsolationPoint : list1) {
                    pointNames.append("<").append(isIsolationPoint.getPointIcon()).append(">").append("[").append(isIsolationPoint.getPointName()).append("] ");
                }
                // 完成解锁
                isTicketOperLogService.addLog9(byId.getTicketId(), byId.getTicketName(), String.valueOf(pointNames));
            }
        }
    }

    /**
     * 需要增加上锁还钥匙的时候锁的验证
     * 1）、强制共享锁，交叉点位的锁rfid还钥匙时必须相同
     * 2）、强制多锁，交叉点位的锁rfid还钥匙时必须不同
     * 3）、非强制共享锁，交叉点位的锁rfid还钥匙时可相同
     * <p>
     * 上锁后还钥匙
     */
    private void checkBeforeLockKeyBack(String type, IsIsolationPoint point, IsLock lock) {
        if (type.equals("1")) {
            // 强制共享锁，交叉点位的锁rfid还钥匙时必须相同，即重复点位锁信息需与已上的锁的信息校验
            // 开始查询已经上锁的点位信息
            IsJobTicketPoints lockingData = iIsJobTicketPointsService.getLockingData(point.getPointId());
            if (lockingData != null) {
                Assert.isTrue(lock.getLockId().equals(lockingData.getLockId()),
                        "点位挂锁错误！点位[" + point.getPointName() + "]当前正在被" + iIsLockService.getById(lockingData.getLockId()).getLockNfc() + "挂锁锁定！");
            }
        }
        if (type.equals("2")) {
            // 强制多锁，交叉点位的锁rfid还钥匙时必须不同
            // 开始查询已经上锁的点位信息
            IsJobTicketPoints lockingData = iIsJobTicketPointsService.getLockingData(point.getPointId());
            if (lockingData != null) {
                Assert.isFalse(lock.getLockId().equals(lockingData.getLockId()), "点位挂锁错误，重复点位[" + point.getPointName() + "]请多锁完成重复点位上锁！");
            }
        }
    }


    /**
     * 解锁时，解除因为点位冲突而没有被解除的点位数据
     */
    public void updateConflictPoints(Long pointId, Long unlockedByKeyId, Date date, Long lockId) {
        // 查询当前点位是否有取了钥匙去解锁的作业票，如果有则更新
        List<IsJobTicketPoints> notFinishConflictJob = iIsJobTicketPointsService.getNotFinishConflictJob(pointId, lockId);
        // 查询当前点位是否有已经完成的作业票，但是该点位没有解锁的
        List<IsJobTicketPoints> finishConflictJob = iIsJobTicketPointsService.getFinishConflictJob(pointId, lockId);
        finishConflictJob.addAll(notFinishConflictJob);
        HashSet<IsJobTicketPoints> isJobTicketPoints1 = new HashSet<>(finishConflictJob);
        // 查询都是去解锁的
        if (!finishConflictJob.isEmpty()) {
            for (IsJobTicketPoints isJobTicketPoints : isJobTicketPoints1) {
                // 2.1.1更新隔离点解锁信息
                iIsJobTicketPointsService.update(Wrappers.<IsJobTicketPoints>lambdaUpdate()
                        .eq(IsJobTicketPoints::getRecordId, isJobTicketPoints.getRecordId())
                        .set(IsJobTicketPoints::getUnlockedByKeyId, unlockedByKeyId)
                        .set(IsJobTicketPoints::getUnlockTime, date)
                        .set(IsJobTicketPoints::getPointStatus, PointStatusEnum.REMOVE_LOCK.status));
                // 3.1开始更新解锁时挂锁信息
                iIsJobTicketLockService.update(Wrappers.<IsJobTicketLock>lambdaUpdate()
                        .eq(IsJobTicketLock::getTicketId, isJobTicketPoints.getTicketId())
                        .eq(IsJobTicketLock::getIsolationPointId, pointId)
                        .eq(IsJobTicketLock::getLockId, lockId)
                        .set(IsJobTicketLock::getLockStatus, LockStatusEnum.REMOVED_LOCK.status));
                // 4.1如果都解锁了，则更新作业负责人的任务状态
                int count = (int) iIsJobTicketPointsService.count(Wrappers.<IsJobTicketPoints>lambdaQuery()
                        .eq(IsJobTicketPoints::getTicketId, isJobTicketPoints.getTicketId())
                        .ne(IsJobTicketPoints::getPointStatus, "2"));
                if (count == 0) {
                    iIsJobTicketUserService.update(Wrappers.<IsJobTicketUser>lambdaUpdate()
                            .eq(IsJobTicketUser::getUserRole, isSystemAttributeService.getIsSystemAttributeByKey("role.jtlocker").getSysAttrValue())
                            .eq(IsJobTicketUser::getTicketId, isJobTicketPoints.getTicketId())
                            .set(IsJobTicketUser::getJobStatus, "5"));
                }
            }
        }

    }

    /**
     * 取出辅件时更新数据
     *
     * @param list
     * @return
     */
    @Override
    public Boolean updateLocksetTake(List<TakeLocksetDTO> list) {
        Assert.isFalse(list.isEmpty(), "请取出至少一个辅件!");
        // 情况复杂，软条件过多，单条剥离处理吧
        for (TakeLocksetDTO dto : list) {
            Assert.notNull(dto.getTicketId(), "请告诉我关于哪个作业票!");
            Assert.notBlank(dto.getLocksetNfc(), "辅件nfc缺失!");
            // 1.查询辅件的详情
            IsLockset lockset = iIsLocksetService.getOne(Wrappers.<IsLockset>lambdaQuery().eq(IsLockset::getLocksetNfc, dto.getLocksetNfc()));
            Assert.notNull(lockset, dto.getLocksetNfc() + "无对应的辅件信息!");
            // 1.1通过序列号查询柜子信息
            IsHardware isHardware = isHardwareService.getOne(Wrappers.<IsHardware>lambdaQuery()
                    .eq(IsHardware::getSerialNumber, dto.getSerialNumber()));
            Assert.notNull(isHardware, "该序列号无对应的硬件信息!");
            // 1.2获取该辅件的类型，找到is_job_ticket_lockset有没有对应的，可能会有多条，取其中一条即可，
            IsJobTicketLockset jobTicketLockset = iIsJobTicketLocksetService.getOne(Wrappers.<IsJobTicketLockset>lambdaQuery()
                    .eq(IsJobTicketLockset::getJobTicketId, dto.getTicketId())
                    // 未使用过的数据
                    .isNull(IsJobTicketLockset::getLocksetId)
                    // 处理下多条取一条用,按照从上倒下顺序使用
                    .orderByAsc(IsJobTicketLockset::getRecordId)
                    .last("offset 0 rows fetch next 1 rows only"));
            Assert.notNull(jobTicketLockset, "无初始化数据来提供给该辅件更新");
            // 1.3开始补充该条数据
            jobTicketLockset.setLocksetId(lockset.getLocksetId());
            jobTicketLockset.setFromHardwareId(isHardware.getId());
            jobTicketLockset.setLocksetStatus(LocksetStatusEnum.TAKED.status);
            jobTicketLockset.setCollectTime(new Date());
            iIsJobTicketLocksetService.updateById(jobTicketLockset);
        }
        return true;
    }

    /**
     * 辅件绑定隔离点(辅件和给隔离点上锁时)
     *
     * @param dto
     * @return
     */
    @Override
    public Boolean updateLocksetPoint(LocksetPointDTO dto) {
        Assert.notNull(dto.getTicketId(), "请告诉我关于哪个作业票!");
        Assert.notBlank(dto.getLocksetNfc(), "辅件nfc缺失!");
        Assert.notNull(dto.getPointNfc(), "请告知隔离点信息!");
        // 1.通过nfc查询挂锁信息
        IsLockset lockset = iIsLocksetService.getOne(Wrappers.<IsLockset>lambdaQuery()
                .eq(IsLockset::getLocksetNfc, dto.getLocksetNfc()));
        Assert.notNull(lockset, "该nfc无对应的辅件信息");
        // 2.通过nfc查询隔离点信息
        IsIsolationPoint point = iIsIsolationPointService.getOneByNfc(dto.getPointNfc());
        Assert.notNull(point, "该nfc无对应的隔离点信息");
        // 3.开始更新绑定关系
        iIsJobTicketLocksetService.update(Wrappers.<IsJobTicketLockset>lambdaUpdate()
                .eq(IsJobTicketLockset::getJobTicketId, dto.getTicketId())
                .eq(IsJobTicketLockset::getLocksetId, lockset.getLocksetId())
                .set(IsJobTicketLockset::getPointId, point.getPointId())
                .set(IsJobTicketLockset::getLocksetStatus, LocksetStatusEnum.USING.status));
        return true;
    }

    /**
     * 辅件归还物资柜
     *
     * @param dto
     * @return
     */
    @Override
    public Boolean updateLocksetReturn(ReturnLocksetDTO dto) {
        Assert.notBlank(dto.getLocksetNfc(), "辅件nfc缺失!");
        Assert.notBlank(dto.getSerialNumber(), "请告知归还到哪一个柜子!");
        // 1.通过nfc查询辅件信息
        IsLockset lockset = iIsLocksetService.getOne(Wrappers.<IsLockset>lambdaQuery()
                .eq(IsLockset::getLocksetNfc, dto.getLocksetNfc()));
        Assert.notNull(lockset, "该nfc无对应的辅件信息!");
        // 1.1通过序列号查询柜子信息
        IsHardware isHardware = isHardwareService.getOne(Wrappers.<IsHardware>lambdaQuery().eq(IsHardware::getSerialNumber, dto.getSerialNumber()));
        Assert.notNull(isHardware, "该序列号无对应的硬件信息!");
        // 2.开始更新归还信息
        if (dto.getTicketId() != null) {
            // 2.1登陆后归还
            iIsJobTicketLocksetService.update(Wrappers.<IsJobTicketLockset>lambdaUpdate()
                    .eq(IsJobTicketLockset::getJobTicketId, dto.getTicketId())
                    .eq(IsJobTicketLockset::getLocksetId, lockset.getLocksetId())
                    .set(IsJobTicketLockset::getToHardwareId, isHardware.getId())
                    .set(IsJobTicketLockset::getLocksetStatus, LocksetStatusEnum.RETURNED.status));
        } else {
            // 2.2不登陆状态下归还
            // 查一下哪个作业票用了这个挂锁，而且还没有完成
            List<IsJobTicketLockset> jobTicketLocksetList = iIsJobTicketLocksetService.list(Wrappers.<IsJobTicketLockset>lambdaQuery()
                    .eq(IsJobTicketLockset::getLocksetId, lockset.getLocksetId())
                    .ne(IsJobTicketLockset::getLocksetStatus, LocksetStatusEnum.RETURNED.status));
            if (jobTicketLocksetList.isEmpty()) {
                log.error("当前辅件未找到关联的作业票, nfc: {}, name : {}", dto.getLocksetNfc(), lockset.getLocksetName());
            } else if (jobTicketLocksetList.size() == 1) {
                // 说明找到的就是
                iIsJobTicketLocksetService.update(Wrappers.<IsJobTicketLockset>lambdaUpdate()
                        .eq(IsJobTicketLockset::getLocksetId, lockset.getLocksetId())
                        .set(IsJobTicketLockset::getToHardwareId, isHardware.getId())
                        .set(IsJobTicketLockset::getLocksetStatus, LocksetStatusEnum.RETURNED.status));
            } else {
                // 出现了多条对应
                log.error("当前辅件找到多条关联的作业票, nfc: {}, name : {}", dto.getLocksetNfc(), lockset.getLocksetName());
            }
        }
        return true;
    }

    /**
     * 获取作业票和关联数据
     *
     * @param ticketId
     * @return
     */
    @Override
    public JobTicketVO selectTicketDetailById(Long ticketId) {
        Assert.notNull(ticketId, "作业票id不可为空!");
        // 0.作业前检查
        /*List<IsJobTicketStep> steps = iIsJobTicketStepService.list(Wrappers.<IsJobTicketStep>lambdaQuery()
                .eq(IsJobTicketStep::getTicketId, ticketId));
        IsJobTicketStep isJobTicketStep3 = steps.stream().filter(o -> o.getStepIndex().equals(3)).collect(Collectors.toList()).get(0);
        IsJobTicketStep isJobTicketStep4 = steps.stream().filter(o -> o.getStepIndex().equals(4)).collect(Collectors.toList()).get(0);
        IsJobTicketStep isJobTicketStep6 = steps.stream().filter(o -> o.getStepIndex().equals(6)).collect(Collectors.toList()).get(0);
        IsJobTicketStep isJobTicketStep7 = steps.stream().filter(o -> o.getStepIndex().equals(7)).collect(Collectors.toList()).get(0);
        if (isJobTicketStep3.getStepStatus().equals("1") && isJobTicketStep4.getStepStatus().equals("0")) {
            // 则是去上锁
            checkBeforeToLock(ticketId);
        }
        if (isJobTicketStep6.getStepStatus().equals("1") && isJobTicketStep7.getStepStatus().equals("0")) {
            // 则是去上锁
            checkBeforeToUnlock(ticketId);
        }*/
        // 1.查询作业票信息
        IsJobTicket isJobTicket = isJobTicketService.getById(ticketId);
        Assert.notNull(isJobTicket, "作业票信息丢失！");
        JobTicketVO jobTicketVO = BeanUtils.toBean(isJobTicket, JobTicketVO.class);
        // 2.查询钥匙数据
        List<IsJobTicketKey> ticketKeyList = iIsJobTicketKeyService.list(Wrappers.<IsJobTicketKey>lambdaQuery()
                .eq(IsJobTicketKey::getTicketId, ticketId));
        List<JobTicketKeyVO> ticketKeyVOList = BeanUtils.toBean(ticketKeyList, JobTicketKeyVO.class);
        // 3.查询挂锁数据
        /*List<IsJobTicketLock> jobTicketLockList = iIsJobTicketLockService.list(Wrappers.<IsJobTicketLock>lambdaQuery()
                .eq(IsJobTicketLock::getTicketId, ticketId));
        List<JobTicketLockVO> ticketLockVOList = BeanUtils.toBean(jobTicketLockList, JobTicketLockVO.class);*/
        List<JobTicketLockVO> ticketLockVOList = iIsJobTicketLockService.getTicketLockByTicketId(ticketId);
        // 4.查询辅件数据
        List<IsJobTicketLockset> jobTicketLocksetList = iIsJobTicketLocksetService.list(Wrappers.<IsJobTicketLockset>lambdaQuery()
                .eq(IsJobTicketLockset::getJobTicketId, ticketId));
        List<JobTicketLocksetVO> ticketLocksetVOList = BeanUtils.toBean(jobTicketLocksetList, JobTicketLocksetVO.class);
        // 5.查询用户数据
        List<IsJobTicketUser> jobTicketUserList = iIsJobTicketUserService.list(Wrappers.<IsJobTicketUser>lambdaQuery()
                .eq(IsJobTicketUser::getTicketId, ticketId));
        List<JobTicketUserVO> ticketUserVOList = BeanUtils.toBean(jobTicketUserList, JobTicketUserVO.class);
        // 6.查询隔离点数据
        /*List<IsJobTicketPoints> jobTicketPointsList = iIsJobTicketPointsService.list(Wrappers.<IsJobTicketPoints>lambdaQuery()
                .eq(IsJobTicketPoints::getTicketId, ticketId));*/
        List<IsJobTicketPointsVO> listByTicketId = iIsJobTicketPointsService.getListByTicketId(ticketId);
        List<JobTicketPointsVO> ticketPointsVOList = BeanUtils.toBean(listByTicketId, JobTicketPointsVO.class);
        if (!ticketPointsVOList.isEmpty()) {
            List<Long> pointIds = ticketPointsVOList.stream().map(JobTicketPointsVO::getPointId).collect(Collectors.toList());
            List<PointDetailVO> pointDetailList = iIsIsolationPointService.getPointDetailList(pointIds);
            for (JobTicketPointsVO jobTicketPointsVO : ticketPointsVOList) {
                for (PointDetailVO pointDetailVO : pointDetailList) {
                    if (jobTicketPointsVO.getPointId().equals(pointDetailVO.getPointId())) {
                        jobTicketPointsVO.setPointCode(pointDetailVO.getPointCode());
                        jobTicketPointsVO.setPointName(pointDetailVO.getPointName());
                        jobTicketPointsVO.setPointType(pointDetailVO.getPointType());
                        jobTicketPointsVO.setPointTypeName(pointDetailVO.getPointTypeName());
                        jobTicketPointsVO.setPointNfc(pointDetailVO.getPointNfc());
                        jobTicketPointsVO.setWorkshopName(pointDetailVO.getWorkshopName());
                        jobTicketPointsVO.setWorkareaName(pointDetailVO.getWorkareaName());
                        jobTicketPointsVO.setWorkstationId(pointDetailVO.getWorkstationId());
                        jobTicketPointsVO.setWorkstationName(pointDetailVO.getWorkstationName());
                        jobTicketPointsVO.setLotoId(pointDetailVO.getLotoId());
                        jobTicketPointsVO.setLotoName(pointDetailVO.getLotoName());
                        jobTicketPointsVO.setPowerType(pointDetailVO.getPowerType());
                        jobTicketPointsVO.setPowerTypeName(pointDetailVO.getPowerTypeName());
                        jobTicketPointsVO.setIsolationMethod(pointDetailVO.getIsolationMethod());
                        jobTicketPointsVO.setPointIcon(pointDetailVO.getPointIcon());
                        jobTicketPointsVO.setPointPicture(pointDetailVO.getPointPicture());
                        jobTicketPointsVO.setLockTypeId(pointDetailVO.getLockTypeId());
                        jobTicketPointsVO.setLockTypeCode(pointDetailVO.getLockTypeCode());
                        jobTicketPointsVO.setLockTypeName(pointDetailVO.getLockTypeName());
                        jobTicketPointsVO.setLockTypeIcon(pointDetailVO.getLockTypeIcon());
                        jobTicketPointsVO.setLockTypeImg(pointDetailVO.getLockTypeImg());
                        // jobTicketPointsVO.setLockNfc(pointDetailVO.getLockNfc());
                        jobTicketPointsVO.setLocksetTypeId(pointDetailVO.getLocksetTypeId());
                    }
                }
            }
        }
        // 7.解锁时，提供的不可解锁的点位数据
        Set<JobTicketPointsVO> noUnlockTicketPointsVOSet = new HashSet<>();
        // if (isSystemAttributeService.getIsSystemAttributeByKey("sys.job.lock_type").getSysAttrValue().equals("1")) {
            /*List<Long> points = ticketPointsVOList.stream().map(JobTicketPointsVO::getPointId).collect(Collectors.toList());
            List<JobTicketDetailVO> jobTicketDetailVOS2 = isJobTicketService.selectConflictTicket2(points, ticketId);
            if (!jobTicketDetailVOS2.isEmpty()) {
                // 代表存在不可解除的点位，查询出来
                List<Long> longList = jobTicketDetailVOS2.stream().map(JobTicketDetailVO::getTicketId).collect(Collectors.toList());
                List<IsJobTicketPoints> list = iIsJobTicketPointsService.list(Wrappers.<IsJobTicketPoints>lambdaQuery()
                        .in(IsJobTicketPoints::getTicketId, longList));
                // 可能有多个作业多个点位，去重一下
                Set<IsJobTicketPoints> set = new HashSet<>(list);
                for (JobTicketPointsVO isJobTicketPoints : ticketPointsVOList) {
                    for (IsJobTicketPoints jobTicketPoints : set) {
                        if (isJobTicketPoints.getPointId().equals(jobTicketPoints.getPointId())) {
                            noUnlockTicketPointsVOSet.add(isJobTicketPoints);
                        }
                    }
                }
            }*/
        // 查找点位相同并且用了同一个锁没有解锁的作业点位(存在虚拟锁的冲突点位)
        for (JobTicketPointsVO jobTicketPointsVO : ticketPointsVOList) {
            List<IsJobTicketPoints> virtualLockConflictPoint = iIsJobTicketPointsService.getVirtualLockConflictPoint(jobTicketPointsVO.getPointId(), jobTicketPointsVO.getLockId(), jobTicketPointsVO.getTicketId());
            if (!virtualLockConflictPoint.isEmpty()) {
                noUnlockTicketPointsVOSet.add(jobTicketPointsVO);
            }
        }
        // }

        // 8.组装数据
        jobTicketVO.setTicketKeyVOList(ticketKeyVOList);
        jobTicketVO.setTicketLockVOList(ticketLockVOList);
        jobTicketVO.setTicketLocksetVOList(ticketLocksetVOList);
        jobTicketVO.setTicketUserVOList(ticketUserVOList);
        jobTicketVO.setTicketPointsVOList(ticketPointsVOList);
        jobTicketVO.setNoUnlockTicketPointsVOSet(noUnlockTicketPointsVOSet);
        return jobTicketVO;
    }

    @Override
    public Boolean updateColockerStatus(UpdateColockerStatusDTO dto) {
        Assert.notNull(dto.getTicketId(), "作业票id不能为空!");
        Assert.notBlank(dto.getJobStatus(), "操作的共锁/解锁状态不能为空!");
        Assert.notBlank(dto.getCardNfc(), "工作卡NFC不能为空!");
        // 1.根据作业卡获取当前人员状态
        IsJobCard card = iIsJobCardService.getOne(Wrappers.<IsJobCard>lambdaQuery().eq(IsJobCard::getCardNfc, dto.getCardNfc()));
        Assert.isFalse(card == null, "该工作卡未绑定用户!");
        // 2.检测获取这个人在该作业票中状态
        IsJobTicketUser jobTicketUser = iIsJobTicketUserService.getOne(Wrappers.<IsJobTicketUser>lambdaQuery()
                .eq(IsJobTicketUser::getUserId, card.getUserId())
                .eq(IsJobTicketUser::getUserRole, isSystemAttributeService.getIsSystemAttributeByKey("role.jtcolocker").getSysAttrValue())
                .eq(IsJobTicketUser::getTicketId, dto.getTicketId()));
        Assert.isFalse(jobTicketUser == null, "该员工卡绑定的员工暂无作业任务!");
        // 2.1判断状态
        IsJobTicket isJobTicket = isJobTicketService.getById(dto.getTicketId());
        Assert.isFalse("0".equals(isJobTicket.getTicketStatus()), "该作业票未开始，请勿共锁！");
        Assert.isFalse("4".equals(dto.getJobStatus()) && "4".equals(jobTicketUser.getJobStatus()), "您已共锁，请勿重复共锁！");
        Assert.isFalse(Integer.parseInt(jobTicketUser.getJobStatus()) < 4 && "5".equals(dto.getJobStatus()), "您还未共锁，请勿操作解除共锁！");
        Assert.isFalse("5".equals(jobTicketUser.getJobStatus()) && "5".equals(dto.getJobStatus()), "您已解除共锁，请勿重复解除锁！");
        // 3.开始操作
        iIsJobTicketUserService.update(Wrappers.<IsJobTicketUser>lambdaUpdate()
                .eq(IsJobTicketUser::getTicketId, dto.getTicketId())
                .eq(IsJobTicketUser::getUserId, card.getUserId())
                .set(IsJobTicketUser::getJobStatus, dto.getJobStatus()));
        // 添加共锁
        if (dto.getJobStatus().equals("4")) {
            isTicketOperLogService.addLog6(isJobTicket.getTicketId(), isJobTicket.getTicketName(), jobTicketUser.getUserName());
        }
        // 解除共锁
        if (dto.getJobStatus().equals("5")) {
            isTicketOperLogService.addLog7(isJobTicket.getTicketId(), isJobTicket.getTicketName(), jobTicketUser.getUserName());
        }
        return true;
    }

    /**
     * 0-更新失败
     * 1-更新成功
     * 2-更新失败
     * @param dto
     * @return
     */
    @Override
    public Integer updateSwitchList(UpdateSwitchParam dto) {
        Assert.isFalse(dto.getList().isEmpty(), "点位开关数据不可为空！");
        Date date = new Date();
        dto.getList().forEach(o -> {
            Assert.notBlank(o.getLotoSerialNumber(), "锁定站序列号不可为空！");
            Assert.notBlank(o.getPointSerialNumber(), "点位序列号不可为空！");
            o.setSwitchLastUpdateTime(date);
        });
        int result = 1;
        // 判断是否有数据变更
        List<UpdateSwitchStatusDTO> pointList = redisCache.getCacheList(SYS_ATTR + dto.getList().get(0).getLotoSerialNumber() + ":sys.points.switch.records");
        if (dto.getList().size() != pointList.size()) {
            result = 2;
        } else {
            for (UpdateSwitchStatusDTO updateSwitchStatusDTO : dto.getList()) {
                List<UpdateSwitchStatusDTO> collect = pointList.stream()
                        .filter(o -> o.getPointSerialNumber().equals(updateSwitchStatusDTO.getPointSerialNumber())).collect(Collectors.toList());
                if (collect.isEmpty()) {
                    result = 2;
                    break;
                } else {
                    if (!updateSwitchStatusDTO.getSwitchStatus().equals(collect.get(0).getSwitchStatus())) {
                        result = 2;
                        break;
                    }
                }
            }
        }
        redisCache.deleteObject(SYS_ATTR + dto.getList().get(0).getLotoSerialNumber() + ":sys.points.switch.last");
        redisCache.setCacheList(SYS_ATTR + dto.getList().get(0).getLotoSerialNumber() + ":sys.points.switch.last", dto.getList());
        redisCache.expire(SYS_ATTR + dto.getList().get(0).getLotoSerialNumber() + ":sys.points.switch.last", 60, TimeUnit.SECONDS);
        redisCache.deleteObject(SYS_ATTR + dto.getList().get(0).getLotoSerialNumber() + ":sys.points.switch.records");
        redisCache.setCacheList(SYS_ATTR + dto.getList().get(0).getLotoSerialNumber() + ":sys.points.switch.records", dto.getList());
        return result;
    }


    @Transactional
    @Override
    public Boolean checkBeforeToLock(Long ticketId) {
        boolean b = false;
        Assert.notNull(ticketId, "当前作业票id不能为空！");
        // 0.检查是不是取了锁 但是没有取钥匙，如果是说明数据有问题，断过网
        // checkExTakeLock(ticketId);
        IsJobTicket isJobTicket = isJobTicketService.getById(ticketId);
        // 1.查询当前作业票需要上锁的点位信息
        List<IsJobTicketPoints> listByTicketId = iIsJobTicketPointsService.list(Wrappers.<IsJobTicketPoints>lambdaQuery()
                .eq(IsJobTicketPoints::getTicketId, ticketId));
        // 4.更新下作业票的状态，如果是上锁时的操作
        isJobTicketService.update(Wrappers.<IsJobTicket>lambdaUpdate()
                .eq(IsJobTicket::getTicketId, ticketId)
                .set(IsJobTicket::getTicketStatus, "2"));
        if (!listByTicketId.isEmpty() && b) {
            // 如果存在冲突的作业，检查下到了哪个阶段（取了钥匙上锁还未归还、上锁钥匙已归还、取了钥匙去解锁未归还、解锁完成钥匙已归还）
            List<Long> points = listByTicketId.stream().map(IsJobTicketPoints::getPointId).collect(Collectors.toList());
            // 2.如果有重复点位，取了钥匙去上锁没有归还的作业
            List<JobTicketDetailVO> jobTicketDetailVOS1 = isJobTicketService.selectConflictTicket1(points, ticketId);
            if (!jobTicketDetailVOS1.isEmpty()) {
                Assert.isFalse(true, "请等待作业票[" + jobTicketDetailVOS1.get(0).getTicketName() + "]上锁完成！");
            }
            // 3.如果上锁钥匙已经归还，需要使用别人的数据帮我们的重复点位上锁了
            // 找到别人已经上锁的并且没有解锁的，而且点位和我重复的作业
            List<JobTicketDetailVO> jobTicketDetailVOS2 = isJobTicketService.selectConflictTicket2(points, ticketId);
            if (!jobTicketDetailVOS2.isEmpty()) {
                List<Long> longList = jobTicketDetailVOS2.stream().map(JobTicketDetailVO::getTicketId).collect(Collectors.toList());
                List<IsJobTicketPoints> list = iIsJobTicketPointsService.list(Wrappers.<IsJobTicketPoints>lambdaQuery()
                        .in(IsJobTicketPoints::getTicketId, longList));
                // 可能有多个作业多个点位，去重一下
                Set<IsJobTicketPoints> set = new HashSet<>(list);
                for (IsJobTicketPoints jobTicketPoints : set) {
                    for (IsJobTicketPoints isJobTicketPoints : listByTicketId) {
                        if (isJobTicketPoints.getPointId().equals(jobTicketPoints.getPointId())) {
                            // isJobTicketPoints.setWorkshopId();
                            // isJobTicketPoints.setWorkareaId();
                            // isJobTicketPoints.setPointId();
                            isJobTicketPoints.setPointStatus(jobTicketPoints.getPointStatus());
                            isJobTicketPoints.setLockId(jobTicketPoints.getLockId());
                            isJobTicketPoints.setLockedByKeyId(jobTicketPoints.getLockedByKeyId());
                            // isJobTicketPoints.setUnlockedByKeyId();
                            isJobTicketPoints.setLockTime(jobTicketPoints.getLockTime());
                            // isJobTicketPoints.setUnlockTime();
                            // isJobTicketPoints.setPrePointId();
                            // isJobTicketPoints.setWorkstationId();
                            // isJobTicketPoints.setMachineryId();
                            iIsJobTicketPointsService.updateById(isJobTicketPoints);
                            // 3.开始更新上锁时挂锁信息
                            IsJobTicketLock one = iIsJobTicketLockService.getOne(Wrappers.<IsJobTicketLock>lambdaUpdate()
                                    .eq(IsJobTicketLock::getTicketId, isJobTicketPoints.getTicketId())
                                    .isNull(IsJobTicketLock::getLockId)
                                    .orderByAsc(IsJobTicketLock::getRecordId)
                                    .last("offset 0 rows fetch next 1 rows only"));
                            if (one != null) {
                                iIsJobTicketLockService.update(Wrappers.<IsJobTicketLock>lambdaUpdate()
                                        .eq(IsJobTicketLock::getRecordId, one.getRecordId())
                                        .set(IsJobTicketLock::getLockId, jobTicketPoints.getLockId())
                                        .set(IsJobTicketLock::getIsolationPointId, jobTicketPoints.getPointId())
                                        .set(IsJobTicketLock::getLockStatus, LockStatusEnum.LOCKED.status));
                                // 4.如果隔离点上锁完毕，则更新作业负责人的任务状态
                                /*int count = (int) iIsJobTicketPointsService.count(Wrappers.<IsJobTicketPoints>lambdaQuery()
                                        .eq(IsJobTicketPoints::getTicketId, isJobTicketPoints.getTicketId())
                                        .ne(IsJobTicketPoints::getPointStatus, "1"));
                                if (count == 0) {
                                    iIsJobTicketUserService.update(Wrappers.<IsJobTicketUser>lambdaUpdate()
                                            .eq(IsJobTicketUser::getUserRole, isSystemAttributeService.getIsSystemAttributeByKey("role.jtlocker").getSysAttrValue())
                                            .eq(IsJobTicketUser::getTicketId, isJobTicketPoints.getTicketId())
                                            .set(IsJobTicketUser::getJobStatus, "4"));
                                    // 4.更新下作业票的状态，如果是上锁时的操作
                                    isJobTicketService.update(Wrappers.<IsJobTicket>lambdaUpdate()
                                            .eq(IsJobTicket::getTicketId, isJobTicketPoints.getTicketId())
                                            .set(IsJobTicket::getTicketStatus, "2"));
                                }*/
                            }
                        }
                    }
                }
            }
            // 4.如果别人拿了钥匙去解锁，那我直接弹全部，自己去上锁
            // 5.如果别人解锁完成归还钥匙，则全部可以弹出去上锁
        }
        // 启动上锁
        isTicketOperLogService.addLog4(isJobTicket.getTicketId(), isJobTicket.getTicketName());
        return true;
    }

    /**
     * 纠正异常取锁
     */
    private void checkExTakeLock(Long ticketId) {
        // 检查是否取出钥匙去上锁，如果没有取到钥匙，但是取出了挂锁，说明有问题，则清空挂锁信息
        IsJobTicketKey one = iIsJobTicketKeyService.getOne(Wrappers.<IsJobTicketKey>lambdaQuery()
                .eq(IsJobTicketKey::getTicketId, ticketId)
                .eq(IsJobTicketKey::getTicketType, 0)
                .isNull(IsJobTicketKey::getKeyId));
        List<IsJobTicketLock> list = iIsJobTicketLockService.list(Wrappers.<IsJobTicketLock>lambdaQuery()
                .eq(IsJobTicketLock::getTicketId, ticketId)
                .isNotNull(IsJobTicketLock::getLockId));
        if (one != null && !list.isEmpty()) {
            // 现在是上锁前检查，但是钥匙已经取出来了，有问题啊，现在开始置空
            for (IsJobTicketLock isJobTicketLock : list) {
                iIsJobTicketLockService.update(Wrappers.<IsJobTicketLock>lambdaUpdate()
                        .eq(IsJobTicketLock::getRecordId, isJobTicketLock.getRecordId())
                        .set(IsJobTicketLock::getLockId, null)
                        .set(IsJobTicketLock::getLockStatus, "0")
                        .set(IsJobTicketLock::getFromHardwareId, null)
                );
            }
        }
    }

    @Override
    public Boolean checkBeforeToUnlock(Long ticketId) {
        Assert.notNull(ticketId, "当前作业票id不能为空！");
        // 1.查询当前作业票需要解锁的点位信息
        List<IsJobTicketPoints> listByTicketId = iIsJobTicketPointsService.list(Wrappers.<IsJobTicketPoints>lambdaQuery()
                .eq(IsJobTicketPoints::getTicketId, ticketId));
        if (!listByTicketId.isEmpty()) {
            // 如果存在冲突的作业，检查下到了哪个阶段（取了钥匙上锁还未归还、上锁钥匙已归还、取了钥匙去解锁未归还、解锁完成钥匙已归还）
            List<Long> points = listByTicketId.stream().map(IsJobTicketPoints::getPointId).collect(Collectors.toList());
            // 2.如果有重复点位，取了钥匙去上锁没有归还的作业
            List<JobTicketDetailVO> jobTicketDetailVOS1 = isJobTicketService.selectConflictTicket1(points, ticketId);
            if (!jobTicketDetailVOS1.isEmpty()) {
                Assert.isFalse(true, "请等待作业票[" + jobTicketDetailVOS1.get(0).getTicketName() + "]上锁完成！");
            }
            // 3.如果取了钥匙去上锁已经归还，代表别的上锁已经完成，我可以解除不是重复的点位，然后手动完成作业，这样别人作业结束以后可以直接解除物理锁
            // List<JobTicketDetailVO> jobTicketDetailVOS2 = isJobTicketService.selectConflictTicket2(points, ticketId);
            // 4.如果别人取了钥匙去解锁，说明都是去解锁，我可以解全部

            // 5.如果别人解除完了回来完成了作业，我可以解除全部
        }
        // 启动解锁
        isTicketOperLogService.addLog8(ticketId, isJobTicketService.getById(ticketId).getTicketName());
        return true;
    }

    @Override
    public Boolean updateCoincideToUnLock(CoincidePointToUnLockDTO dto) {
        if (!dto.getNoUnlockTicketPointsVOSet().isEmpty()) {
            Date date = new Date();
            for (JobTicketPointsVO jobTicketPointsVO : dto.getNoUnlockTicketPointsVOSet()) {
                iIsJobTicketPointsService.update(Wrappers.<IsJobTicketPoints>lambdaUpdate()
                        .eq(IsJobTicketPoints::getRecordId, jobTicketPointsVO.getRecordId())
                        .set(IsJobTicketPoints::getUnlockedByKeyId, jobTicketPointsVO.getLockedByKeyId())
                        .set(IsJobTicketPoints::getUnlockTime, date)
                        .set(IsJobTicketPoints::getPointStatus, PointStatusEnum.REMOVE_LOCK.status));
                // 3.1开始更新解锁时挂锁信息
                iIsJobTicketLockService.update(Wrappers.<IsJobTicketLock>lambdaUpdate()
                        .eq(IsJobTicketLock::getTicketId, jobTicketPointsVO.getTicketId())
                        .eq(IsJobTicketLock::getLockId, jobTicketPointsVO.getLockId())
                        .set(IsJobTicketLock::getLockStatus, LockStatusEnum.REMOVED_LOCK.status));
                // 4.1如果都解锁了，则更新作业负责人的任务状态
                int count = (int) iIsJobTicketPointsService.count(Wrappers.<IsJobTicketPoints>lambdaQuery()
                        .eq(IsJobTicketPoints::getTicketId, jobTicketPointsVO.getTicketId())
                        .ne(IsJobTicketPoints::getPointStatus, "2"));
                if (count == 0) {
                    iIsJobTicketUserService.update(Wrappers.<IsJobTicketUser>lambdaUpdate()
                            .eq(IsJobTicketUser::getUserRole, isSystemAttributeService.getIsSystemAttributeByKey("role.jtlocker").getSysAttrValue())
                            .eq(IsJobTicketUser::getTicketId, jobTicketPointsVO.getTicketId())
                            .set(IsJobTicketUser::getJobStatus, "5"));
                }
            }
        }
        return true;
    }

    @Transactional
    @Override
    public Boolean updateHardwareEsStatus(ExDTO dto) {
        // 1.开始更新钥匙
        if (!dto.getKeyExDTOList().isEmpty()) {
            List<String> keyNfcList = dto.getKeyExDTOList().stream().map(IsKeyExDTO::getKeyNfc).collect(Collectors.toList());
            List<IsKey> isKeyList = isKeyService.list(Wrappers.<IsKey>lambdaQuery()
                    .in(IsKey::getKeyNfc, keyNfcList));
            for (IsKey isKey : isKeyList) {
                for (IsKeyExDTO isKeyExDTO : dto.getKeyExDTOList()) {
                    if (isKey.getKeyNfc().equals(isKeyExDTO.getKeyNfc())) {
                        isKey.setExStatus(isKeyExDTO.getExStatus());
                        isKey.setExRemark(isKeyExDTO.getExRemark());
                    }
                }
            }
            isKeyService.updateBatchById(isKeyList);
        }
        // 2.开始更新挂锁
        if (!dto.getLockExDTOList().isEmpty()) {
            List<String> lockNfcList = dto.getLockExDTOList().stream().map(IsLockExDTO::getLockNfc).collect(Collectors.toList());
            List<IsLock> isLockList = iIsLockService.list(Wrappers.<IsLock>lambdaQuery()
                    .in(IsLock::getLockNfc, lockNfcList));
            for (IsLock isLock : isLockList) {
                for (IsLockExDTO isLockExDTO : dto.getLockExDTOList()) {
                    if (isLock.getLockNfc().equals(isLockExDTO.getLockNfc())) {
                        isLock.setExStatus(isLockExDTO.getExStatus());
                        isLock.setExRemark(isLockExDTO.getExRemark());
                    }
                }
            }
            iIsLockService.updateBatchById(isLockList);
        }
        // 3.开始更新工卡
        if (!dto.getJobCardExDTOList().isEmpty()) {
            List<String> cardNfcList = dto.getJobCardExDTOList().stream().map(IsJobCardExDTO::getCardNfc).collect(Collectors.toList());
            List<IsJobCard> cardList = iIsJobCardService.list(Wrappers.<IsJobCard>lambdaQuery()
                    .in(IsJobCard::getCardNfc, cardNfcList));
            for (IsJobCard isJobCard : cardList) {
                for (IsJobCardExDTO isJobCardExDTO : dto.getJobCardExDTOList()) {
                    if (isJobCard.getCardNfc().equals(isJobCardExDTO.getCardNfc())) {
                        isJobCard.setExStatus(isJobCardExDTO.getExStatus());
                        isJobCard.setExRemark(isJobCardExDTO.getExRemark());
                    }
                }
            }
            iIsJobCardService.updateBatchById(cardList);
        }
        // 4.开始更新锁仓
        if (!dto.getSlotsExDTOList().isEmpty()) {
            for (IsLockCabinetSlotsExDTO slotsExDTO : dto.getSlotsExDTOList()) {
                if (StringUtils.isNotBlank(slotsExDTO.getRow()) && StringUtils.isNotBlank(slotsExDTO.getCol())) {
                    iIsLockCabinetSlotsService.update(Wrappers.<IsLockCabinetSlots>lambdaUpdate()
                            .eq(IsLockCabinetSlots::getRow, slotsExDTO.getRow())
                            .eq(IsLockCabinetSlots::getCol, slotsExDTO.getCol())
                            .set(IsLockCabinetSlots::getStatus, slotsExDTO.getStatus())
                            .set(IsLockCabinetSlots::getRemark, slotsExDTO.getRemark()));
                }
            }
        }
        return true;
    }

    @Override
    public Boolean getMySelfState() {
        // 当前登陆人
        Long userId = SecurityUtils.getUserId();
        // 获取当前登陆人未完成的作业
        List<IsJobTicketUser> myJobs = iIsJobTicketUserService.getMyJob(userId);
        System.out.println("myJobs=" + myJobs.toString());
        if (myJobs.isEmpty()) {
            return false;
        }
        // 如果有，检查一下这个人是否是需要去上锁
        for (IsJobTicketUser myJob : myJobs) {
            List<IsJobTicketStep> steps = iIsJobTicketStepService.list(Wrappers.<IsJobTicketStep>lambdaQuery()
                    .eq(IsJobTicketStep::getTicketId, myJob.getTicketId())
                    .eq(IsJobTicketStep::getStepIndex, "5")
                    .eq(IsJobTicketStep::getStepStatus, "0"));
            System.out.println("steps=" + steps.toString());
            if (!steps.isEmpty()) {
                return true;
            }
        }
        // 检查是否有需要解锁的，如果共锁人都已经解锁，但是点位存在没解锁
        for (IsJobTicketUser myJob : myJobs) {
            List<IsJobTicketUser> list = iIsJobTicketUserService.list(Wrappers.<IsJobTicketUser>lambdaQuery()
                    .eq(IsJobTicketUser::getTicketId, myJob.getTicketId())
                    .eq(IsJobTicketUser::getUserRole, JobUserEnum.JTCOLOCKER)
                    .eq(IsJobTicketUser::getJobStatus, "5"));
            List<IsJobTicketPoints> list1 = iIsJobTicketPointsService.list(Wrappers.<IsJobTicketPoints>lambdaQuery()
                    .eq(IsJobTicketPoints::getTicketId, myJob.getTicketId())
                    .eq(IsJobTicketPoints::getPointStatus, "1"));
            System.out.println("list=" + list.toString() + "----------list1=" + list1.toString());
            if (list.isEmpty() && !list1.isEmpty()) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断挂锁关联作业处于哪个阶段 0-上锁未取钥匙(可锁-需更改还锁逻辑) 1-上锁取了钥匙(不可锁) 2-上锁归还了钥匙(可锁) 3-解锁取了钥匙(可锁) 4-解锁归还了钥匙(可锁) 5-和作业无关(可锁)
     *
     * @param nfc
     * @return
     */
    @Override
    public Integer getLockStateByNfc(String nfc, Long ticketId) {
        Assert.notBlank(nfc, "该锁nfc不能为空！");
        // 查询当前锁是否存在
        IsLock lock = iIsLockService.getOne(Wrappers.<IsLock>lambdaQuery()
                .eq(IsLock::getLockNfc, nfc));
        Assert.isFalse(lock == null, nfc + "对应的挂锁数据不存在！");
        // 查询这个挂锁有没有不是完成或者取消的作业，然后判断作业能不能
        IsJobTicketLock lockJobByBfc = iIsJobTicketLockService.getLockJobByBfc(nfc, ticketId);
        if (lockJobByBfc != null) {
            // 判断作业到了什么阶段
            // 获取上锁时钥匙的最新一条数据
            IsJobTicketKey lockLast = iIsJobTicketKeyService.getOne(Wrappers.<IsJobTicketKey>lambdaQuery()
                    .eq(IsJobTicketKey::getTicketId, lockJobByBfc.getTicketId())
                    .eq(IsJobTicketKey::getTicketType, 0)
                    .orderByDesc(IsJobTicketKey::getRecordId)
                    .last("offset 0 rows fetch next 1 rows only"));
            // 获取解锁时钥匙的最新一条数据
            IsJobTicketKey unlockLast = iIsJobTicketKeyService.getOne(Wrappers.<IsJobTicketKey>lambdaQuery()
                    .eq(IsJobTicketKey::getTicketId, lockJobByBfc.getTicketId())
                    .eq(IsJobTicketKey::getTicketType, 1)
                    .orderByDesc(IsJobTicketKey::getRecordId)
                    .last("offset 0 rows fetch next 1 rows only"));
            // 判断阶段
            if (lockLast.getKeyStatus().equals("0")) {
                return 0;
            } else if (lockLast.getKeyStatus().equals("1")) {
                return 1;
            } else if (lockLast.getKeyStatus().equals("2") && unlockLast.getKeyStatus().equals("0")) {
                return 2;
            } else if (unlockLast.getKeyStatus().equals("1")) {
                return 3;
            } else if (unlockLast.getKeyStatus().equals("2")) {
                return 4;
            }
        }
        return 5;
    }
}
