package com.ximai.mes.tm.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ximai.common.constant.UserConstants;
import com.ximai.common.utils.MessageUtils;
import com.ximai.common.utils.data.DataUtil;
import com.ximai.common.utils.data.ExceptionUtil;
import com.ximai.common.utils.data.StringUtils;
import com.ximai.mes.constant.TaskWorkunitStatusEnum;
import com.ximai.mes.constant.TmToolMachineCheckEnum;
import com.ximai.mes.constant.TmToolMachineTypeEnum;
import com.ximai.mes.constant.TmToolStatusEnum;
import com.ximai.mes.md.domain.MdItem;
import com.ximai.mes.md.domain.MdWorkunit;
import com.ximai.mes.md.mapper.MdItemMapper;
import com.ximai.mes.md.mapper.MdWorkunitMapper;
import com.ximai.mes.md.vo.MdItemVo;
import com.ximai.mes.md.vo.MdWorkunitVo;
import com.ximai.mes.pro.domain.ProArrange;
import com.ximai.mes.pro.domain.proWorkOrder.ProWorkOrderProcess;
import com.ximai.mes.pro.domain.proWorkOrder.ProWorkOrderProcessTool;
import com.ximai.mes.pro.domain.proWorkOrder.ProWorkorder;
import com.ximai.mes.pro.domain.task.ProTask;
import com.ximai.mes.pro.domain.task.ProTaskWorkunit;
import com.ximai.mes.pro.mapper.ProArrangeMapper;
import com.ximai.mes.pro.mapper.proWorkOrder.ProWorkOrderProcessMapper;
import com.ximai.mes.pro.mapper.proWorkOrder.ProWorkOrderProcessToolMapper;
import com.ximai.mes.pro.mapper.task.ProTaskMapper;
import com.ximai.mes.pro.mapper.task.ProTaskWorkunitMapper;
import com.ximai.mes.pro.service.proWorkOrder.IProWorkOrderProcessService;
import com.ximai.mes.pro.service.proWorkOrder.IProWorkOrderProcessToolService;
import com.ximai.mes.tm.domain.TmTool;
import com.ximai.mes.tm.domain.TmToolMachines;
import com.ximai.mes.tm.domain.TmToolRequestUseItem;
import com.ximai.mes.tm.mapper.TmToolMachinesMapper;
import com.ximai.mes.tm.mapper.TmToolMapper;
import com.ximai.mes.tm.mapper.TmToolRequestUseItemMapper;
import com.ximai.mes.tm.service.ITmToolMachinesService;
import com.ximai.system.strategy.AutoCodeUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.bridge.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.ximai.mes.constant.WorkorderProcessConst.IS_EXIST_TOOL_NO;
import static com.ximai.mes.constant.WorkorderProcessConst.IS_EXIST_TOOL_YES;

/**
 * 刀模版上下机Service业务层处理
 *
 * @author generator
 * @date 2024-02-06
 */
@Slf4j
@Service
public class TmToolMachinesServiceImpl implements ITmToolMachinesService {
    @Autowired
    private TmToolMachinesMapper tmToolMachinesMapper;


    @Resource
    private ProWorkOrderProcessMapper proWorkOrderProcessMapper;
    @Autowired
    private TmToolMapper tmToolMapper;
    @Autowired
    private TmToolRequestUseItemMapper tmToolRequestUseItemMapper;

    @Autowired
    private AutoCodeUtil autoCodeUtil;

    @Autowired
    private IProWorkOrderProcessToolService proWorkOrderProcessToolService;
    @Autowired
    private ProWorkOrderProcessToolMapper proWorkOrderProcessToolMapper;

    @Autowired
    private IProWorkOrderProcessService proWorkOrderProcessService;

    @Autowired
    private ProArrangeMapper proArrangeMapper;

    @Autowired
    private ProTaskWorkunitMapper proTaskWorkunitMapper;

    @Autowired
    private ProTaskMapper proTaskMapper;

    @Resource
    private MdItemMapper mdItemMapper;
    @Autowired
    private MdWorkunitMapper mdWorkunitMapper;

    /**
     * 查询刀模版上下机
     *
     * @param toolMachinesId 刀模版上下机主键
     * @return 刀模版上下机
     */
    @Override
    public TmToolMachines selectTmToolMachinesByToolMachinesId(Long toolMachinesId) {
        return tmToolMachinesMapper.selectTmToolMachinesByToolMachinesId(toolMachinesId);
    }

    /**
     * 查询刀模版上下机列表
     *
     * @param tmToolMachines 刀模版上下机
     * @return 刀模版上下机
     */
    @Override
    public List<TmToolMachines> selectTmToolMachinesList(TmToolMachines tmToolMachines) {
        return tmToolMachinesMapper.selectTmToolMachinesList(tmToolMachines);
    }


    /**
     * 查询刀模版上下机列表
     *
     * @param tmToolMachines 刀模版上下机
     * @return 刀模版上下机
     */
    @Override
    public List<TmToolMachines> selectTmToolMachinesVoList(TmToolMachines tmToolMachines) {
        return tmToolMachinesMapper.selectTmToolMachinesVoList(tmToolMachines);
    }

    /**
     * 新增刀模版上下机
     *
     * @param tmToolMachinesList 刀模版上下机
     * @return 结果
     */
    @Override
    public int insertTmToolMachines(List<TmToolMachines> tmToolMachinesList) {
        int i = 0;
        if (CollectionUtil.isEmpty(tmToolMachinesList)) {
            log.info("传入的记录为空");
            return i;
        }

        for (TmToolMachines tmToolMachines : tmToolMachinesList) {

            // 编码如果为空则自动生成
            if (StringUtils.isEmpty(tmToolMachines.getToolMachinesCode())) {
                tmToolMachines.setToolMachinesCode(autoCodeUtil.genSerialCode(UserConstants.TOOL_MACHINES_CODE, null));
            }

            //新增主表数据
            i = i + this.insertTmToolMachines(tmToolMachines);
        }

        return i;
    }

