package com.bonus.material.basic.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.bonus.common.biz.config.BackstageApplication;
import com.bonus.common.biz.config.DateTimeHelper;
import com.bonus.common.biz.config.QrCodeUtils;
import com.bonus.common.biz.constant.MaterialConstants;
import com.bonus.common.biz.domain.purchase.PurchaseDto;
import com.bonus.common.biz.enums.*;
import com.bonus.common.core.utils.DateUtils;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.material.basic.domain.BmQrBoxInfo;
import com.bonus.material.basic.domain.dto.BoxBindWarehouseDto;
import com.bonus.material.basic.domain.vo.BoxInfoBindVo;
import com.bonus.material.basic.mapper.BmQrBoxMapper;
import com.bonus.material.basic.service.BmQrBoxService;
import com.bonus.material.ma.domain.Machine;
import com.bonus.material.ma.domain.Type;
import com.bonus.material.ma.domain.vo.MachineVo;
import com.bonus.material.ma.mapper.MachineMapper;
import com.bonus.material.ma.service.ITypeService;
import com.bonus.material.purchase.config.RemoteConfig;
import com.bonus.material.purchase.domain.PurchaseCheckDetails;
import com.bonus.material.purchase.domain.vo.PurchaseVo;
import com.bonus.material.purchase.mapper.PurchaseBindMapper;
import com.bonus.material.purchase.mapper.PurchaseStorageMapper;
import com.bonus.material.task.mapper.TmTaskMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.bonus.common.biz.constant.MaterialConstants.QR_BOX_PREFIX;

/**
 * @author  ma_sh
 * @create 2024/12/10 17:26
 */
@Service
@Slf4j
public class BmQrBoxServiceImpl implements BmQrBoxService {

    @Resource
    private BmQrBoxMapper bmQrBoxMapper;

    @Resource
    private MachineMapper machineMapper;

    @Resource
    private PurchaseBindMapper purchaseBindMapper;

    @Resource
    private PurchaseStorageMapper purchaseStorageMapper;

    @Resource
    private TmTaskMapper tmTaskMapper;

    @Resource
    private RemoteConfig remoteConfig;

    @Resource
    private ITypeService typeService;

    /**
     * 查询二维码标准箱管理列表
     */
    @Override
    public List<BmQrBoxInfo> selectBmQrBoxInfoList(BmQrBoxInfo bmQrBoxInfo) {
        if (null != bmQrBoxInfo.getStatus()) {
            bmQrBoxInfo.setStatusList(Arrays.asList(bmQrBoxInfo.getStatus().split(",")));
        }
        List<BmQrBoxInfo> list = bmQrBoxMapper.find(bmQrBoxInfo);
        if (CollectionUtil.isNotEmpty(list)) {
            if (CollectionUtil.isNotEmpty(bmQrBoxInfo.getStatusList())) {
                if(bmQrBoxInfo.getStatusList().contains("2") && bmQrBoxInfo.getStatusList().contains("5")) {
                    // 将list中状态为2和5并且devNum大于0的数据过滤出来
                    list = list.stream()
                            // 先判空list中的bmQrBoxInfo1和它的statusList，避免空指针
                            .filter(bmQrBoxInfo1 -> bmQrBoxInfo1 != null
                                    && bmQrBoxInfo1.getStatus() != null
                                    && bmQrBoxInfo1.getDevNum() > 0)
                            .filter(bmQrBoxInfo1 -> "2".equals(bmQrBoxInfo1.getStatus())
                                    || "5".equals(bmQrBoxInfo1.getStatus()))
                            .collect(Collectors.toList());
                }
            }
        }
        return list;
    }

    /**
     * 新增二维码标准箱管理
     */
    @Override
    public AjaxResult insertBmQrcodeInfo(BmQrBoxInfo bmQrBoxInfo) {
        // 查询当月标准箱数
        int thisMonthMaxOrder = bmQrBoxMapper.getMonthMaxOrderByDate(DateUtils.getCurrentYear(), DateUtils.getCurrentMonth());
        String code = null;
        List<BmQrBoxInfo> boxInfos;
        int retryCount = 0;
        int maxRetry = 10; // 设置最大重试次数，防止无限循环
        do {
            // 生成编码，每次重试递增序号
            code = genderTaskCode(thisMonthMaxOrder + retryCount);
            bmQrBoxInfo.setBoxCode(code);
            // 检查编码是否已存在
            boxInfos = bmQrBoxMapper.findBoxInfoByKey(bmQrBoxInfo);
            retryCount++;

            // 如果达到最大重试次数仍存在重复，抛出异常
            if (retryCount > maxRetry) {
                throw new RuntimeException("超过最大重试次数，无法生成唯一的二维码箱号");
            }
        } while (CollectionUtils.isNotEmpty(boxInfos));
        bmQrBoxInfo.setBoxCode(code);
        bmQrBoxInfo.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
        bmQrBoxInfo.setCreateTime(DateUtils.getNowDate());
        final int result = bmQrBoxMapper.insertBmQrcodeInfo(bmQrBoxInfo);
        return 0 < result ? AjaxResult.success(HttpCodeEnum.SUCCESS.getMsg()) : AjaxResult.error(HttpCodeEnum.FAIL.getCode(), HttpCodeEnum.FAIL.getMsg());
    }