    @Override
    public int insertTmToolMachines(TmToolMachines tmToolMachines) {
        tmToolMachines.createAction();
        tmToolMachines.setToolMachinesCode(autoCodeUtil.genSerialCode(UserConstants.TOOL_MACHINES_CODE, null));

        return tmToolMachinesMapper.insertTmToolMachines(tmToolMachines);
    }

    /**
     * 修改刀模版上下机
     *
     * @param tmToolMachines 刀模版上下机
     * @return 结果
     */
    @Override
    public int updateTmToolMachines(TmToolMachines tmToolMachines) {
        tmToolMachines.updateAction();
        return tmToolMachinesMapper.updateTmToolMachines(tmToolMachines);
    }

    /**
     * 批量删除刀模版上下机
     *
     * @param toolMachinesIds 需要删除的刀模版上下机主键
     * @return 结果
     */
    @Override
    public int deleteTmToolMachinesByToolMachinesIds(Long[] toolMachinesIds) {
        return tmToolMachinesMapper.deleteTmToolMachinesByToolMachinesIds(toolMachinesIds);
    }

    /**
     * 删除刀模版上下机信息
     *
     * @param toolMachinesId 刀模版上下机主键
     * @return 结果
     */
    @Override
    public int deleteTmToolMachinesByToolMachinesId(Long toolMachinesId) {
        return tmToolMachinesMapper.deleteTmToolMachinesByToolMachinesId(toolMachinesId);
    }

    @Transactional
    @Override
    public int updateBindStatus(List<TmToolMachines> list) {
        Integer action = list.get(0).getType();
        ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(list) || StringUtils.isEmpty(action), MessageUtils.message("pro.tool.error.error1"));

        List<Long> machinesIds = list.stream().map(TmToolMachines::getToolMachinesId).collect(Collectors.toList());
        List<TmToolMachines> dbToolMachinesList = tmToolMachinesMapper.selectListByQwV2(new QueryWrapper<TmToolMachines>().in("t1.tool_machines_id", machinesIds));

        ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(dbToolMachinesList) || dbToolMachinesList.size() < machinesIds.size(), MessageUtils.message("pro.tool.error.error2"));

        Set<String> errorBondingSet = dbToolMachinesList.stream().filter(x -> x.getType() == null || x.getToolRequestUseItemId() == null || x.getToolRequestUseId() == null).filter(x -> !Objects.equals(x.getIsExistTool(), IS_EXIST_TOOL_YES)).map(x -> x.getToolMachinesId().toString()).collect(Collectors.toSet());
        ExceptionUtil.checkTrueThrowException(CollectionUtil.isNotEmpty(errorBondingSet), MessageUtils.message("pro.tool.error.error3", errorBondingSet));

        List<String> toolCodes = dbToolMachinesList.stream().map(TmToolMachines::getToolCode).filter(StringUtils::isNotEmpty).collect(Collectors.toList());
        Set<Long> set = dbToolMachinesList.stream().map(TmToolMachines::getToolRequestUseItemId).filter(Objects::nonNull).collect(Collectors.toSet());
        List<TmTool> tmTools = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(set)) {
            tmTools = tmToolMachinesMapper.selectListToolByQw(new QueryWrapper<TmToolMachines>().in("tool_request_use_item_id", set));
            toolCodes.addAll(tmTools.stream().map(TmTool::getToolCode).filter(StringUtils::isNotEmpty).collect(Collectors.toList()));
        }

        checkTmToollIlegal(toolCodes, null);

        Map<Long, TmToolMachines> dbToolMachinesMap = dbToolMachinesList.stream().collect(Collectors.toMap(TmToolMachines::getToolMachinesId, x -> x));
        Map<Long, TmToolMachines> requestToolMachinesMap = list.stream().collect(Collectors.toMap(TmToolMachines::getToolMachinesId, x -> x));


        int i = 0;
        for (TmToolMachines tmToolMachines : list) {
            Long toolMachinesId = tmToolMachines.getToolMachinesId();
            TmToolMachines dbToolMachines = dbToolMachinesMap.get(toolMachinesId);
            ExceptionUtil.checkTrueThrowException(dbToolMachines == null, MessageUtils.message("pro.tool.error.error4", tmToolMachines.getToolCode()));
            TmToolMachines requestToolMachines = requestToolMachinesMap.get(toolMachinesId);
            if (Objects.equals(dbToolMachines.getType(), requestToolMachines.getType())) {
                ExceptionUtil.checkTrueThrowException(Objects.equals(dbToolMachines.getType(), TmToolMachineTypeEnum.DIS_MOUNT.getType()), MessageUtils.message("pro.tool.error.error5"));
                ExceptionUtil.checkTrueThrowException(Objects.equals(dbToolMachines.getType(), TmToolMachineTypeEnum.MOUNT.getType()), MessageUtils.message("pro.tool.error.error6"));
            }


            TmToolMachines updated = dbToolMachinesMap.get(toolMachinesId);
            //上机修改状态，上机时间改为最新；下机修改状态，下机时间改为最新
            if (Objects.equals(TmToolMachineTypeEnum.MOUNT.getType(), action)) {
                updated.setType(TmToolMachineTypeEnum.MOUNT.getType());
                updated.setUpDate(new Date());
            } else if (Objects.equals(TmToolMachineTypeEnum.DIS_MOUNT.getType(), action)) {
                updated.setType(TmToolMachineTypeEnum.DIS_MOUNT.getType());
                updated.setDownDate(new Date());
            }

            this.updateTmToolMachines(updated);
            i++;
        }
        return i;
    }

    @Override
    public List<TmToolMachines> selectListByQw(QueryWrapper<TmToolMachines> queryWrapper) {
        return tmToolMachinesMapper.selectListByQw(queryWrapper);
    }

    @Override
    public List<TmToolMachines> selectListJoinUseItemByQw(QueryWrapper<TmToolMachines> queryWrapper) {
        return tmToolMachinesMapper.selectListJoinUseItemByQw(queryWrapper);
    }

    // 报工满足条件下架刀模版具

    @Override
    public void feedbackToolDismount(ProTaskWorkunit taskWorkunit) {
        // 报工数量相等 自动下机
        if (taskWorkunit.getQuantityProduced().subtract(taskWorkunit.getQuantity()).doubleValue() >= 0) {
            QueryWrapper<TmToolMachines> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("type", TmToolMachineTypeEnum.MOUNT.getType());
            queryWrapper.eq("task_workunit_id", taskWorkunit.getTaskWorkunitId());
            List<TmToolMachines> tmToolMachinesList = this.selectListByQw(queryWrapper);

            for (TmToolMachines tmToolMachines : tmToolMachinesList) {
                tmToolMachines.setType(TmToolMachineTypeEnum.DIS_MOUNT.getType());
                this.updateTmToolMachines(tmToolMachines);
            }
        }

    }


    // 工单完结下架刀模版具
    @Override
    public void taskComplateToolDismount(ProTaskWorkunit proTaskWorkunit) {
        if (Objects.equals(proTaskWorkunit.getStatus(), TaskWorkunitStatusEnum.FINISHED.getStatus())) {
            QueryWrapper<TmToolMachines> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("type", TmToolMachineTypeEnum.MOUNT.getType());
            queryWrapper.eq("task_workunit_id", proTaskWorkunit.getTaskWorkunitId());
            List<TmToolMachines> tmToolMachinesList = this.selectListByQw(queryWrapper);
            for (TmToolMachines tmToolMachines : tmToolMachinesList) {
                tmToolMachines.setType(TmToolMachineTypeEnum.DIS_MOUNT.getType());
                this.updateTmToolMachines(tmToolMachines);
            }
        }
    }


    private TmToolMachineCheckEnum checkProcessToolMount(List<TmToolMachines> tmToolMachinesList, Map<Long, Integer> neededBindToolMap) {
        // 创建的记录不够
        List<TmToolMachines> machinesBondingList = tmToolMachinesList.stream().filter(x -> x.getToolRequestUseItemId() != null && x.getItemId() != null).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(machinesBondingList)) {
//            return TmToolMachineCheckEnum.ERROR_02;
            return TmToolMachineCheckEnum.ERROR_04;
        }

        // 已经绑定刀具的记录为空
        Map<Long, List<TmToolMachines>> tmToolBondMap = machinesBondingList.stream().collect(Collectors.groupingBy(TmToolMachines::getItemId));


        // 已绑定数刀模板记录不够小于必须需要的刀具
        for (Map.Entry<Long, List<TmToolMachines>> entry : tmToolBondMap.entrySet()) {
            List<TmToolMachines> value = entry.getValue();
            Integer i = DataUtil.getNormalData(neededBindToolMap.get(entry.getKey()));
            if (value.size() != i) {
                return TmToolMachineCheckEnum.ERROR_04;
            }
        }


        // 已上机的刀具
        Map<Long, List<TmToolMachines>> tmToolMountMap = machinesBondingList.stream()
                .filter(x -> Objects.equals(x.getType(), TmToolMachineTypeEnum.MOUNT.getType()))
                .collect(Collectors.groupingBy(TmToolMachines::getItemId));
        if (CollectionUtil.isEmpty(tmToolBondMap)) {
            return TmToolMachineCheckEnum.ERROR_04;
        }


        Map<Long, List<TmToolMachines>> tmToolMachinesMap = tmToolMachinesList.stream().collect(Collectors.groupingBy(TmToolMachines::getItemId));
        for (Map.Entry<Long, List<TmToolMachines>> entry : tmToolMachinesMap.entrySet()) {
            Long key = entry.getKey();
            List<TmToolMachines> value = entry.getValue();
            if (value.size() > 0
                    && CollectionUtil.isEmpty(tmToolMountMap)
            ) {
                return TmToolMachineCheckEnum.ERROR_04;
            }

            List<TmToolMachines> machinesList = tmToolMountMap.get(key);


            if (value.size() != machinesList.size()
                    || CollectionUtil.isEmpty(machinesList)
            ) {
                return TmToolMachineCheckEnum.ERROR_04;
            }
        }
        return TmToolMachineCheckEnum.NOMAL_00;

    }


    // 检查刀模板具
    @Override
    public TmToolMachineCheckEnum checkWhetherTheToolTemplateIsSatisfied(Long taskWorkunitId) {
        // 检查是否需要绑定刀模版具
        Map<Long, Integer> neededBindToolMap = proWorkOrderProcessToolService.selectRequiredToolForWorkunitTask(taskWorkunitId);
        List<ProWorkOrderProcess> proWorkOrderProcesses = proWorkOrderProcessMapper.selectProcessIsExistToolByTwId(taskWorkunitId);

        if (CollectionUtil.isEmpty(neededBindToolMap) && CollectionUtil.isEmpty(proWorkOrderProcesses)) {
            // 无需绑定刀模板具
            return TmToolMachineCheckEnum.ERROR_06;
        }
        List<TmToolMachines> tmToolMachinesList = tmToolMachinesMapper.selectListByQw(new QueryWrapper<TmToolMachines>().eq("t1.task_workunit_id", taskWorkunitId));

        if (CollectionUtil.isNotEmpty(neededBindToolMap)) {
            // 刀模板记录未创建
            if (CollectionUtil.isEmpty(tmToolMachinesList)) {
                return TmToolMachineCheckEnum.ERROR_01;
            }

            return checkProcessToolMount(tmToolMachinesList.stream().filter(x -> x.getIsExistTool() != IS_EXIST_TOOL_YES).collect(Collectors.toList()), neededBindToolMap);
        }

        if (CollectionUtil.isEmpty(tmToolMachinesList)) {
            return TmToolMachineCheckEnum.ERROR_04;
        }

        List<TmToolMachines> tmToolMachines = tmToolMachinesList.stream()
                .filter(x -> !Objects.equals(x.getType(), TmToolMachineTypeEnum.MOUNT.getType())).collect(Collectors.toList());
        return CollectionUtil.isNotEmpty(tmToolMachines) ? TmToolMachineCheckEnum.ERROR_04 : TmToolMachineCheckEnum.NOMAL_00;


        // 创建了并且全部上机 
    }


    @Override
    public List<MdItemVo> selectUpTmToolRequestList(MdWorkunitVo mdWorkunit) {
        mdWorkunit.setType(1);
        return tmToolMachinesMapper.selectUpTmToolRequestList(mdWorkunit);
    }

    @Override
    public List<TmToolMachines> getRecordsByProcessIdAndArrangeCode(TmToolMachines tmToolMachines) {
        return tmToolMachinesMapper.selectTmToolMachinesVoList(tmToolMachines);
    }

    @Override
    public List<TmToolMachines> insertObj(Long taskWorkunitId) {
        List<ProTaskWorkunit> proTaskWorkunits = proTaskWorkunitMapper.selectListByQw(new QueryWrapper<ProTaskWorkunit>().eq("task_workunit_id", taskWorkunitId));
        ExceptionUtil.checkTrueThrowException(proTaskWorkunits.size() > 1, MessageUtils.message("pro.tool.error.error10"));


        TmToolMachineCheckEnum b = this.checkWhetherTheToolTemplateIsSatisfied(taskWorkunitId);
        if (!Objects.equals(b.getStatus(), TmToolMachineCheckEnum.ERROR_01.getStatus())) {
            log.info(b.getMsg() + ",taskWorkunitId:" + taskWorkunitId);
            return new ArrayList<>();
        }


        ProTaskWorkunit proTaskWorkunit = proTaskWorkunits.get(0);
        List<ProTask> proTasks = proTaskMapper.selectListJoinByQw(new QueryWrapper<ProTask>().eq("t1.task_id", proTaskWorkunit.getTaskId()));
        ProTask proTask = proTasks.get(0);

        List<MdWorkunit> mdWorkunits = mdWorkunitMapper.selectListByQw(new QueryWrapper<MdWorkunit>().eq("workunit_id", proTaskWorkunit.getWorkunitId()));
        MdWorkunit mdWorkunit = mdWorkunits.get(0);

        ProWorkorder proWorkorder = proTaskWorkunitMapper.selectProWorkorderByTaskWorkunitId(taskWorkunitId);
        String arrangeCode = proWorkorder.getArrangeCode();
        List<ProArrange> proArranges = proArrangeMapper.selectListByQw(new QueryWrapper<ProArrange>().eq("arrange_code", arrangeCode));
        ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(proArranges), MessageUtils.message("pro.tool.error.error11"));

        Set<Long> workorderIds = proArranges.stream().map(ProArrange::getWorkorderId).collect(Collectors.toSet());
        QueryWrapper<ProWorkOrderProcessTool> processToolQueryWrapper = new QueryWrapper<>();
        processToolQueryWrapper.in("t1.work_order_id", workorderIds);
        processToolQueryWrapper.in("t3.process_id", proTask.getProcessId());
        List<ProWorkOrderProcessTool> processTools = proWorkOrderProcessToolMapper.selectListByQw(processToolQueryWrapper);
        List<TmToolMachines> tmToolMachinesList = new ArrayList<>();

        if (CollectionUtil.isNotEmpty(processTools)) {
            Map<Long, Optional<ProWorkOrderProcessTool>> processToolls = processTools.stream().filter(x -> x.getQuantity() != null
                    && x.getQuantity().doubleValue() > 0).collect(Collectors.groupingBy(ProWorkOrderProcessTool::getToolId, Collectors.maxBy(Comparator.comparingDouble(x -> x.getQuantity().doubleValue()))));


            Set<Long> workorderProcessIds = processToolls.values().stream().filter(x -> x.get() != null).map(x -> x.get().getWorkorderProcessId()).collect(Collectors.toSet());
            List<ProWorkOrderProcess> proWorkOrderProcesses = proWorkOrderProcessService.selectListByQw(new QueryWrapper<ProWorkOrderProcess>().in("t1.workorder_process_id", workorderProcessIds));
            Map<Long, Long> processMap = proWorkOrderProcesses.stream().collect(Collectors.toMap(ProWorkOrderProcess::getWorkorderProcessId, ProWorkOrderProcess::getProcessId));
            for (Map.Entry<Long, Optional<ProWorkOrderProcessTool>> entrySet : processToolls.entrySet()) {
                Optional<ProWorkOrderProcessTool> value = entrySet.getValue();
                if (value.isPresent()) {
                    ProWorkOrderProcessTool proWorkOrderProcessTool = value.get();
                    BigDecimal quantity = proWorkOrderProcessTool.getQuantity();
                    Long processId = processMap.get(proWorkOrderProcessTool.getWorkorderProcessId());
                    long l = quantity.longValue();
                    for (long l1 = 0; l1 < l; l1++) {
                        TmToolMachines tmToolMachines = new TmToolMachines();
                        //开始封装数据进行新增
                        tmToolMachines.setItemId(proWorkOrderProcessTool.getToolId());
                        tmToolMachines.setWorkunitId(proTaskWorkunit.getWorkunitId());
                        tmToolMachines.setWorkunitName(mdWorkunit.getWorkunitName());
                        tmToolMachines.setWorkunitCode(mdWorkunit.getWorkunitCode());
                        tmToolMachines.setTaskId(proTaskWorkunit.getTaskId());
                        tmToolMachines.setTaskCode(proTask.getTaskCode());
                        tmToolMachines.setTaskName(proTask.getTaskName());
                        tmToolMachines.setTaskWorkunitId(taskWorkunitId);
                        tmToolMachines.setArrangeCode(arrangeCode);
                        tmToolMachines.setProcessId(processId);
                        tmToolMachines.setWorkorderId(proWorkOrderProcessTool.getWorkOrderId());
                        tmToolMachines.setUpDate(null);//默认当前上机时间
                        tmToolMachines.setDownDate(null);
                        tmToolMachinesList.add(tmToolMachines);
                    }
                }
            }
        }

        return tmToolMachinesList;
    }

    @Override
    public void insertObj(TmToolMachines tmToolMachines) {
        this.insertTmToolMachines(insertObj(tmToolMachines.getTaskWorkunitId()));
    }

    @Override
    public Integer bindTool(String toolCode, Integer type, TmToolMachines tmToolMachines, String isExistTool) {
        List<TmTool> tmTools = tmToolMapper.selectListByQw(new QueryWrapper<TmTool>().eq("tool_code", toolCode));
        ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(tmTools), MessageUtils.message("pro.tool.error.error12"));

        TmToolRequestUseItem tmToolRequestUseItem = null;
        if (isExistTool == IS_EXIST_TOOL_NO) {
            List<TmToolRequestUseItem> tmToolRequestUseItems = tmToolRequestUseItemMapper.selecListByQw(new QueryWrapper<TmToolRequestUseItem>().eq("t2.tool_code", toolCode));
            ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(tmToolRequestUseItems), MessageUtils.message("pro.tool.error.error13"));
            tmToolRequestUseItem = tmToolRequestUseItems.get(0);
        }
        return bindTool(tmToolMachines, tmToolRequestUseItem, type);
    }


    @Override
    public int bindTool(TmToolMachines tmToolMachines, TmToolRequestUseItem tmToolRequestUseItem, Integer type) {
        int count = 0;
        if (null != type) {
            //上机修改状态，上机时间改为最新；下机修改状态，下机时间改为最新
            if (Objects.equals(TmToolMachineTypeEnum.MOUNT.getType(), type)) {
                tmToolMachines.setType(TmToolMachineTypeEnum.MOUNT.getType());
                tmToolMachines.setUpDate(new Date());
            } else if (Objects.equals(TmToolMachineTypeEnum.DIS_MOUNT.getType(), type)) {
                tmToolMachines.setType(TmToolMachineTypeEnum.DIS_MOUNT.getType());
                tmToolMachines.setDownDate(new Date());
            } else if (Objects.equals(TmToolMachineTypeEnum.INIT.getType(), type)) {
                tmToolMachines.setType(TmToolMachineTypeEnum.INIT.getType());
                tmToolMachines.setUpDate(new Date());
                tmToolMachines.setDownDate(null);
            }

            if (tmToolRequestUseItem != null) {
                tmToolMachines.setToolRequestUseId(tmToolRequestUseItem.getToolRequestUseId());
                tmToolMachines.setToolRequestUseItemId(tmToolRequestUseItem.getToolRequestUseItemId());
            }

            count = this.updateTmToolMachines(tmToolMachines);
        }
        return count;

    }

    private void checkTmToollIlegal(List<String> toolCodes, String sapItemCode) {
        Set<String> collect = toolCodes.stream().filter(Objects::nonNull).collect(Collectors.toSet());
        ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(collect), MessageUtils.message("pro.tool.error.error14"));
        for (String toolCode : collect) {
            List<TmTool> tmTools = tmToolMapper.selectListByQw(new QueryWrapper<TmTool>().eq("tool_code", toolCode));
            ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(tmTools), MessageUtils.message("pro.tool.error.error15",toolCode,sapItemCode));
            ExceptionUtil.checkTrueThrowException(tmTools.size() > 1, MessageUtils.message("pro.tool.error.error16",toolCode,sapItemCode));
            TmTool tmTool = tmTools.get(0);
            ExceptionUtil.checkTrueThrowException(Objects.equals(tmTool.getStatus(), TmToolStatusEnum.SCRAP.getStatus()), MessageUtils.message("pro.tool.error.error17",toolCode,sapItemCode));
            ExceptionUtil.checkTrueThrowException(Objects.equals(tmTool.getStatus(), TmToolStatusEnum.STORE.getStatus()), MessageUtils.message("pro.tool.error.error18",toolCode,sapItemCode));
        }

        if (StringUtils.isNotEmpty(sapItemCode)) {

            List<MdItem> mdItems1 = mdItemMapper.selectListByQw(new QueryWrapper<MdItem>().eq("sap_item_code", sapItemCode));
            ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(mdItems1), MessageUtils.message("pro.tool.error.error18",JSON.toJSONString(toolCodes), sapItemCode));

        }
    }

    @Override
    public Integer checkIsExistToolWindow(TmToolMachines machines) {
        String sn = machines.getSn();
        Long taskWorkunitId = machines.getTaskWorkunitId();
//        Integer type = machines.getType();

        ExceptionUtil.checkTrueThrowException(sn == null || "".equals(sn) || !sn.contains("-"), MessageUtils.message("pro.tool.error.error26"));
        String[] snList = sn.split("-");
        String toolCode = snList[1];
        String sapItemCode = snList[0];
        checkTmToollIlegal(Collections.singletonList(toolCode), sapItemCode);


        // 已经在使用中的tool_code
        QueryWrapper<TmToolMachines> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("tt.tool_code", toolCode);
        queryWrapper.eq("mi.sap_item_code", sapItemCode);
        List<TmToolMachines> tmToolMachinesList = tmToolMachinesMapper.selectListByQw(queryWrapper);
        if (CollectionUtil.isNotEmpty(tmToolMachinesList)) {
            // 查看本单元是否有上机记录,且不等于已下机
            List<TmToolMachines> collect = tmToolMachinesList.stream().filter(x -> x.getToolRequestUseItemId() != null
                    && Objects.equals(x.getTaskWorkunitId(), taskWorkunitId)
                    && Objects.equals(x.getToolCode(), toolCode)).collect(Collectors.toList());
            return CollectionUtil.isNotEmpty(collect) ? 0 : 1;
        }
        return 1;
    }

    @Override
    public Integer scanCode(TmToolMachines machines) {
//        System.out.println(JSONObject.toJSONString("扫码请求参数: " + machines));
        String sn = machines.getSn();
        Long taskWorkunitId = machines.getTaskWorkunitId();
        Integer type = machines.getType();

        ExceptionUtil.checkTrueThrowException(sn == null || "".equals(sn) || !sn.contains("-"), MessageUtils.message("pro.tool.error.error26"));
        String[] snList = sn.split("-");
        String toolCode = snList[1];
        String sapItemCode = snList[0];
        checkTmToollIlegal(Collections.singletonList(toolCode), sapItemCode);

        List<TmToolMachines> toolMachinesList = new ArrayList<>();


        QueryWrapper<TmToolMachines> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("tt.tool_code", toolCode);
        queryWrapper.eq("mi.sap_item_code", sapItemCode);
        queryWrapper.eq("t1.task_workunit_id", taskWorkunitId);
        List<TmToolMachines> tmToolMachinesList = tmToolMachinesMapper.selectListByQw(queryWrapper);

        switch (DataUtil.getNormalData(machines.getIsExistTool(), IS_EXIST_TOOL_NO)) {
            case IS_EXIST_TOOL_NO:

//                // 已经在使用中的tool_code
//
                if (Objects.equals(TmToolMachineTypeEnum.MOUNT.getType(), type) && CollectionUtil.isNotEmpty(tmToolMachinesList)) {
                    // 刀模版code没有找到上机记录
                    boolean b = tmToolMachinesList.stream().anyMatch(x -> x.getToolRequestUseItemId() != null
                            && Objects.equals(TmToolMachineTypeEnum.MOUNT.getType(), x.getType()));
                    ExceptionUtil.checkTrueThrowException(b, MessageUtils.message("pro.tool.error.error9"));

                    // 查看本单元是否有上机记录,且不等于已下机
                    List<TmToolMachines> collect = tmToolMachinesList.stream().filter(x -> x.getToolRequestUseItemId() != null
                            && Objects.equals(x.getTaskWorkunitId(), taskWorkunitId)
                            && Objects.equals(x.getToolCode(), toolCode)
                            && (Objects.equals(TmToolMachineTypeEnum.DIS_MOUNT.getType(), x.getType()) || Objects.equals(TmToolMachineTypeEnum.INIT.getType(), x.getType()))).collect(Collectors.toList());

                    if (CollectionUtil.isNotEmpty(collect)) {
                        return bindTool(toolCode, type, collect.get(0), IS_EXIST_TOOL_NO);
                    }
                }


                if (Objects.equals(TmToolMachineTypeEnum.DIS_MOUNT.getType(), type)) {
                    QueryWrapper<TmToolMachines> qw = new QueryWrapper<>();
                    qw.eq("t1.tool_code", toolCode);
                    qw.eq("t2.sap_item_code", sapItemCode);
                    tmToolMachinesList.addAll(tmToolMachinesMapper.selectListByQwV2(qw));

                    ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(tmToolMachinesList), MessageUtils.message("pro.tool.error.error20"));
                    toolMachinesList = tmToolMachinesList.stream().filter(x ->
//                            x -> x.getToolRequestUseItemId() != null
                                    Objects.equals(TmToolMachineTypeEnum.MOUNT.getType(), x.getType())
                                            && Objects.equals(x.getTaskWorkunitId(), taskWorkunitId)
                    ).collect(Collectors.toList());
                    ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(toolMachinesList), MessageUtils.message("pro.tool.error.error20"));
                    return bindTool(toolCode, type, toolMachinesList.get(0), IS_EXIST_TOOL_NO);
                }


                List<TmToolMachines> toolMachines = tmToolMachinesMapper.selectListByQw(new QueryWrapper<TmToolMachines>().eq("t1.task_workunit_id", taskWorkunitId).eq("mi.sap_item_code", sapItemCode));
                ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(toolMachines), MessageUtils.message("pro.tool.error.error21"));

                toolMachinesList = toolMachines.stream().filter(x -> x.getToolRequestUseItemId() == null).collect(Collectors.toList());
                if (CollectionUtil.isEmpty(toolMachinesList)) {
                    if (Objects.equals(TmToolMachineTypeEnum.MOUNT.getType(), type)) {
                        toolMachinesList = toolMachines.stream().filter(
                                x -> x.getToolRequestUseItemId() != null
                                        && !Objects.equals(TmToolMachineTypeEnum.MOUNT.getType(), x.getType())
                        ).collect(Collectors.toList());
                    } else if (Objects.equals(TmToolMachineTypeEnum.DIS_MOUNT.getType(), type)) {
                        toolMachinesList = toolMachines.stream().filter(
                                x -> x.getToolRequestUseItemId() != null
                                        && Objects.equals(TmToolMachineTypeEnum.MOUNT.getType(), x.getType())
                        ).collect(Collectors.toList());
                    }
                }

                ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(toolMachinesList), MessageUtils.message("pro.tool.error.error21"));
                return bindTool(toolCode, type, toolMachinesList.get(0), IS_EXIST_TOOL_NO);
            case IS_EXIST_TOOL_YES:


                List<ProWorkOrderProcessTool> processTools = proWorkOrderProcessToolMapper.selectRequiredToolByTaskWorkunitId(taskWorkunitId);
                TmToolMachines tmToolMachines = machines.deepCopyObj();


                if (CollectionUtil.isEmpty(processTools)) {
                    QueryWrapper<TmToolMachines> qw = new QueryWrapper<>();
                    qw.eq("t1.tool_code", toolCode);
                    qw.eq("t2.sap_item_code", sapItemCode);
                    List<TmToolMachines> isExsitToolMachines = tmToolMachinesMapper.selectListByQwV2(qw);
                    if (Objects.equals(TmToolMachineTypeEnum.MOUNT.getType(), type)) {
                        if (CollectionUtil.isNotEmpty(isExsitToolMachines)) {

                            List<TmToolMachines> tmToolMachines1 = isExsitToolMachines.stream().filter(x -> Objects.equals(x.getType(), TmToolMachineTypeEnum.MOUNT.getType())).collect(Collectors.toList());
                            ExceptionUtil.checkTrueThrowException(CollectionUtil.isNotEmpty(tmToolMachines1), MessageUtils.message("pro.tool.error.error6"));

                            tmToolMachines1 = isExsitToolMachines.stream().filter(x -> (Objects.equals(x.getType(), TmToolMachineTypeEnum.DIS_MOUNT.getType()) || Objects.equals(x.getType(), TmToolMachineTypeEnum.INIT.getType())) && Objects.equals(x.getTaskWorkunitId(), taskWorkunitId)).collect(Collectors.toList());
                            if (CollectionUtil.isNotEmpty(tmToolMachines1)) {
                                return bindTool(toolCode, type, tmToolMachines1.get(0), IS_EXIST_TOOL_YES);
                            }
                        }


                        ProTaskWorkunit proTaskWorkunit = proTaskWorkunitMapper.selectProTaskWorkunitByTaskWorkunitId(taskWorkunitId);
                        ProTask proTask = proTaskMapper.selectProTaskByTaskId(proTaskWorkunit.getTaskId());
                        List<MdItem> mdItems = mdItemMapper.selectListByQw(new QueryWrapper<MdItem>().eq("sap_item_code", sapItemCode));
                        List<TmTool> tmTools = tmToolMapper.selectListByQw(new QueryWrapper<TmTool>().eq("tool_code", toolCode));
                        List<ProWorkOrderProcess> proWorkOrderProcesses = proWorkOrderProcessMapper.selectProcessIsExistToolByTwId(taskWorkunitId);
                        ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(proWorkOrderProcesses), MessageUtils.message("md.process.error.not.exist"));
                        //开始封装数据进行新增
                        if (CollectionUtil.isNotEmpty(mdItems)) {
                            tmToolMachines.setItemId(mdItems.get(0).getItemId());
                        }

                        if (CollectionUtil.isNotEmpty(tmTools)) {
                            TmTool tmTool = tmTools.get(0);
                            tmToolMachines.setToolId(tmTool.getToolId());
                            tmToolMachines.setToolCode(tmTool.getToolCode());
                            tmToolMachines.setToolName(tmTool.getToolName());
                        }

                        tmToolMachines.setIsExistTool(IS_EXIST_TOOL_YES);
                        tmToolMachines.setWorkunitId(proTaskWorkunit.getWorkunitId());
                        tmToolMachines.setWorkunitName(proTaskWorkunit.getWorkunitName());
                        tmToolMachines.setWorkunitCode(proTaskWorkunit.getWorkunitCode());
                        tmToolMachines.setTaskId(proTask.getTaskId());
                        tmToolMachines.setTaskCode(proTask.getTaskCode());
                        tmToolMachines.setTaskName(proTask.getTaskName());
                        tmToolMachines.setTaskWorkunitId(taskWorkunitId);
                        tmToolMachines.setArrangeCode(proTask.getArrangeCode());
                        tmToolMachines.setProcessId(proTask.getProcessId());
                        tmToolMachines.setWorkorderId(proWorkOrderProcesses.get(0).getWorkorderId());
                        tmToolMachines.setType(TmToolMachineTypeEnum.INIT.getType());
                        tmToolMachines.setUpDate(null);//默认当前上机时间
                        tmToolMachines.setDownDate(null);
                        this.insertTmToolMachines(tmToolMachines);
                    } else {
                        QueryWrapper<TmToolMachines> qw2 = new QueryWrapper<>();
                        qw2.eq("t1.tool_code", toolCode);
                        qw2.eq("t2.sap_item_code", sapItemCode);
                        qw2.eq("t1.task_workunit_id", taskWorkunitId);
                        qw2.eq("t1.type", TmToolMachineTypeEnum.MOUNT.getType());
                        List<TmToolMachines> tmToolMachinesList1 = tmToolMachinesMapper.selectListByQwV2(qw2);
                        ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(tmToolMachinesList1), MessageUtils.message("pro.tool.error.error21"));
                        tmToolMachines = tmToolMachinesList1.get(0);
                    }
                    return bindTool(toolCode, type, tmToolMachines, IS_EXIST_TOOL_YES);
                } else {

                    List<MdItem> mdItems1 = mdItemMapper.selectListByQw(new QueryWrapper<MdItem>().eq("sap_item_code", sapItemCode));

                    List<Long> processToolItemIds = processTools.stream().map(ProWorkOrderProcessTool::getToolId).filter(x -> Objects.equals(x, mdItems1.get(0).getItemId())).distinct().collect(Collectors.toList());
                    ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(processToolItemIds), MessageUtils.message("pro.tool.error.error22"));


                    List<TmToolRequestUseItem> tmToolRequestUseItems = tmToolRequestUseItemMapper.selectListByQw(new QueryWrapper<TmToolRequestUseItem>().eq("tt.tool_code", toolCode));
                    ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(tmToolRequestUseItems), MessageUtils.message("pro.tool.error.error23"));

                    // 已经在使用中的tool_code
                    if (Objects.equals(TmToolMachineTypeEnum.MOUNT.getType(), type) && CollectionUtil.isNotEmpty(tmToolMachinesList)) {
                        // 刀模版code没有找到上机记录
                        ExceptionUtil.checkTrueThrowException(tmToolMachinesList.stream().anyMatch(x ->
                                x.getToolRequestUseItemId() != null
                                        && Objects.equals(TmToolMachineTypeEnum.MOUNT.getType(), x.getType())), MessageUtils.message("pro.tool.error.error9"));

                        // 查看本单元是否有上机记录,且不等于已下机
                        List<TmToolMachines> collect = tmToolMachinesList.stream().filter(x -> x.getToolRequestUseItemId() != null
                                && Objects.equals(x.getTaskWorkunitId(), taskWorkunitId)
                                && Objects.equals(x.getToolCode(), toolCode)
                                && (Objects.equals(TmToolMachineTypeEnum.DIS_MOUNT.getType(), x.getType()) || Objects.equals(TmToolMachineTypeEnum.INIT.getType(), x.getType()))).collect(Collectors.toList());

                        if (CollectionUtil.isNotEmpty(collect)) {
                            return bindTool(toolCode, type, collect.get(0), IS_EXIST_TOOL_NO);
                        }

                    }


                    List<TmToolMachines> toolMachines3 = tmToolMachinesMapper.selectListByQwV2(new QueryWrapper<TmToolMachines>().eq("t1.task_workunit_id", taskWorkunitId).eq("t2.sap_item_code", sapItemCode));
                    toolMachinesList = toolMachines3.stream().filter(x -> x.getToolRequestUseItemId() == null).collect(Collectors.toList());
                    if (CollectionUtil.isEmpty(toolMachinesList)) {
                        if (Objects.equals(TmToolMachineTypeEnum.MOUNT.getType(), type)) {
                            toolMachinesList = toolMachines3.stream().filter(
                                    x -> x.getToolRequestUseItemId() != null
                                            && !Objects.equals(TmToolMachineTypeEnum.MOUNT.getType(), x.getType())
                            ).collect(Collectors.toList());
                        }
                    }
                    ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(toolMachinesList), MessageUtils.message("pro.tool.error.error8"));
                    tmToolMachines = toolMachinesList.get(0);
                    if (CollectionUtil.isEmpty(toolMachinesList)) {
                        createTmToolMachines(tmToolMachines, taskWorkunitId, toolCode, sapItemCode);
                    }
                    return bindTool(toolCode, type, tmToolMachines, IS_EXIST_TOOL_NO);

                }

            default:
                break;
        }
        return 0;

    }

    private void createTmToolMachines(TmToolMachines tmToolMachines, Long taskWorkunitId, String sapItemCode, String toolCode) {

        ProTaskWorkunit proTaskWorkunit = proTaskWorkunitMapper.selectProTaskWorkunitByTaskWorkunitId(taskWorkunitId);
        ProTask proTask = proTaskMapper.selectProTaskByTaskId(proTaskWorkunit.getTaskId());
        List<MdItem> mdItems = mdItemMapper.selectListByQw(new QueryWrapper<MdItem>().eq("sap_item_code", sapItemCode));
        List<TmTool> tmTools = tmToolMapper.selectListByQw(new QueryWrapper<TmTool>().eq("tool_code", toolCode));
        List<ProWorkOrderProcess> proWorkOrderProcesses = proWorkOrderProcessMapper.selectProcessIsExistToolByTwId(taskWorkunitId);
        ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(proWorkOrderProcesses), MessageUtils.message("md.process.error.not.exist"));
        //开始封装数据进行新增
        if (CollectionUtil.isNotEmpty(mdItems)) {
            tmToolMachines.setItemId(mdItems.get(0).getItemId());
        }

        if (CollectionUtil.isNotEmpty(tmTools)) {
            TmTool tmTool = tmTools.get(0);
            tmToolMachines.setToolId(tmTool.getToolId());
            tmToolMachines.setToolCode(tmTool.getToolCode());
            tmToolMachines.setToolName(tmTool.getToolName());
        }

        tmToolMachines.setIsExistTool(IS_EXIST_TOOL_YES);
        tmToolMachines.setWorkunitId(proTaskWorkunit.getWorkunitId());
        tmToolMachines.setWorkunitName(proTaskWorkunit.getWorkunitName());
        tmToolMachines.setWorkunitCode(proTaskWorkunit.getWorkunitCode());
        tmToolMachines.setTaskId(proTask.getTaskId());
        tmToolMachines.setTaskCode(proTask.getTaskCode());
        tmToolMachines.setTaskName(proTask.getTaskName());
        tmToolMachines.setTaskWorkunitId(taskWorkunitId);
        tmToolMachines.setArrangeCode(proTask.getArrangeCode());
        tmToolMachines.setProcessId(proTask.getProcessId());
        tmToolMachines.setWorkorderId(proWorkOrderProcesses.get(0).getWorkorderId());
        tmToolMachines.setType(TmToolMachineTypeEnum.INIT.getType());
        tmToolMachines.setUpDate(null);//默认当前上机时间
        tmToolMachines.setDownDate(null);
        this.insertTmToolMachines(tmToolMachines);

    }
}