    /**
     * 生成标准箱编码
     * @param thisMonthMaxOrder
     * @return
     */
    private String genderTaskCode(int thisMonthMaxOrder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date nowDate = DateUtils.getNowDate();
        String format = dateFormat.format(nowDate);
        String result = format.replace("-", "");
        return QR_BOX_PREFIX + result + String.format("-%03d", thisMonthMaxOrder + 1);
    }

    /**
     * BoxCode查询标准箱信息
     *
     * @param bmQrBoxInfo 查询条件
     */
    @Override
    public AjaxResult getBoxInfoBindListByCode(BmQrBoxInfo bmQrBoxInfo) {
        if (null == bmQrBoxInfo.getBoxCode()) {
            return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), "请输入标准箱编码");
        }
        final BoxInfoBindVo boxInfoBindVo = new BoxInfoBindVo();

        final List<BmQrBoxInfo> boxInfos = bmQrBoxMapper.findBoxInfoByKey(bmQrBoxInfo);
        boxInfos.removeIf(Objects::isNull);
        if (boxInfos.isEmpty()) {
            return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), "标准箱编码不存在");
        } else if (1 == boxInfos.size()) {
            if (null == boxInfos.get(0).getBoxId() || null == boxInfos.get(0).getBoxCode()) {
                return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), "标准箱信息异常，请联系运维人员处理");
            }
            boxInfoBindVo.setBoxId(boxInfos.get(0).getBoxId());
            boxInfoBindVo.setBoxCode(boxInfos.get(0).getBoxCode());
        } else {
            return AjaxResult.warn("该二维码已绑定多个标准箱，请联系运维人员处理");
        }

        final List<BmQrBoxInfo> boxBindList = bmQrBoxMapper.getBoxBindList(boxInfoBindVo.getBoxId());
        boxBindList.removeIf(Objects::isNull);
        boxInfoBindVo.setBindMaTotal(boxBindList.size());
        boxBindList.removeIf(item -> null == item.getMaStatus());
        boxBindList.removeIf(item -> !"新购待入库".equals(item.getMaStatus()));
        if (Objects.nonNull(bmQrBoxInfo.getMaTypeId())) {
            boxBindList.removeIf(item -> null == item.getMaTypeId() || !Objects.equals(item.getMaTypeId(), bmQrBoxInfo.getMaTypeId()));
        }
        boxInfoBindVo.setSuccessMaTotal(boxBindList.size());
        return AjaxResult.success(boxInfoBindVo);
    }

    /**
     * APP -- 新购入库扫码 -- 确认入库
     *
     * @param boxBindWarehouseDto 入库信息
     */
    @Override
    public AjaxResult appWarehouse(BoxBindWarehouseDto boxBindWarehouseDto) {
        // -------------- 标准箱状态校验 -------------------------
        if (null == boxBindWarehouseDto.getBoxCode()) {
            return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), "请输入标准箱编码");
        }
        if (null == boxBindWarehouseDto.getTaskId() || null == boxBindWarehouseDto.getMaTypeId()) {
            return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), "请输入任务ID和入库的物资类型ID");
        }
        final List<BmQrBoxInfo> boxInfos = bmQrBoxMapper.findBoxInfoByKey(new BmQrBoxInfo().setBoxCode(boxBindWarehouseDto.getBoxCode()));
        boxInfos.removeIf(Objects::isNull);
        if (boxInfos.isEmpty()) {
            return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), "标准箱编码不存在");
        } else if (1 == boxInfos.size()) {
            if (null == boxInfos.get(0).getBoxId() || null == boxInfos.get(0).getBoxCode()) {
                boxBindWarehouseDto.setBoxId(boxInfos.get(0).getBoxId());
                return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), "标准箱信息异常，请联系运维人员处理");
            }
        } else {
            return AjaxResult.warn("该二维码已绑定多个标准箱，请联系运维人员处理");
        }

        // -------------- 标准箱绑定的机具明细校验 -------------------------
        final List<BmQrBoxInfo> boxBindList = bmQrBoxMapper.getBoxBindList(boxBindWarehouseDto.getBoxId());
        boxBindList.removeIf(Objects::isNull);
        boxBindList.removeIf(item -> null == item.getMaStatus());
        boxBindList.removeIf(item ->
                !item.getMaStatus().equals(MaMachineStatusEnum.NEW_PURCHASE.getStatusName()) &&
                !item.getMaStatus().equals(MaMachineStatusEnum.REPAIR_TO_STORE.getStatusName()) &&
                !item.getMaStatus().equals(MaMachineStatusEnum.BACK_TO_STORE.getStatusName())
        );
        boxBindList.removeIf(item -> null == item.getMaTypeId() || !Objects.equals(item.getMaTypeId(), boxBindWarehouseDto.getMaTypeId()));


        // ----------------- 进行入库操作 -------------------------------
        final Long purchaseDetailId = purchaseStorageMapper.selectIdByTaskId(boxBindWarehouseDto.getTaskId(), boxBindWarehouseDto.getMaTypeId());
        if (null == purchaseDetailId || 0 == purchaseDetailId) {
            return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), "新购任务不存在此物资类型，请确认录入是否正确");
        }
        // 更新入库数量
        purchaseStorageMapper.updateNum(purchaseDetailId, BigDecimal.valueOf(boxBindList.size()));
        // 更新物资类型库存数量
        purchaseStorageMapper.updateStorageNum(BigDecimal.valueOf(boxBindList.size()), Math.toIntExact(boxBindWarehouseDto.getMaTypeId()));
        // 更新物资设备状态
        boxBindList.forEach(item -> {
            item.setMaStatus(MaMachineStatusEnum.IN_STORE.getStatus().toString());
            purchaseStorageMapper.updateMachineByCode(new PurchaseDto().setMaCode(item.getMaCode()).setTypeId(Math.toIntExact(boxBindWarehouseDto.getMaTypeId())));
        });
        // 更新新购验收明细状态
        purchaseStorageMapper.updateInputStatusById(PurchaseTaskStatusEnum.IN_STORE.getStatus(), Math.toIntExact(purchaseDetailId));

        // TODO 缺少修改TmTask表状态
        // ---------------- 返回前端 -------------------------------------
        return AjaxResult.success("入库成功");
    }

    /**
     * 下载二维码标准箱
     * @param response 响应对象
     */
    @Override
    public void download(BmQrBoxInfo bmQrBoxInfo, HttpServletResponse response) {
        try {
            final List<BmQrBoxInfo> list = bmQrBoxMapper.find(bmQrBoxInfo);
            String code = "无编码";
            if (!list.isEmpty()) {
                code = list.get(0).getBoxCode();
            }
            // 新购管理-二维码打印-新增
            final String url = BackstageApplication.getUrl() + "backstage/machine/qrCodePage?qrcode=" + code;
            // 二维码的图片格式
            final String format = "jpg";
            //设置路径
            final String mkdirsName = "images";
            // linux 系统路径
            String saveDirectory = "/data/imw/" + mkdirsName + "/";
            final String os = System.getProperty("os.name");
            if (os.toLowerCase().startsWith("win")) {
                //本地路径
                saveDirectory = "D://files/" + mkdirsName + "/";
            }
            // 生成二维码
            File files = new File(saveDirectory);
            if (!files.exists()) {
                files.mkdirs();
            }
            QrCodeUtils.generateQRImage(url, saveDirectory, code + ".jpg", format);
            String qrUrl = saveDirectory + code + ".jpg";
            String path = qrUrl.replace("filePath", "/data/imw");
            // 判断照片是否存在
            final File imageFile = new File(path);
            if (!imageFile.exists()) {
                log.warn("图片不存在");
            }
            //设置MIME类型
            response.setContentType("application/octet-stream");
            response.addHeader("Content-disposition", "attachment;filename=" + new String(path.getBytes(), StandardCharsets.ISO_8859_1));
            final InputStream inputStream = Files.newInputStream(imageFile.toPath());
            final ServletOutputStream outputStream = response.getOutputStream();
            final byte[] bs = new byte[1024];
            while ((0 < inputStream.read(bs))) {
                outputStream.write(bs);
            }
            outputStream.close();
            inputStream.close();
        } catch (final Exception e) {
            log.error(e.getMessage());
        }
    }

    /**
     * 修改二维码标准箱管理
     */
    @Override
    public AjaxResult updateBmQrcodeInfo(BmQrBoxInfo bmQrBoxInfo) {
        bmQrBoxInfo.setUpdateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
        bmQrBoxInfo.setUpdateTime(DateUtils.getNowDate());
        final int result = bmQrBoxMapper.updateBmQrcodeInfoById(bmQrBoxInfo);
        return 0 < result ? AjaxResult.success(HttpCodeEnum.SUCCESS.getMsg()) : AjaxResult.error(HttpCodeEnum.FAIL.getCode(), HttpCodeEnum.FAIL.getMsg());
    }

    /**
     * APP - 移交标准箱
     *
     * @param bmQrBoxInfo 标准箱信息
     */
    @Override
    public AjaxResult appTransfer(BmQrBoxInfo bmQrBoxInfo) {
        // 根据boxId查询该标准箱里面是否存在设备，空箱不允许移交
        List<BmQrBoxInfo> list = bmQrBoxMapper.getList(bmQrBoxInfo);
        if (CollectionUtils.isEmpty(list)) {
            return AjaxResult.error("该标准箱中无相关设备，无法进行移交！");
        }
        bmQrBoxInfo.setBoxCode(null).setBoxName(null).setBoxType(null).setStatus(QrBoxStatusEnum.QR_BOX_STATUS_WAIT_RECEIVE.getStatus().toString());
        bmQrBoxInfo.setTransferUser(SecurityUtils.getLoginUser().getUserid());
        return 0 < bmQrBoxMapper.updateBmQrcodeInfoById(bmQrBoxInfo) ? AjaxResult.success(HttpCodeEnum.SUCCESS.getMsg()) :
                AjaxResult.error(HttpCodeEnum.FAIL.getCode(), HttpCodeEnum.FAIL.getMsg());
    }

    /**
     * APP -- 移交驳回
     *
     * @param bmQrBoxInfo 标准箱信息
     */
    @Override
    public AjaxResult appTransferReject(BmQrBoxInfo bmQrBoxInfo) {
        final List<BmQrBoxInfo> bmQrBoxInfos = bmQrBoxMapper.find(new BmQrBoxInfo().setBoxId(bmQrBoxInfo.getBoxId()));
        if (!bmQrBoxInfos.isEmpty()) {
            final BmQrBoxInfo item = bmQrBoxInfos.get(0);
            if (null == item.getInputUser() || !Objects.equals(item.getInputUser(), SecurityUtils.getLoginUser().getUserid())) {
                return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), "驳回失败,您并非接收人,无法操作驳回!");
            }
        } else {
            return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), "驳回失败,无此标准箱信息!");
        }
        bmQrBoxInfo.setBoxCode(null).setBoxName(null).setBoxType(null).setStatus(QrBoxStatusEnum.QR_BOX_STATUS_REJECT.getStatus().toString());
        return 0 < bmQrBoxMapper.updateBmQrcodeInfoById(bmQrBoxInfo) ?
                AjaxResult.success(HttpCodeEnum.SUCCESS.getMsg()) :
                AjaxResult.error(HttpCodeEnum.FAIL.getCode(), HttpCodeEnum.FAIL.getMsg());
    }

    /**
     * APP - 接收标准箱
     *
     * @param bmQrBoxInfo 标准箱信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult appReceive(BmQrBoxInfo bmQrBoxInfo) {
       /* int result = 0;
        // 用来存储每个 taskId 的出现次数
        Map<String, Integer> taskIdCountMap = new HashMap<>();
        final List<BmQrBoxInfo> bmQrBoxInfos = bmQrBoxMapper.find(new BmQrBoxInfo().setBoxId(bmQrBoxInfo.getBoxId()));
        if (!bmQrBoxInfos.isEmpty()) {
            final BmQrBoxInfo item = bmQrBoxInfos.get(0);
            if (null == item.getTransferUser()) {
                return AjaxResult.error(500, "接收失败,当前操作非移交人,无法接收!");
            }
            List<BmQrBoxInfo> list = bmQrBoxMapper.getBoxBindListById(bmQrBoxInfo);
            if (CollectionUtils.isNotEmpty(list)) {
                //修改机具状态为在库
                for (BmQrBoxInfo qrBoxInfo : list) {
                    result += machineMapper.updateStatus(qrBoxInfo.getMaId(), MaMachineStatusEnum.IN_STORE.getStatus());
                    String taskId = qrBoxInfo.getTaskId();
                    Long typeId = qrBoxInfo.getMaTypeId();
                    // 使用 taskId 和 typeId 拼接成复合键
                    String key = taskId + "_" + typeId;
                    taskIdCountMap.put(key, taskIdCountMap.getOrDefault(key, 0) + 1);
                }
                //根据taskId机器数量，更新入库数量
                if (result > 0) {
                    for (Map.Entry<String, Integer> entry : taskIdCountMap.entrySet()) {
                        String key = entry.getKey();
                        int count = entry.getValue();
                        String[] parts = key.split("_");
                        String taskId = parts[0];
                        Long typeId = Long.parseLong(parts[1]);
                        result += purchaseBindMapper.updatePurchaseBindByTaskIdAndTypeId(taskId, typeId, count);
                        result += purchaseStorageMapper.updateStorageNum(BigDecimal.valueOf(count), typeId.intValue());
                        PurchaseDto purchaseDto = new PurchaseDto();
                        purchaseDto.setTaskId(taskId);
                        purchaseDto.setTypeId(typeId.intValue());
                        List<PurchaseCheckDetails> bindMaList = purchaseBindMapper.getMachineById(purchaseDto);
                        if (CollectionUtils.isNotEmpty(bindMaList)) {
                            result += purchaseStorageMapper.updatePurchaseBindByTaskIdAndTypeId(PurchaseTaskStatusEnum.TO_STORE.getStatus(), taskId, typeId);
                        } else {
                            result += purchaseStorageMapper.updatePurchaseBindBy(PurchaseTaskStatusEnum.IN_STORE.getStatus(), taskId, typeId);
                        }
                        List<PurchaseVo> statusList = purchaseStorageMapper.select(taskId);
                        result += updateTaskStatus(statusList);
                    }
                }
            }
        } else {
            return AjaxResult.error(500, "接收失败,无此标准箱信息!");
        }*/
        bmQrBoxInfo.setBoxCode(null).setBoxName(null).setBoxType(null)
                .setInputUser(SecurityUtils.getLoginUser().getUserid())
                .setStatus(QrBoxStatusEnum.QR_BOX_STATUS_ON_RECEIVE.getStatus().toString());
        return 0 < bmQrBoxMapper.updateBmQrcodeInfoById(bmQrBoxInfo) ?
                AjaxResult.success(HttpCodeEnum.SUCCESS.getMsg()) :
                AjaxResult.error(500, HttpCodeEnum.FAIL.getMsg());
    }

    /**
     * 更新任务状态
     * @param details
     * @return
     */
    private int updateTaskStatus(List<PurchaseVo> details) {
        Map<Integer, List<Integer>> groupedByIdStatus = details.stream()
                .collect(Collectors.groupingBy(
                        PurchaseVo::getTaskId,
                        Collectors.mapping(PurchaseVo::getStatus, Collectors.toList())
                ));
        return groupedByIdStatus.entrySet().stream()
                .mapToInt(entry -> {
                    Integer id = entry.getKey();
                    List<Integer> statusList = entry.getValue();
                    if (!statusList.contains(PurchaseTaskStatusEnum.TO_STORE.getStatus()) && !statusList.contains(PurchaseTaskStatusEnum.TO_STORE_AFTER_REJECT.getStatus())
                            && statusList.stream().allMatch(status -> status.equals(PurchaseTaskStatusEnum.IN_STORE.getStatus()))) {
                        return tmTaskMapper.updateTaskStatus(id.toString(), PurchaseTaskStatusEnum.TASK_FINISHED.getStatus());
                    }
                    return 0;
                }).sum();
    }

    /**
     * APP - 扫码创建标准箱
     *
     * @param bmQrBoxInfo 标准箱信息
     */
    @Override
    public AjaxResult updateBmQrcodeInfoByCode(BmQrBoxInfo bmQrBoxInfo) {
        bmQrBoxInfo.setUpdateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
        bmQrBoxInfo.setUpdateTime(DateUtils.getNowDate());
        bmQrBoxInfo.setStatus(QrBoxStatusEnum.QR_BOX_STATUS_WAIT_BIND.getStatus().toString());
        final int result = bmQrBoxMapper.updateBmQrcodeInfoByCode(bmQrBoxInfo);
        return 0 < result ? AjaxResult.success(HttpCodeEnum.SUCCESS.getMsg()) : AjaxResult.error(HttpCodeEnum.FAIL.getCode(), HttpCodeEnum.FAIL.getMsg());
    }

    /**
     * 通过QR_CODE 查询物资信息
     *
     * @param qrCode 二维码编码
     */
    @Override
    public AjaxResult getMaInfoByQrCode(String qrCode) {
        if (StringUtils.isBlank(qrCode)) {
            return AjaxResult.error("二维码编码为空，请完善后重试!");
        }
        return AjaxResult.success(bmQrBoxMapper.getMaInfoByQrCode(qrCode));
    }

    /**
     * APP - 扫码绑定物资
     *
     * @param bmQrBoxInfo 扫码信息
     */
    @Override
    public AjaxResult addQrcodeBoxBind(BmQrBoxInfo bmQrBoxInfo) {
        if (null == bmQrBoxInfo.getBoxId()) {return AjaxResult.error("标准箱ID为空，请完善后重试!");}
        if (null == bmQrBoxInfo.getQrCode()) {return AjaxResult.error("QR编码为空，请完善后重试!");}

        try {
            // 物资状态要求是待入库、在库状态
            final MachineVo machineVo = machineMapper.selectMachineByMaCode(bmQrBoxInfo);
            if (null == machineVo || null == machineVo.getMaId()) {
                return AjaxResult.error("物资信息不存在!");
            }
            if (null == machineVo.getMaStatus()) {
                return AjaxResult.error("物资状态异常，请完善后重试!");
            }
            if (!Objects.equals(machineVo.getMaStatus(), MaMachineStatusEnum.NEW_PURCHASE.getStatus().toString()) &&
                    !Objects.equals(machineVo.getMaStatus(), MaMachineStatusEnum.REPAIR_TO_STORE.getStatus().toString())
            ) {
                return AjaxResult.error("物资状态非待入库状态,无法操作:" + machineVo.getMaStatus());
            }

            // 物资的新购批次判断，是否和Box标准箱内已存在的是同一批
//            if (null == machineVo.getBuyTask()) {
//                return AjaxResult.error("物资未关联采购批次，请完善后重试!");
//            }
//            String boxBindMaBuyTaskId = bmQrBoxMapper.getBoxBindMaBuyTaskByBoxId(bmQrBoxInfo.getBoxId());
//            if (null != boxBindMaBuyTaskId && !Objects.equals(boxBindMaBuyTaskId, machineVo.getBuyTask())) {
//                return AjaxResult.error("该物资批次与标准箱已存在批次不匹配，请完善后重试!");
//            }

            // 此物资未在其他标准型入过库，才可以绑定
            if (0 < bmQrBoxMapper.existsMaId(machineVo.getMaId())) {
                return AjaxResult.error("该物资已绑定其他标准箱，无法再次绑定!");
            }

            // 一个标准型只有1种类型
            final List<Long> boxMaTypeList = bmQrBoxMapper.getBoxMaTypeList(bmQrBoxInfo.getBoxId());
            if (!boxMaTypeList.isEmpty()) {
                if (1 < boxMaTypeList.size()) {
                    return AjaxResult.error("该标准箱已绑定多种物资，无法进行操作，请联系运维人员处理!");
                }
                if (!Objects.equals(boxMaTypeList.get(0), machineVo.getTypeId())) {
                    return AjaxResult.error("该标准箱已绑定其他类型物资，无法绑定此类型!");
                }
            }

            // 验证通过，进行数据处理
            bmQrBoxInfo.setMaId(machineVo.getMaId());
            bmQrBoxInfo.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
            bmQrBoxInfo.setCreateTime(DateUtils.getNowDate());
            if (0 < bmQrBoxMapper.addQrcodeBoxBind(bmQrBoxInfo)) {
                // 修改标准箱状态为已完成
                bmQrBoxInfo.setStatus(QrBoxStatusEnum.QR_BOX_STATUS_WAIT_TRANSFER.getStatus().toString());
                bmQrBoxMapper.updateBmQrcodeStatus(bmQrBoxInfo);
                return AjaxResult.success(HttpCodeEnum.SUCCESS.getMsg());
            }
            return AjaxResult.error("绑定失败:成功绑定0条");
        } catch (final Exception e) {
            System.err.println("绑定失败,SQL执行异常:" + e.getMessage());
            return AjaxResult.error("绑定失败,SQL执行异常:" + e.getMessage());
        }
    }

    /**
     * 获取绑定物资列表
     *
     * @param bean
     */
    @Override
    public List<BmQrBoxInfo> getBoxBindList(BmQrBoxInfo bean) {
        return bmQrBoxMapper.getBoxBindLists(bean);
    }

    /**
     * 删除二维码标准箱
     * @param bmQrBoxInfo 主键
     */
    @Override
    public AjaxResult deleteById(BmQrBoxInfo bmQrBoxInfo) {
        //根据id查看标准箱是否绑定，绑定不能删除
        if (0 < bmQrBoxMapper.countBmQrcodeInfoByBoxId(bmQrBoxInfo.getBoxId())) {
            return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), "该标准箱已绑定设备，无法删除");
        }
        final int result = bmQrBoxMapper.deleteById(bmQrBoxInfo);
        return 0 < result ? AjaxResult.success(HttpCodeEnum.SUCCESS.getMsg()) : AjaxResult.error(HttpCodeEnum.FAIL.getCode(), HttpCodeEnum.FAIL.getMsg());
    }

    /**
     * 解除二维码标准箱绑定关系
     *
     * @param bmQrBoxInfo 解绑信息
     */
    @Override
    public AjaxResult unBindQrcodeBox(BmQrBoxInfo bmQrBoxInfo) {
        final boolean unResult = 0 < bmQrBoxMapper.unBindQrcodeBox(bmQrBoxInfo);
        if (0 == bmQrBoxMapper.countBmQrcodeInfoByBoxId(bmQrBoxInfo.getBoxId())) {
            bmQrBoxInfo.setBoxCode(null).setBoxName(null).setBoxType(null).setStatus(QrBoxStatusEnum.QR_BOX_STATUS_WAIT_BIND.getStatus().toString());
            bmQrBoxMapper.updateBmQrcodeInfoById(bmQrBoxInfo);
        }
        return unResult ? AjaxResult.success(HttpCodeEnum.SUCCESS.getMsg()) : AjaxResult.error(HttpCodeEnum.FAIL.getCode(), HttpCodeEnum.FAIL.getMsg());
    }

    /**
     * 查询二维码标准箱管理绑定详情列表
     * @param bmQrBoxInfo 查询条件
     * @return list列表
     */
    @Override
    public List<BmQrBoxInfo> getList(BmQrBoxInfo bmQrBoxInfo) {
        return bmQrBoxMapper.getList(bmQrBoxInfo);
    }

    /**
     * app出库查询标准箱绑定详情
     * @param bmQrBoxInfo
     * @return
     */
    @Override
    public AjaxResult getBoxBindListByCode(BmQrBoxInfo bmQrBoxInfo) {
        if (null == bmQrBoxInfo.getBoxCode() || null == bmQrBoxInfo.getMaTypeId()) {
            return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), "标准箱编码或机具类型id不能为空");
        }
        List<BmQrBoxInfo> recordList = new ArrayList<>();
        List<BmQrBoxInfo> list = bmQrBoxMapper.getBoxBindListByCode(bmQrBoxInfo);
        int num = 0;
        String msg;
        if (CollectionUtil.isNotEmpty(list)) {
            for (BmQrBoxInfo qrBoxInfo : list) {
                if (qrBoxInfo.getMaStatus().equals(MaMachineStatusEnum.IN_STORE.getStatus().toString())) {
                    recordList.add(qrBoxInfo);
                    num ++;
                }
            }
            msg = "监测到" + bmQrBoxInfo.getBoxCode() + "标准箱中有" + list.size() + "台设备，符合出库条件设备" + num + "台，请确认是否出库!";
        } else {
            msg = "监测到" + bmQrBoxInfo.getBoxCode() + "标准箱中无符合出库条件的设备，请检查后重新提交!";
            recordList = new ArrayList<>();
        }
        // 返回包含设备列表和消息的结果
        final Map<String, Object> result = new HashMap<>(2);
        result.put("recordList", recordList);
        result.put("msg", msg);
        return AjaxResult.success(result);
    }

    /**
     * APP -- 修饰入库 -- 扫码获取绑定物资信息
     * @param bmQrBoxInfo
     * @return
     */
    @Override
    public AjaxResult getBoxCodeList(BmQrBoxInfo bmQrBoxInfo) {
        if (null == bmQrBoxInfo.getBoxCode() ) {
            return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), "标准箱编码不能为空");
        }
        return AjaxResult.success(bmQrBoxMapper.getBoxCodeList(bmQrBoxInfo));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult appBoxInput(BoxBindWarehouseDto boxBindWarehouseDto) {
        int result = 0;
        try {
            List<BoxBindWarehouseDto> boxList = bmQrBoxMapper.getBoxList(boxBindWarehouseDto);
            for (BoxBindWarehouseDto  boxMa: boxList) {
                //1.验证标准箱里的机具是否待入库
                if ("0".equals(boxMa.getMaStatus())) {

                }else{
                    return AjaxResult.error(String.format("标准箱里%s状态异常，请检查后重新提交!", boxMa.getMaStatus()));
                }
                //2.修改新购入库数量,    //2.5.修改入库任务状态
                result = updateNewInputNum(boxMa);
                if (0 == result) {
                    return AjaxResult.error("入库失败:成功入库0条");
                }
                //3.修改库存
                result = updateStorageNum(boxMa);
                if (0 == result) {
                    return AjaxResult.error("入库失败:成功入库0条");
                }
                //4.修改标准箱状态
                result = updateBoxStatus(boxMa);
                if (0 == result) {
                    return AjaxResult.error("入库失败:成功入库0条");
                }

            }


        } catch (final Exception e) {
            System.err.println("入库失败,SQL执行异常:" + e.getMessage());
            return AjaxResult.error("入库失败,SQL执行异常:" + e.getMessage());
        }

        return AjaxResult.success();
    }

    /**
     * 获取标准箱详情
     * @param info
     * @return
     */
    @Override
    public AjaxResult getBoxInfo(BoxBindWarehouseDto info) {
        BoxBindWarehouseDto bmQrBoxInfo = bmQrBoxMapper.getBoxInfo(info);
        // 根据boxCode查询标准箱详情
        List<BoxBindWarehouseDto> boxList = bmQrBoxMapper.getBoxList(info);
        if (bmQrBoxInfo != null) {
            Map<String, String> boxStatus = remoteConfig.getDictValue("qr_box_status");
            if (StringUtils.isNotBlank(bmQrBoxInfo.getBoxStatus())) {
                bmQrBoxInfo.setBoxStatus(StringUtils.isBlank(boxStatus.get(bmQrBoxInfo.getBoxStatus())) ? "" : boxStatus.get(bmQrBoxInfo.getBoxStatus()));
            }
            if (CollectionUtil.isNotEmpty(boxList)) {
                bmQrBoxInfo.setInputNum(BigDecimal.valueOf(boxList.size()));
            }
        }
        return AjaxResult.success(bmQrBoxInfo);
    }

    /**
     * 标准箱信息详情查询
     * @param dto
     * @return
     */
    @Override
    public AjaxResult getBoxDetails(BoxBindWarehouseDto dto) {
        List<BoxBindWarehouseDto> list = bmQrBoxMapper.getBoxList(dto);
        if (CollectionUtil.isNotEmpty(list)) {
            Map<String, String> machineStatus = remoteConfig.getDictValue("ma_machine_status");
            if (CollectionUtils.isNotEmpty(list)) {
                list.forEach(info -> {
                    if (StringUtils.isNotBlank(info.getMaStatus())) {
                        info.setMaStatus(StringUtils.isBlank(machineStatus.get(info.getMaStatus())) ? "" : machineStatus.get(info.getMaStatus()));
                    }
                });
            }
        }
        return AjaxResult.success(list);
    }

    /**
     * 根据编码查询信息
     * @param info
     * @return
     */
    @Override
    public AjaxResult getMaCodeList(BmQrBoxInfo info) {
       /* // 先根据编码查询ma_machine
        MachineVo machineVo = machineMapper.selectMachineByMaCode(info);
        if (machineVo != null) {
            if (!Objects.equals(machineVo.getMaStatus(), MaMachineStatusEnum.INFORMATION_COLLECTION.getStatus().toString())) {
                return AjaxResult.error("物资状态非信息采集待入库状态,无法操作!");
            }
        }*/
        // 先根据编码查询ws_ma_info
        MachineVo wsMaInfo = machineMapper.selectMaInfoByMaCode(info);
        return AjaxResult.success(wsMaInfo);
    }

    /**
     * 添加标准箱绑定物资信息
     * @param machine
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult addMaCodeBoxBind(Machine machine) {
        if (null == machine.getBoxId()) {return AjaxResult.error("标准箱ID为空，请完善后重试!");}
        if (null == machine.getMaCode()) {return AjaxResult.error("编码为空，请完善后重试!");}

        try {
            // 先查询数据是否存在
            BmQrBoxInfo bmQrBoxInfo = new BmQrBoxInfo();
            bmQrBoxInfo.setMaCode(machine.getMaCode());
            //MachineVo vo = machineMapper.selectMachineByMaCode(bmQrBoxInfo);
            //machine.setMaStatus(MaMachineStatusEnum.INFORMATION_COLLECTION.getStatus().toString());
            /*if (vo != null) {
                machine.setMaId(vo.getMaId());
                machine.setUpdateTime(DateUtils.getNowDate());
                int i = machineMapper.updateMachine(machine);
                if (0 == i) {
                    return AjaxResult.error("更新绑定机具失败");
                }
            } else {
                // 先走新增获取maId,状态为待在库
                machine.setCreateTime(DateUtils.getNowDate());
                int result = machineMapper.insertMachine(machine);
                if (0 == result) {
                    return AjaxResult.error("新增绑定机具失败");
                }
            }*/
            // 此物资未在其他标准型入过库，才可以绑定
            if (0 < bmQrBoxMapper.existsMaId(machine.getMaId())) {
                return AjaxResult.error("该物资已绑定其他标准箱，无法再次绑定!");
            }

            // 一个标准型只有1种类型
            final List<Long> boxMaTypeList = bmQrBoxMapper.getBoxWsTypeList(machine.getBoxId());
            if (!boxMaTypeList.isEmpty()) {
                if (1 < boxMaTypeList.size()) {
                    return AjaxResult.error("该标准箱已绑定多种物资，无法进行操作，请联系运维人员处理!");
                }
                if (!Objects.equals(boxMaTypeList.get(0), machine.getTypeId())) {
                    return AjaxResult.error("该标准箱已绑定其他类型物资，无法绑定此类型!");
                }
            }

            // 验证通过，进行数据处理
            bmQrBoxInfo.setMaId(machine.getMaId());
            bmQrBoxInfo.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
            bmQrBoxInfo.setCreateTime(DateUtils.getNowDate());
            bmQrBoxInfo.setBoxId(machine.getBoxId());
            // 关联ws_ma_info
            bmQrBoxInfo.setBoxType("0");
            bmQrBoxMapper.updateBmQrcodeInfoById(bmQrBoxInfo);
            if (0 < bmQrBoxMapper.addQrcodeBoxBind(bmQrBoxInfo)) {
                // 修改标准箱状态为待移交
                bmQrBoxInfo.setStatus(QrBoxStatusEnum.QR_BOX_STATUS_WAIT_TRANSFER.getStatus().toString());
                bmQrBoxMapper.updateBmQrcodeStatus(bmQrBoxInfo);
                return AjaxResult.success(HttpCodeEnum.SUCCESS.getMsg());
            }
            return AjaxResult.error("绑定失败:成功绑定0条");
        } catch (final Exception e) {
            System.err.println("绑定失败,SQL执行异常:" + e.getMessage());
            return AjaxResult.error("绑定失败,SQL执行异常:" + e.getMessage());
        }
    }

    /**
     * 获取标准箱绑定物资信息
     * @param bean
     * @return
     */
    @Override
    public List<BmQrBoxInfo> getBoxBindWsList(BmQrBoxInfo bean) {
        return bmQrBoxMapper.getBoxBindWsList(bean);
    }

    private int updateBoxStatus(BoxBindWarehouseDto boxMa) {
        int result = 0;
        result = bmQrBoxMapper.updateBoxStatus(boxMa);
        return result;
    }

    private int updateStorageNum(BoxBindWarehouseDto boxMa) {
        Type type = new Type();
        int result = 0;


        String maStatus = boxMa.getMaStatus();
        if("0".equals(maStatus)) {
            type.setModelTitle("新购入库");
            type.setTypeId(boxMa.getMaTypeId());
            type.setInputNum(BigDecimal.valueOf(1));
            type.setMaId(boxMa.getMaId());
            type.setStyle("4");
            result = typeService.updateNumAddOrSubtract(type);
            result = machineMapper.updateMaStatus(boxMa);
            /*boxMa.setInputNum(BigDecimal.valueOf(1));
            result = bmQrBoxMapper.updateStorageNum(boxMa);*/
        }

        return result;
    }

    private int updateNewInputNum(BoxBindWarehouseDto boxMa) {
        int result = 0;
        result = bmQrBoxMapper.updateNewInputNum(boxMa);

        BoxBindWarehouseDto sonStatus = bmQrBoxMapper.getSingleInfo(boxMa);
        if (sonStatus != null) {
            //不用修改任务状态
        } else {
            //修改子任务状态
            bmQrBoxMapper.updatePurchaseStatus(boxMa);
            BoxBindWarehouseDto taskStatus = bmQrBoxMapper.getTaskInfo(boxMa);
            if (taskStatus != null) {
                //不用修改任务状态
            } else {
                //修改任务状态
                bmQrBoxMapper.updateTaskStatus(boxMa);
            }


        }
        return result;
    }

}
