package cn.iocoder.yudao.module.product.service.harvestbatch;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.common.enums.BlockStateEnum;
import cn.iocoder.yudao.framework.common.enums.CodeEnum;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.basic.api.businessinfo.BusinessInfoApi;
import cn.iocoder.yudao.module.basic.api.goodsinfo.GoodsInfoApi;
import cn.iocoder.yudao.module.basic.api.goodsinfo.dto.GoodsInfoRespDTO;
import cn.iocoder.yudao.module.basic.api.redis.dto.BusinessInfoDTO;
import cn.iocoder.yudao.module.chain.api.blockcertificate.BlockCertificateApi;
import cn.iocoder.yudao.module.chain.api.blockcertificate.dto.*;
import cn.iocoder.yudao.module.chain.api.operatedetail.OperateDetailApi;
import cn.iocoder.yudao.module.chain.api.operatedetail.dto.OperateDetailRespDTO;
import cn.iocoder.yudao.module.chain.api.operatedetail.dto.OperateDetailSaveReqDTO;
import cn.iocoder.yudao.module.chain.enums.*;
import cn.iocoder.yudao.module.configure.api.deviceenvtype.DeviceEnvTypeApi;
import cn.iocoder.yudao.module.configure.api.deviceenvtype.dto.DeviceEnvTypeCreateReqDTO;
import cn.iocoder.yudao.module.configure.api.uniTemplate.UniTemplateApi;
import cn.iocoder.yudao.module.configure.api.uniTemplate.dto.UniTemplateDTO;
import cn.iocoder.yudao.module.product.controller.admin.envtype.vo.EnvTypeConfigRespVO;
import cn.iocoder.yudao.module.product.controller.admin.envtype.vo.EnvTypeDeviceConfigRespVO;
import cn.iocoder.yudao.module.product.controller.admin.harvestbatch.vo.*;
import cn.iocoder.yudao.module.product.dal.dataobject.harvestbatch.HarvestBatchDO;
import cn.iocoder.yudao.module.product.dal.dataobject.harvestbatchconfig.HarvestBatchConfigDO;
import cn.iocoder.yudao.module.product.dal.mysql.harvestbatch.HarvestBatchMapper;
import cn.iocoder.yudao.module.product.dal.mysql.harvestbatchconfig.HarvestBatchConfigMapper;
import cn.iocoder.yudao.module.product.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.product.service.envtype.EnvTypeService;
import cn.iocoder.yudao.module.system.api.languagetype.LanguageTypeApi;
import cn.iocoder.yudao.module.system.api.languagetype.dto.LanguageTypeRespDTO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

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

/**
 * 采收批次 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class HarvestBatchServiceImpl implements HarvestBatchService {

    @Resource
    private HarvestBatchMapper harvestBatchMapper;

    @Resource
    private HarvestBatchConfigMapper harvestBatchConfigMapper;

    @Resource
    private EnvTypeService envTypeService;

    @Resource
    private BlockCertificateApi blockCertificateApi;

    @Resource
    private OperateDetailApi operateDetailApi;

    @Resource
    private GoodsInfoApi goodsInfoApi;

    @Resource
    private BusinessInfoApi businessInfoApi;

    @Resource
    private UniTemplateApi uniTemplateApi;

    @Resource
    private DeviceEnvTypeApi deviceEnvTypeApi;

    @Resource
    private LanguageTypeApi languageTypeApi;

    @Override
    public void deleteHarvestBatch(Long id) {
        // 校验存在
        validateHarvestBatchExists(id);
        // 删除
        harvestBatchMapper.deleteById(id);
    }

    @Override
    public void deleteBatch(List<Long> ids) {
        List<HarvestBatchDO> harvestBatchs = harvestBatchMapper.selectList(new LambdaQueryWrapperX<HarvestBatchDO>().in(HarvestBatchDO::getId, ids));
        if(harvestBatchs.size() != ids.size()) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.HARVEST_BATCH_NOT_EXISTS);
        }
        harvestBatchMapper.deleteBatchIds(ids);
    }

    private void validateHarvestBatchExists(Long id) {
        HarvestBatchDO harvestBatchDO = harvestBatchMapper.selectById(id);
        if (harvestBatchDO == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.HARVEST_BATCH_NOT_EXISTS);
        }
    }

    @Override
    public HarvestBatchRespVO getHarvestBatchDetail(Long id) {
        return harvestBatchMapper.getHarvestBatchDetail(id, null, null);
    }

    @Override
    public List<String> getAllBatchCode() {
        return harvestBatchMapper.selectList(new LambdaQueryWrapperX<HarvestBatchDO>()
                .select(HarvestBatchDO::getHarvestBatchId)).stream().map(HarvestBatchDO::getHarvestBatchId).collect(Collectors.toList());
    }

    @Override
    public PageResult<HarvestBatchDO> getHarvestBatchPage(HarvestBatchPageReqVO pageReqVO) {
        return harvestBatchMapper.selectPage(pageReqVO);
    }

    @Override
    public List<String> getHarverstBatchIdList(Integer count) {
        List<String> results = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            results.add(CodeEnum.HARVEST_BATCH_CODE.getCode());
        }
        return results;
    }

    @Override
    public GoodsConfigRespVO getGoodsConfig(Long id) {
        // 根据批次id 查询该采收批次信息
        HarvestBatchRespVO harvestBatch = this.verifyHarvestBatch(id, null);
        GoodsConfigRespVO result = new GoodsConfigRespVO();
        BeanUtil.copyProperties(harvestBatch, result);

        // 查询商户信息
        BlockCertificateReqDTO businessReqDTO = new BlockCertificateReqDTO();
        businessReqDTO.setOperateType(OperateTypeEnum.BUSINESS_INFO.getType());// 查询商户信息类型
        businessReqDTO.setBatchType(BatchTypeEnum.HARVEST_BATCH.getType());// 查询类型为采收批次的类型
        businessReqDTO.setBatchId(harvestBatch.getHarvestBatchId());
        List<BlockCertificateRespDTO> businessRespDTOs = blockCertificateApi.getBlockCertificateList(businessReqDTO).getData();
        BlockCertificateSaveReqVO businessInfo = new BlockCertificateSaveReqVO();
        if(businessRespDTOs.isEmpty() || businessRespDTOs.get(0).getOperateDetails().isEmpty()) {
            /*
              说明没有上链信息
              设置一个空的商户信息环节,
              注意： 一般只有第一次进入商品信息配置并且没有点【保存】才会进入该流程
             */
            BusinessInfoDTO businessInfoDTO = businessInfoApi.getBusinessInfoById(harvestBatch.getBelongBusinessId()).getData();
            if(businessInfoDTO == null) {
                throw ServiceExceptionUtil.exception(ErrorCodeConstants.BUSINESS_INFO_NOT_EXISTS);
            }
            businessInfo.setBatchId(harvestBatch.getHarvestBatchId());
            businessInfo.setBatchType(BatchTypeEnum.HARVEST_BATCH.getType());
            businessInfo.setOperateType(OperateTypeEnum.BUSINESS_INFO.getType());
            List<OperateDetailSaveReqVO> details = new ArrayList<>();
            OperateDetailSaveReqVO businessName = new OperateDetailSaveReqVO();
            businessName.setTitle("商户名称");
            businessName.setType(OperateDetailTypeEnum.TEXT.getType());
            businessName.setContent(businessInfoDTO.getBusinessName());
            details.add(businessName);

            OperateDetailSaveReqVO area = new OperateDetailSaveReqVO();
            area.setTitle("所属行政区");
            area.setType(OperateDetailTypeEnum.TEXT.getType());
            area.setContent(businessInfoDTO.getArea());
            details.add(area);

            OperateDetailSaveReqVO companiesName = new OperateDetailSaveReqVO();
            companiesName.setTitle("企业名称");
            companiesName.setType(OperateDetailTypeEnum.TEXT.getType());
            companiesName.setContent(businessInfoDTO.getCompaniesName());
            details.add(companiesName);

            OperateDetailSaveReqVO businessCode = new OperateDetailSaveReqVO();
            businessCode.setTitle("统一社会信用代码");
            businessCode.setType(OperateDetailTypeEnum.TEXT.getType());
            businessCode.setContent(businessInfoDTO.getBusinessCode());
            details.add(businessCode);

            OperateDetailSaveReqVO legalName = new OperateDetailSaveReqVO();
            legalName.setTitle("法人名称");
            legalName.setType(OperateDetailTypeEnum.TEXT.getType());
            legalName.setContent(businessInfoDTO.getLegalName());
            details.add(legalName);

            OperateDetailSaveReqVO legalIdCard = new OperateDetailSaveReqVO();
            legalIdCard.setTitle("法人身份证");
            legalIdCard.setType(OperateDetailTypeEnum.TEXT.getType());
            legalIdCard.setContent(businessInfoDTO.getLegalIdCard());
            details.add(legalIdCard);
            businessInfo.setOperateDetails(details);
        } else {
            /*
              有查询到上链认证信息
             */
            List<OperateDetailSaveReqVO> details = this.getOperateDetails(businessRespDTOs.get(0), businessInfo);
            businessInfo.setOperateDetails(details);
        }
        // 设置商品信息
        result.setBusinessInfo(businessInfo);

        // 查询商品信息
        BlockCertificateReqDTO blockCertificateDTO = new BlockCertificateReqDTO();
        blockCertificateDTO.setOperateType(OperateTypeEnum.GOODS_INFO.getType());// 查询商品信息类型
        blockCertificateDTO.setBatchType(BatchTypeEnum.HARVEST_BATCH.getType());// 查询类型为采收批次的类型
        blockCertificateDTO.setBatchId(harvestBatch.getHarvestBatchId());
        List<BlockCertificateRespDTO> respDTOs = blockCertificateApi.getBlockCertificateList(blockCertificateDTO).getData();

        BlockCertificateSaveReqVO goodsInfo = new BlockCertificateSaveReqVO();
        if(respDTOs.isEmpty() || respDTOs.get(0).getOperateDetails().isEmpty()) {
            /*
              说明没有上链信息
              设置一个空的商品信息环节, 仅包含商品名称和商品规格
              注意： 一般只有第一次进入商品信息配置并且没有点【保存】才会进入该流程
             */
            goodsInfo.setBatchId(harvestBatch.getHarvestBatchId());
            goodsInfo.setBatchType(BatchTypeEnum.HARVEST_BATCH.getType());
            goodsInfo.setOperateType(OperateTypeEnum.GOODS_INFO.getType());
            List<OperateDetailSaveReqVO> details = new ArrayList<>();
            OperateDetailSaveReqVO goodsName = new OperateDetailSaveReqVO();
            goodsName.setTitle("商品名称");
            goodsName.setType(OperateDetailTypeEnum.TEXT.getType());
            goodsName.setContent(harvestBatch.getGoodsName());
            details.add(goodsName);
            // 查询商品单位
            GoodsInfoRespDTO goodsInfoResp = this.getGoodsInfoByGoodsId(harvestBatch.getGoodsId(), harvestBatch.getBelongBusinessId());

            OperateDetailSaveReqVO goodsUnit = new OperateDetailSaveReqVO();
            goodsUnit.setTitle("商品规格");
            goodsUnit.setType(OperateDetailTypeEnum.TEXT.getType());
            goodsUnit.setContent(goodsInfoResp.getGoodsSpecs());
            details.add(goodsUnit);
            goodsInfo.setOperateDetails(details);
        } else {
            /*
              有查询到上链认证信息
             */
            List<OperateDetailSaveReqVO> details = this.getOperateDetails(respDTOs.get(0), goodsInfo);
            goodsInfo.setOperateDetails(details);
        }
        // 设置商品信息
        result.setGoodsInfo(goodsInfo);

        return result;
    }

    private GoodsInfoRespDTO getGoodsInfoByGoodsId(String goodsId, Long businessInfoId) {
        List<String> goodsIds = new ArrayList<>();
        goodsIds.add(goodsId);
        List<GoodsInfoRespDTO> goodsInfos = goodsInfoApi.getGoodsInfoListByGoodsIds(goodsIds, businessInfoId).getData();
        if(goodsInfos == null || goodsInfos.isEmpty() || goodsInfos.size() != goodsIds.size()) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.GOODS_INFO_NOT_EXISTS);// 说明对应的商品已经被删除
        }
        return goodsInfos.get(0);
    }

    private HarvestBatchRespVO verifyHarvestBatch(Long id, Long languageTypeId) {
        // 根据批次id 查询该采收批次信息
        HarvestBatchRespVO harvestBatch = harvestBatchMapper.getHarvestBatchDetail(id, null, languageTypeId);
        if(harvestBatch == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.HARVEST_BATCH_NOT_EXISTS);
        }
        return harvestBatch;
    }

    private List<OperateDetailSaveReqVO> getOperateDetails(BlockCertificateRespDTO respDTO, BlockCertificateSaveReqVO reqVO) {
        List<OperateDetailSaveReqVO> verifyDetails = new ArrayList<>();
        BeanUtil.copyProperties(respDTO, reqVO);
        respDTO.getOperateDetails().forEach(item -> {
            OperateDetailSaveReqVO detail = new OperateDetailSaveReqVO();
            BeanUtil.copyProperties(item, detail);
            verifyDetails.add(detail);
        });
        return verifyDetails;
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public Boolean createGoodsConfig(GoodsConfigSaveReqVO createReqVO) {
        // 根据批次id 查询该采收批次信息
        GoodsConfigRespVO goodsConfig = this.getGoodsConfig(createReqVO.getId());
        if(goodsConfig.getGoodsInfo().getId() != null) {// 已经有商品配置信息了，无法重复新增
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.CAN_NOT_CREATE_BLOCK_CERTIFICATE_REPEAT);
        }
        GoodsInfoRespDTO goodsInfoResp = this.getGoodsInfoByGoodsId(goodsConfig.getGoodsId(), goodsConfig.getBelongBusinessId());

        // 创建环节信息
        List<BlockCertificateCreateReqDTO> reqs = new ArrayList<>();
        // 商户环节信息
        BlockCertificateCreateReqDTO businessInfo = new BlockCertificateCreateReqDTO();
        businessInfo.setChainOperateId(CodeEnum.CHAIN_OPERATE_CODE.getCode());
        businessInfo.setOperateType(OperateTypeEnum.BUSINESS_INFO.getType()); // 操作类型: 商户信息类型
        businessInfo.setOperateName(OperateTypeEnum.BUSINESS_INFO.getName()); //
        businessInfo.setOperateObjId(goodsConfig.getBelongBusinessId()); // 所对应的商户id
        businessInfo.setBatchId(goodsConfig.getHarvestBatchId());
        businessInfo.setBatchType(BatchTypeEnum.HARVEST_BATCH.getType());
        // 上链未做完，这里只改状态
        businessInfo.setChainState(createReqVO.getBusinessInfo().getChainState()); // 上链状态（是否自动上链
        businessInfo.setBelongBusinessId(goodsConfig.getBelongBusinessId());
        businessInfo.setBelongBusinessName(goodsConfig.getBelongBusinessName());
        businessInfo.setLinkId(CodeEnum.TRACE_LINK_CODE.getCode());
        businessInfo.setLinkName(createReqVO.getBusinessInfo().getLinkName());

        // 设置环节明细
        this.setOperateDetails(createReqVO.getBusinessInfo().getOperateDetails(), businessInfo);
        reqs.add(businessInfo);// 商户信息

        // 商品环节信息
        BlockCertificateCreateReqDTO blockCertificate = new BlockCertificateCreateReqDTO();
        blockCertificate.setChainOperateId(CodeEnum.CHAIN_OPERATE_CODE.getCode());
        blockCertificate.setOperateType(OperateTypeEnum.GOODS_INFO.getType()); // 操作类型: 商品信息类型
        blockCertificate.setOperateName(OperateTypeEnum.GOODS_INFO.getName()); //
        blockCertificate.setOperateObjId(goodsInfoResp.getId()); // 所对应的商品id
        blockCertificate.setBatchId(goodsConfig.getHarvestBatchId());
        blockCertificate.setBatchType(BatchTypeEnum.HARVEST_BATCH.getType());
        // 上链未做完，这里只改状态
        blockCertificate.setChainState(createReqVO.getGoodsInfo().getChainState()); // 上链状态（是否自动上链
        blockCertificate.setBelongBusinessId(goodsConfig.getBelongBusinessId());
        blockCertificate.setBelongBusinessName(goodsConfig.getBelongBusinessName());
        blockCertificate.setLinkId(CodeEnum.TRACE_LINK_CODE.getCode());
        blockCertificate.setLinkName(createReqVO.getGoodsInfo().getLinkName());

        // 设置环节明细
        this.setOperateDetails(createReqVO.getGoodsInfo().getOperateDetails(), blockCertificate);

        reqs.add(blockCertificate);// 商品信息

        return !blockCertificateApi.createBlockCertificateBatch(reqs).isError();
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void updateGoodsConfig(GoodsConfigSaveReqVO updateReqVO) {
        // 校验配置主表信息，懒得再写个，直接调用已有方法
        GoodsConfigRespVO goodsConfig = this.getGoodsConfig(updateReqVO.getId());
        if(goodsConfig.getGoodsInfo().getId() == null || updateReqVO.getGoodsInfo().getId().longValue() != goodsConfig.getGoodsInfo().getId().longValue()) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.GOODS_CONFIG_NOT_EXISTS);
        }

        List<OperateDetailSaveReqVO> detailsInDB = goodsConfig.getGoodsInfo().getOperateDetails();
        List<OperateDetailSaveReqVO> details = updateReqVO.getGoodsInfo().getOperateDetails();
        List<OperateDetailSaveReqVO> biDetailsInDB = goodsConfig.getBusinessInfo().getOperateDetails();
        List<OperateDetailSaveReqVO> biDetails = updateReqVO.getBusinessInfo().getOperateDetails();
        List<Long> detailsIdsDB = detailsInDB.stream().map(OperateDetailSaveReqVO::getId).collect(Collectors.toList()); // 数据库中已存在的环节明细（商品配置信息）id
        List<Long> willUpdateIds = details.stream().map(OperateDetailSaveReqVO::getId).filter(Objects::nonNull).collect(Collectors.toList()); // 页面传过来拥有id的数据

        List<Long> biDetailsIdsDB = biDetailsInDB.stream().map(OperateDetailSaveReqVO::getId).collect(Collectors.toList()); // 数据库中已存在的环节明细（商户配置信息）id
        List<Long> biWillUpdateIds = biDetails.stream().map(OperateDetailSaveReqVO::getId).filter(Objects::nonNull).collect(Collectors.toList()); // 页面传过来拥有id的数据

        List<OperateDetailSaveReqDTO> createOperateDetails = new ArrayList<>();
        List<BlockCertificateUpdateReqDTO> updateBlockCertificates = new ArrayList<>(); // 待更新的列表

        BlockCertificateUpdateReqDTO businessInfo = new BlockCertificateUpdateReqDTO();
        BeanUtil.copyProperties(goodsConfig.getBusinessInfo(), businessInfo);
        // 这里暂时开放规则：已上链和未上链均可以修改环节名称等信息
        // 需要删除的明细id集合
        List<Long> deleteDetailIds = biDetailsIdsDB.stream().filter(d -> !biWillUpdateIds.contains(d)).collect(Collectors.toList()); // 找出需要删除的数据id

        businessInfo.setLinkName(updateReqVO.getBusinessInfo().getLinkName());
        // 是否上链 上链未做完，这边只改状态
        businessInfo.setChainState(updateReqVO.getBusinessInfo().getChainState());
        businessInfo.setScanShow(updateReqVO.getBusinessInfo().getScanShow());// 改为不管什么时候都可以修改是否展示
        businessInfo.setBelongBusinessId(goodsConfig.getBelongBusinessId());
        businessInfo.setBelongBusinessName(goodsConfig.getBelongBusinessName());

        List<OperateDetailSaveReqDTO> businessDetailSaves = new ArrayList<>();
        updateReqVO.getBusinessInfo().getOperateDetails().forEach(detail -> {
            OperateDetailSaveReqDTO operateDetail = new OperateDetailSaveReqDTO();
            if(detail.getId() != null) {
                BeanUtil.copyProperties(detail, operateDetail);
                businessDetailSaves.add(operateDetail);
            } else {
                // 新增操作
                this.setOperateDetail(detail, operateDetail, businessInfo);
                createOperateDetails.add(operateDetail);
            }
        });
        businessInfo.setDetails(businessDetailSaves);
        updateBlockCertificates.add(businessInfo);

        BlockCertificateUpdateReqDTO goodsInfo = new BlockCertificateUpdateReqDTO();
        BeanUtil.copyProperties(goodsConfig.getGoodsInfo(), goodsInfo);
        // 这里暂时开放规则：已上链和未上链均可以修改环节名称等信息
        deleteDetailIds.addAll(detailsIdsDB.stream().filter(d -> !willUpdateIds.contains(d)).collect(Collectors.toList())); // 找出需要删除的数据id

        goodsInfo.setLinkName(updateReqVO.getGoodsInfo().getLinkName());
        // 是否上链 上链未做完，这边只改状态
        goodsInfo.setChainState(updateReqVO.getGoodsInfo().getChainState());
        goodsInfo.setScanShow(updateReqVO.getGoodsInfo().getScanShow());// 改为不管什么时候都可以修改是否展示
        goodsInfo.setBelongBusinessId(goodsConfig.getBelongBusinessId());
        goodsInfo.setBelongBusinessName(goodsConfig.getBelongBusinessName());

        List<OperateDetailSaveReqDTO> operateDetailSaves = new ArrayList<>();
        updateReqVO.getGoodsInfo().getOperateDetails().forEach(detail -> {
            OperateDetailSaveReqDTO operateDetail = new OperateDetailSaveReqDTO();
            if(detail.getId() != null) {
                BeanUtil.copyProperties(detail, operateDetail);
                operateDetailSaves.add(operateDetail);
            } else {
                // 新增操作
                this.setOperateDetail(detail, operateDetail, goodsInfo);
                createOperateDetails.add(operateDetail);
            }
        });

        goodsInfo.setDetails(operateDetailSaves);
        if(!deleteDetailIds.isEmpty()) {
            operateDetailApi.deleteOperateDetailBatch(deleteDetailIds);
        }
        if(!createOperateDetails.isEmpty()) { // 新增明细
            operateDetailApi.createOperateDetailBatch(createOperateDetails);
        }

        if(!updateBlockCertificates.isEmpty()) {
            blockCertificateApi.updateBlockCertificateBatch(updateBlockCertificates);
        }
    }

    private void setBlockCertificate(BlockCertificateCreateReqDTO blockCertificate, Integer operateType, String operateName, HarvestBatchRespVO harvestBatch,
            BlockCertificateSaveReqVO saveReqVO) {
        blockCertificate.setChainOperateId(CodeEnum.CHAIN_OPERATE_CODE.getCode());
        blockCertificate.setOperateType(operateType); // 操作类型
        blockCertificate.setOperateName(operateName); //
        blockCertificate.setBatchId(harvestBatch.getHarvestBatchId());
        blockCertificate.setBatchType(BatchTypeEnum.HARVEST_BATCH.getType());
        // 上链未做完，这里只改状态
        blockCertificate.setChainState(saveReqVO.getChainState()); // 上链状态（是否自动上链
        blockCertificate.setBelongBusinessId(harvestBatch.getBelongBusinessId());
        blockCertificate.setBelongBusinessName(harvestBatch.getBelongBusinessName());
        blockCertificate.setLinkId(CodeEnum.TRACE_LINK_CODE.getCode());
        blockCertificate.setLinkName(saveReqVO.getLinkName());
//        if(saveReqVO.getChainState().equals(ChainStateEnum.ON_CHAIN.getState())) {
            blockCertificate.setScanShow(saveReqVO.getScanShow());
//        }
        blockCertificate.setSort(saveReqVO.getSort());

        this.setOperateDetails(saveReqVO.getOperateDetails(), blockCertificate);
    }

    /**
     * 设置将要保存的区块上链操作具体上链信息
     */
    private void setOperateDetails(List<OperateDetailSaveReqVO> reqDetails, BlockCertificateCreateReqDTO blockCertificate) {
        List<OperateDetailSaveReqDTO> operateDetails = new ArrayList<>();
        for(OperateDetailSaveReqVO detail: reqDetails) {
            OperateDetailSaveReqDTO operateDetail = new OperateDetailSaveReqDTO();
            this.setOperateDetail(detail, operateDetail, blockCertificate);
            operateDetails.add(operateDetail);
        }
        blockCertificate.setDetails(operateDetails);
    }

    private void setOperateDetail(OperateDetailSaveReqVO detail, OperateDetailSaveReqDTO operateDetail, BlockCertificateBaseReqDTO blockCertificate) {
        BeanUtil.copyProperties(detail, operateDetail);

        operateDetail.setId(null);// 不管页面传不传，这里重置成null
        operateDetail.setChainOperateId(blockCertificate.getChainOperateId());
        operateDetail.setOperateInfo(BatchTypeEnum.HARVEST_BATCH.getName());
        this.verifyFieldAndSetOperateDetail(detail, operateDetail);
        operateDetail.setBelongBusinessId(blockCertificate.getBelongBusinessId());
        operateDetail.setBelongBusinessName(blockCertificate.getBelongBusinessName());
    }

    private void verifyFieldAndSetOperateDetail(OperateDetailSaveReqVO detail, OperateDetailSaveReqDTO operateDetail) {
        // 校验标题内容
        if(!detail.getType().equals(OperateDetailTypeEnum.NO_TITLE_TEXT.getType()) && !detail.getType().equals(OperateDetailTypeEnum.NO_TITLE_LONG_TEXT.getType())
                && !detail.getType().equals(OperateDetailTypeEnum.BIG_IMAGE.getType())
                && !detail.getType().equals(OperateDetailTypeEnum.NO_TITLE_IMAGE.getType())
                && !detail.getType().equals(OperateDetailTypeEnum.NO_TITLE_BIG_IMAGE.getType())
                && !detail.getType().equals(OperateDetailTypeEnum.NO_TITLE_VIDEO.getType())
                && !detail.getType().equals(OperateDetailTypeEnum.NO_TITLE_MAP.getType())
                && !detail.getType().equals(OperateDetailTypeEnum.NO_TITLE_POINT_MAP.getType())
                && StringUtils.isBlank(detail.getTitle())
        ) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.OPERATE_TITLE_CAN_NOT_BE_NULL);
        }
        if(!detail.getType().equals(OperateDetailTypeEnum.TEXT.getType()) && !detail.getType().equals(OperateDetailTypeEnum.NO_TITLE_TEXT.getType())) {
            operateDetail.setLinkText("");
        }
        if(detail.getTitle() == null) {
            operateDetail.setTitle("");// 设置一个空字符串
        }
        if(detail.getContent() == null) {
            operateDetail.setContent("");// 设置一个空字符串
        }
//        if(blockCertificate.getChainState().equals(ChainStateEnum.NOT_ON_CHAIN.getState())
//                && !blockCertificate.getOperateType().equals(OperateTypeEnum.JOB.getType())) {
//            operateDetail.setScanShow(Boolean.TRUE);// 未上链并且不是作业类型的写死成true
//        } else {
        operateDetail.setScanShow(detail.getScanShow());
//        }
        operateDetail.setSort(detail.getSort() == null ? BigInteger.ZERO.intValue() : detail.getSort());
    }

    @Override
    public LinkConfigRespVO getLinkConfig(Long id) {
        // 根据批次id 查询该采收批次信息
        HarvestBatchRespVO harvestBatch = this.verifyHarvestBatch(id, null);
        LinkConfigRespVO result = new LinkConfigRespVO();
        BeanUtil.copyProperties(harvestBatch, result);

        // 查询环节配置信息
        BlockCertificateReqDTO blockCertificateDTO = new BlockCertificateReqDTO();
        blockCertificateDTO.setOperateType(OperateTypeEnum.LINK.getType());// 查询环节信息类型
        blockCertificateDTO.setBatchType(BatchTypeEnum.HARVEST_BATCH.getType());// 查询类型为采收批次的类型
        blockCertificateDTO.setBatchId(harvestBatch.getHarvestBatchId());
        List<BlockCertificateRespDTO> respDTOs = blockCertificateApi.getBlockCertificateList(blockCertificateDTO).getData();

        List<BlockCertificateSaveReqVO> links = new ArrayList<>();
        respDTOs.forEach(blockDTO -> {
            BlockCertificateSaveReqVO blockCertificate = new BlockCertificateSaveReqVO();
            BeanUtil.copyProperties(blockDTO, blockCertificate);
            List<OperateDetailSaveReqVO> details = this.getOperateDetails(blockDTO.getOperateDetails());
            blockCertificate.setOperateDetails(details);
            links.add(blockCertificate);
        });
        result.setLinks(links);
        return result;
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void updateLinkConfig(LinkConfigSaveReqVO updateReqVO) {
        // 根据批次id 查询该采收批次信息
        HarvestBatchRespVO harvestBatch = this.verifyHarvestBatch(updateReqVO.getId(), null);

        // 查询环节信息
        BlockCertificateReqDTO blockCertificateDTO = new BlockCertificateReqDTO();
        blockCertificateDTO.setOperateType(OperateTypeEnum.LINK.getType());// 查询环节信息类型
        blockCertificateDTO.setBatchType(BatchTypeEnum.HARVEST_BATCH.getType());// 查询类型为采收批次的类型
        blockCertificateDTO.setBatchId(harvestBatch.getHarvestBatchId());
        List<BlockCertificateRespDTO> respDTOs = blockCertificateApi.getBlockCertificateList(blockCertificateDTO).getData();

        Map<Long, List<Long>> odIdsDBMap = new HashMap<>();// 数据库中已有的操作ID集合, 以map存储
        Map<Long, OperateDetailRespDTO> odDBMap = new HashMap<>();
        Map<Long, BlockCertificateRespDTO> bcDBMap = new HashMap<>();
        List<Long> linkIdsDB = respDTOs.stream().map(link -> {
            bcDBMap.put(link.getId(), link);
            link.getOperateDetails().forEach(detail -> odDBMap.put(detail.getId(), detail));
            // 懒得另外定义一个变量， 这边再次循环一次
            odIdsDBMap.put(link.getId(), link.getOperateDetails().stream().map(OperateDetailRespDTO::getId).collect(Collectors.toList()));
            return link.getId();
        }).collect(Collectors.toList());// 数据库中已有的环节ID集合
        List<Long> hasOnChainLinkIds = respDTOs.stream().filter(req -> req.getChainState().equals(ChainStateEnum.ON_CHAIN.getState()))
                .map(BlockCertificateRespDTO::getId).collect(Collectors.toList());// 数据库中已有的已上链的环节ID集合
        List<Long> deleteCertificateIds = new ArrayList<>();// 需要删除的证书列表
        List<Long> deleteDetailIds = new ArrayList<>();// 需要删除的操作明细列表
        List<BlockCertificateCreateReqDTO> createBlockCertificates = new ArrayList<>();// 需要新增的证书列表
        List<BlockCertificateUpdateReqDTO> updateBlockCertificates = new ArrayList<>(); // 待更新的列表
        // 明细单独新增到已有证书下时才需要放入以下集合中
        List<OperateDetailSaveReqDTO> createOperateDetails = new ArrayList<>();// 需要新增的操作明细列表

        List<BlockCertificateSaveReqVO> linkReqs = updateReqVO.getLinkInfos();
        if(linkReqs != null && !linkReqs.isEmpty()) {
            List<Long> willUpdateLinkIds = new ArrayList<>();

            linkReqs.forEach(linkReq -> {
                // 根据id判断是更新还是新增
                if(linkReq.getId() != null) {
                    // 更新
                    if(!linkIdsDB.contains(linkReq.getId())) { // 环节配置不存在
                        throw ServiceExceptionUtil.exception(ErrorCodeConstants.LINK_CONFIG_NOT_EXISTS);
                    }
                    // 放入将要更新的环节id集合
                    willUpdateLinkIds.add(linkReq.getId());
                    BlockCertificateUpdateReqDTO blockCertificate = new BlockCertificateUpdateReqDTO();
                    BeanUtil.copyProperties(bcDBMap.get(linkReq.getId()), blockCertificate);

                    // 判断上链状态
//                    if(bcDBMap.get(linkReq.getId()).getChainState().equals(ChainStateEnum.NOT_ON_CHAIN.getState())) {
                        // 未上链
                        blockCertificate.setLinkName(linkReq.getLinkName());
                        blockCertificate.setChainState(linkReq.getChainState());
//                        if(linkReq.getChainState().equals(ChainStateEnum.ON_CHAIN.getState())) {
                        blockCertificate.setScanShow(linkReq.getScanShow());
//                        }
                        blockCertificate.setSort(linkReq.getSort());

                        List<Long> willUpdateDetailIds = new ArrayList<>();// 将要更新的操作明细集合
                        List<OperateDetailSaveReqDTO> operateDetails = new ArrayList<>();
                        linkReq.getOperateDetails().forEach(detail -> {
                            OperateDetailSaveReqDTO operateDetail = new OperateDetailSaveReqDTO();
                            if(detail.getId() != null) {
                                if(!odIdsDBMap.get(linkReq.getId()).contains(detail.getId())) {
                                    throw ServiceExceptionUtil.exception(ErrorCodeConstants.OPERATE_DETAIL_NOT_EXISTS);
                                }
                                BeanUtil.copyProperties(odDBMap.get(detail.getId()), operateDetail);
                                operateDetail.setType(detail.getType());
                                operateDetail.setTitle(detail.getTitle());
                                operateDetail.setContent(detail.getContent());
                                this.verifyFieldAndSetOperateDetail(detail, operateDetail);

                                operateDetails.add(operateDetail);
                                willUpdateDetailIds.add(detail.getId());
                            } else {
                                // 新增操作
                                this.setOperateDetail(detail, operateDetail, blockCertificate);
                                createOperateDetails.add(operateDetail);
                            }
                        });
                        blockCertificate.setDetails(operateDetails);

                        // 未上链才可进行删除操作
                        deleteDetailIds.addAll(odIdsDBMap.get(linkReq.getId()).stream().filter(id -> !willUpdateDetailIds.contains(id)).collect(Collectors.toList()));
//                    } else {
//                        // 已上链状态
//                        blockCertificate.setScanShow(linkReq.getScanShow());
//                        blockCertificate.setSort(linkReq.getSort());
//
//                        List<OperateDetailSaveReqDTO> operateDetails = new ArrayList<>();
//                        // 只修改数据库里面有的
//                        linkReq.getOperateDetails().forEach(detail -> {
//                            if(odIdsDBMap.get(linkReq.getId()).contains(detail.getId())) {
//                                OperateDetailSaveReqDTO operateDetail = new OperateDetailSaveReqDTO();
//                                BeanUtil.copyProperties(odDBMap.get(detail.getId()), operateDetail);
//                                operateDetail.setScanShow(detail.getScanShow());
//                                operateDetails.add(operateDetail);
//                            }
//                        });
//                        blockCertificate.setDetails(operateDetails);
//                    }

                    updateBlockCertificates.add(blockCertificate);
                } else {
                    // 新增
                    // 商品环节信息
                    BlockCertificateCreateReqDTO blockCertificate = new BlockCertificateCreateReqDTO();
                    this.setBlockCertificate(blockCertificate, OperateTypeEnum.LINK.getType(), OperateTypeEnum.LINK.getName(), harvestBatch, linkReq);

                    createBlockCertificates.add(blockCertificate);
                }
            });

            deleteCertificateIds.addAll(linkIdsDB.stream().filter(id -> !willUpdateLinkIds.contains(id)).collect(Collectors.toList()));
        } else if(!linkIdsDB.isEmpty()) {
            // 说明是全部删除
            deleteCertificateIds.addAll(linkIdsDB);
        }

        if(!hasOnChainLinkIds.isEmpty()) {
            // 判断删除的id中是否有已上链的数据
            deleteCertificateIds.forEach(id -> {
                if(hasOnChainLinkIds.contains(id)) {
                    throw ServiceExceptionUtil.exception(ErrorCodeConstants.ON_CHAIN_LINK_CONFIG_CAN_NOT_DELETE);
                }
            });
        }

        if(!deleteCertificateIds.isEmpty()) {
            blockCertificateApi.deleteBlockCertificateBatch(deleteCertificateIds);
        }

        if(!deleteDetailIds.isEmpty()) {
            operateDetailApi.deleteOperateDetailBatch(deleteDetailIds);
        }

        if(!createBlockCertificates.isEmpty()) {
            blockCertificateApi.createBlockCertificateBatch(createBlockCertificates);
        }

        if(!createOperateDetails.isEmpty()) {// 新增明细
            operateDetailApi.createOperateDetailBatch(createOperateDetails);
        }
        if(!updateBlockCertificates.isEmpty()) {
            blockCertificateApi.updateBlockCertificateBatch(updateBlockCertificates);
        }
    }

    @Override
    public FarmingConfigRespVO getFarmingConfig(Long id) {
        // 根据批次id 查询该采收批次信息
        HarvestBatchRespVO harvestBatch = this.verifyHarvestBatch(id, null);
//        if(harvestBatch.getBlockState().equals(BlockStateEnum.FREEZE.getBlockState())) {
//            throw ServiceExceptionUtil.exception(ErrorCodeConstants.BLOCK_STATE_IS_FREEZE);
//        }
        FarmingConfigRespVO result = new FarmingConfigRespVO();
        BeanUtil.copyProperties(harvestBatch, result);

        // 查询农事计划信息
        BlockCertificateReqDTO plantBCDTO = new BlockCertificateReqDTO();
        plantBCDTO.setOperateType(OperateTypeEnum.PLAN.getType());// 查询农事计划
        plantBCDTO.setBatchType(BatchTypeEnum.HARVEST_BATCH.getType());// 查询类型为采收批次的类型
        plantBCDTO.setBatchId(harvestBatch.getHarvestBatchId());
        List<BlockCertificateRespDTO> plantRespDTOs = blockCertificateApi.getBlockCertificateList(plantBCDTO).getData();

        // 查询农事作业信息
        BlockCertificateReqDTO jobBCDTO = new BlockCertificateReqDTO();
        // jobBCDTO.setOperateType(OperateTypeEnum.JOB.getType());// 查询农事作业
        List<Integer> operateTypes = new ArrayList<>();
        operateTypes.add(OperateTypeEnum.JOB.getType());
        operateTypes.add(OperateTypeEnum.JOB_INPUT.getType());
        jobBCDTO.setOperateTypes(operateTypes);
        jobBCDTO.setBatchType(BatchTypeEnum.HARVEST_BATCH.getType());// 查询类型为采收批次的类型
        jobBCDTO.setBatchId(harvestBatch.getHarvestBatchId());
        List<BlockCertificateRespDTO> jobRespDTOs = blockCertificateApi.getBlockCertificateList(jobBCDTO).getData();
        Map<String, List<BlockCertificateRespDTO>> jobRespMap = new HashMap<>();
        jobRespDTOs.forEach(resp -> {
            List<BlockCertificateRespDTO> list = jobRespMap.get(resp.getParentOperateId());
            if(resp.getParentOperateId() != null && !resp.getParentOperateId().isEmpty() && list == null) {
                list = new ArrayList<>();
                list.add(resp);
                jobRespMap.put(resp.getParentOperateId(), list);
            } else if(resp.getParentOperateId() != null && !resp.getParentOperateId().isEmpty()) {
                list.add(resp);
                jobRespMap.put(resp.getParentOperateId(), list);
            }
        });

        List<FarmingPlantReqVO> farmingPlans = new ArrayList<>();
        plantRespDTOs.forEach(plant -> {
            FarmingPlantReqVO plantBC = new FarmingPlantReqVO();
            BeanUtil.copyProperties(plant, plantBC);
            // 循环设置明细
            List<OperateDetailSaveReqVO> plantDetails = this.getOperateDetails(plant.getOperateDetails());
            plantBC.setOperateDetails(plantDetails);

            // 循环设置农事作业信息
            List<BlockCertificateSaveReqVO> farmingJobs = new ArrayList<>();
            if(jobRespMap.get(plant.getChainOperateId()) != null) {
                jobRespMap.get(plant.getChainOperateId()).forEach(job -> {
                    BlockCertificateSaveReqVO jobBC = new BlockCertificateSaveReqVO();
                    BeanUtil.copyProperties(job, jobBC);
                    // 循环设置明细
                    List<OperateDetailSaveReqVO> jobDetails = this.getOperateDetails(job.getOperateDetails());
                    jobBC.setOperateDetails(jobDetails);
                    farmingJobs.add(jobBC);
                });
            }
            plantBC.setFarmingJobs(farmingJobs);
            farmingPlans.add(plantBC);
        });

        result.setFarmingPlans(farmingPlans);
        return result;
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void updateFarmingConfig(FarmingConfigSaveReqVO updateReqVO) {
        // 直接使用已有方法，避免又报代码重复
//        FarmingConfigRespVO respVO = this.getFarmingConfig(updateReqVO.getId());
//        HarvestBatchDO harvestBatch = new HarvestBatchDO();
//        BeanUtil.copyProperties(respVO, harvestBatch);
//        // 是否已上链
//        boolean onChain = !respVO.getFarmingPlans().isEmpty() && respVO.getFarmingPlans().get(0).getChainState().equals(ChainStateEnum.ON_CHAIN.getState());
//        if(onChain && updateReqVO.getChainState().equals(ChainStateEnum.NOT_ON_CHAIN.getState())) {
//            throw ServiceExceptionUtil.exception(ErrorCodeConstants.FARMING_CONFIG_HAS_ON_CHAIN); // 已上链的无法修改上链状态
//        }
//
//        List<Long> willUpdatePlanIds = new ArrayList<>();
//        List<Long> willUpdateJobIds = new ArrayList<>();
//        Map<Long, FarmingPlantSaveReqVO> reqPlanMap = new HashMap<>();
//        Map<String, BlockCertificateSaveReqVO> reqJobMap = new HashMap<>();
//        Map<Long, FarmingPlantSaveReqVO> willUpdatePlanMap = new HashMap<>();
//        Map<Long, BlockCertificateSaveReqVO> willUpdateJobMap = new HashMap<>();
//        Map<Long, String> planRemarksMap = new HashMap<>();
//        Map<String, String> jobRemarksMap = new HashMap<>();
//        List<Long> planIds = new ArrayList<>();
//        updateReqVO.getFarmingPlans().forEach(plan -> {
//            if(plan.getId() != null) {
//                willUpdatePlanIds.add(plan.getId());
//                willUpdatePlanMap.put(plan.getId(), plan);
//            }
//            if(plan.getOperateObjId() != null) {
//                reqPlanMap.put(plan.getOperateObjId(), plan);
//                planIds.add(plan.getOperateObjId());
//                plan.getOperateDetails().forEach(detail -> {
//                    if(detail.getTitle().equals("说明")) {
//                        planRemarksMap.put(plan.getOperateObjId(), detail.getContent());
//                    }
//                });
//            }
//            plan.getFarmingJobs().forEach(job -> {
//                if(job.getOperateType() == null) {
//                    throw ServiceExceptionUtil.exception(ErrorCodeConstants.JOB_OPERATE_TYPE_CAN_NOT_BE_NULL);
//                }
//                if(job.getId() != null) {
//                    willUpdateJobIds.add(job.getId());
//                    willUpdateJobMap.put(job.getId(), job);
//                }
//                if(job.getOperateObjId() != null) {
//                    reqJobMap.put(job.getOperateType() + "" + job.getOperateObjId(), job);
//                    job.getOperateDetails().forEach(detail -> {
//                        if(detail.getTitle().equals("说明")) {
//                            jobRemarksMap.put(job.getOperateType() + "" + job.getOperateObjId(), detail.getContent());
//                        }
//                    });
//                }
//            });
//        });
//
//        List<Long> deleteCertificateIds = new ArrayList<>();// 需要删除的证书列表
//        List<BlockCertificateCreateReqDTO> createBlockCertificates = new ArrayList<>();// 需要新增的证书列表
//        List<BlockCertificateUpdateReqDTO> updateBlockCertificates = new ArrayList<>(); // 待更新的列表
//
//        // 每次重新选择地块计划之后，旧的都会进行删除操作
//        // 只要没传id 都当做新增
//        if(willUpdatePlanIds.isEmpty()) {
//            // 新增
//            // 已上链无法进行新增操作
////            if(onChain) {
////                throw ServiceExceptionUtil.exception(ErrorCodeConstants.CAN_NOT_CREATE_WHEN_FARMING_CONFIG_HAS_ON_CHAIN);
////            }
//
//            // 获取种植计划以及种植作业相关数据
//            // 这里直接使用页面调用的获取接口， 由于页面无法进行过多的变更，故这里的数据为了保证准确性（不被串改），无法修改的字段直接用该接口的数据, 如果没传，就按默认。
//            List<FarmingPlantReqVO> plantDBs = landPlanService.getLandPlanForFarmingConfig(respVO.getGoodsId(), planIds, null, BlockStateEnum.ACTIVATION.getBlockState());
//            plantDBs.forEach(plantConfig -> {
//                BlockCertificateCreateReqDTO createPlant = new BlockCertificateCreateReqDTO();
//                BeanUtil.copyProperties(plantConfig, createPlant);
//                this.setBlockCertificate(createPlant, OperateTypeEnum.PLAN.getType(), OperateTypeEnum.PLAN.getName(), harvestBatch, plantConfig);
//                // createPlant.setRemarks(reqPlanMap.get(plantConfig.getOperateObjId()).getRemarks());// 修改remark字段
//                // 循环找到说明字段，并进行修改
//                plantConfig.getOperateDetails().forEach(detail -> {
//                    if(detail.getTitle().equals("说明")) {
//                        detail.setContent(planRemarksMap.get(plantConfig.getOperateObjId()));
//                    }
//                });
//                // 修改上链状态
//                createPlant.setChainState(updateReqVO.getChainState());
//                // 修改是否展示
//                createPlant.setScanShow(reqPlanMap.get(plantConfig.getOperateObjId()).getScanShow());
//                // 修改环节名称
//                createPlant.setLinkName(reqPlanMap.get(plantConfig.getOperateObjId()).getLinkName());
//
//                createBlockCertificates.add(createPlant);
//                // 循环农事作业
//                plantConfig.getFarmingJobs().forEach(job -> {
//                    BlockCertificateCreateReqDTO createJob = new BlockCertificateCreateReqDTO();
//                    BeanUtil.copyProperties(job, createJob);
//                    // 找到备注字段，并设置值
//                    job.getOperateDetails().forEach(detail -> {
//                        if(detail.getTitle().equals("说明")) {
//                            detail.setContent(jobRemarksMap.get(job.getOperateType() + "" + job.getOperateObjId()));
//                        }
//                    });
//
//                    this.setBlockCertificate(createJob, OperateTypeEnum.JOB.getType(), OperateTypeEnum.JOB.getName(), harvestBatch, job);
//                    // createJob.setRemarks(reqJobMap.get(job.getOperateObjId()).getRemarks());// 修改remark字段
//                    // 修改上链状态
//                    createJob.setChainState(updateReqVO.getChainState());
//                    createJob.setScanShow(reqJobMap.get(job.getOperateType() + "" + job.getOperateObjId()).getScanShow());// 修改扫码展示
//                    createJob.setParentOperateId(createPlant.getChainOperateId());// 设置该字段与农事计划作绑定
//
//                    createBlockCertificates.add(createJob);
//                });
//            });
//
//            // 删除所有旧的数据
//            respVO.getFarmingPlans().forEach(plant -> {
//                plant.getFarmingJobs().forEach(job -> deleteCertificateIds.add(job.getId()));
//                deleteCertificateIds.add(plant.getId());
//            });
//        } else {
//            // 编辑
//            // 此时不会做新增操作
//            respVO.getFarmingPlans().forEach(plant -> {
//                if(willUpdatePlanIds.contains(plant.getId())) {
//                    // 只更新已存在的，其他无视
//                    FarmingPlantSaveReqVO plantReq = willUpdatePlanMap.get(plant.getId());
//                    BlockCertificateUpdateReqDTO updatePlant = new BlockCertificateUpdateReqDTO();
//                    BeanUtil.copyProperties(plant, updatePlant);
//                    // 这里换成 已上链和未上链都可修改
//                    updatePlant.setScanShow(plantReq.getScanShow());
//                    updatePlant.setChainState(updateReqVO.getChainState());
//                    updatePlant.setLinkName(reqPlanMap.get(plant.getOperateObjId()).getLinkName());
//                    List<OperateDetailSaveReqDTO> details = new ArrayList<>();
//                    // 找到备注， 更新备注
//                    this.setFarmingRemarks(plant.getOperateDetails(), details, planRemarksMap.get(plant.getOperateObjId()));
//                    updatePlant.setDetails(details);
//
//                    plant.getFarmingJobs().forEach(job -> {
//                        // 页面如果不传
//                        if(willUpdateJobIds.contains(job.getId())) {
//                            // 只更新已存在的，其他无视
//                            BlockCertificateSaveReqVO jobReq = willUpdateJobMap.get(job.getId());
//                            BlockCertificateUpdateReqDTO updateJob = new BlockCertificateUpdateReqDTO();
//                            BeanUtil.copyProperties(job, updateJob);
////                            if(!onChain) {// 判断数据库中的上链状态是否为未上链
//                            List<OperateDetailSaveReqDTO> jobDetails = new ArrayList<>();
//                            // 找到备注， 更新备注
//                            this.setFarmingRemarks(job.getOperateDetails(), jobDetails, jobRemarksMap.get(job.getOperateType() + "" + job.getOperateObjId()));
//                            updateJob.setDetails(jobDetails);
////                            }
//                            updateJob.setScanShow(jobReq.getScanShow());
//                            updateJob.setChainState(updatePlant.getChainState());
//
//                            updateBlockCertificates.add(updateJob);
//                        } else {
//                            // 如果未上链， 则可进行删除操作( 这里也去掉限制 2023.06.25
//                            deleteCertificateIds.add(job.getId());
//                        }
//                    });
//                    updateBlockCertificates.add(updatePlant);
//                } else {
//                    // 如果未上链， 则可进行删除操作 弃用，现在都可以删除
//                    deleteCertificateIds.add(plant.getId());
//                    plant.getFarmingJobs().forEach(job -> deleteCertificateIds.add(job.getId()));
//                }
//            });
//        }
//
//        if(!deleteCertificateIds.isEmpty()) {
//            blockCertificateApi.deleteBlockCertificateBatch(deleteCertificateIds);
//        }
//
//        if(!createBlockCertificates.isEmpty()) {
//            blockCertificateApi.createBlockCertificateBatch(createBlockCertificates);
//        }
//
//        if(!updateBlockCertificates.isEmpty()) {
//            blockCertificateApi.updateBlockCertificateBatch(updateBlockCertificates);
//        }
    }

    private List<OperateDetailSaveReqVO> getOperateDetails(List<OperateDetailRespDTO> operateDetails) {
        List<OperateDetailSaveReqVO> plantDetails = new ArrayList<>();
        // 循环设置明细
        operateDetails.forEach(detail -> {
            OperateDetailSaveReqVO operateDetail = new OperateDetailSaveReqVO();
            BeanUtil.copyProperties(detail, operateDetail);
            plantDetails.add(operateDetail);
        });
        return plantDetails;
    }

    private void setPlanRemarks(List<OperateDetailSaveReqVO> detailDBs, List<OperateDetailSaveReqDTO> saveDetails, String content) {
        // 找到备注， 更新备注
        detailDBs.forEach(detail -> {
            if(detail.getTitle().equals("说明")) {
                OperateDetailSaveReqDTO detailDB = new OperateDetailSaveReqDTO();
                BeanUtil.copyProperties(detail, detailDB);
                detailDB.setContent(content);
                saveDetails.add(detailDB);
            }
        });
    }

    private void setFarmingRemarks(List<OperateDetailSaveReqVO> detailDBs, List<OperateDetailSaveReqDTO> saveDetails, Map<String, String> jobItemMap) {
        // 找到备注， 更新备注
        detailDBs.forEach(detail -> {
            if(detail.getTitle().equals("任务类型")) {
                OperateDetailSaveReqDTO detailDB = new OperateDetailSaveReqDTO();
                BeanUtil.copyProperties(detail, detailDB);
                detailDB.setContent(jobItemMap.get("jobType"));
                saveDetails.add(detailDB);
            }
            if(detail.getTitle().equals("投入品名称")) {
                OperateDetailSaveReqDTO detailDB = new OperateDetailSaveReqDTO();
                BeanUtil.copyProperties(detail, detailDB);
                detailDB.setContent(jobItemMap.get("inputsName"));
                saveDetails.add(detailDB);
            }
            if(detail.getTitle().equals("作业日期")) {
                OperateDetailSaveReqDTO detailDB = new OperateDetailSaveReqDTO();
                BeanUtil.copyProperties(detail, detailDB);
                detailDB.setContent(jobItemMap.get("jobDate"));
                saveDetails.add(detailDB);
            }
            if(detail.getTitle().equals("作业员工")) {
                OperateDetailSaveReqDTO detailDB = new OperateDetailSaveReqDTO();
                BeanUtil.copyProperties(detail, detailDB);
                detailDB.setContent(jobItemMap.get("jobWorker"));
                saveDetails.add(detailDB);
            }
            if(detail.getTitle().equals("说明")) {
                OperateDetailSaveReqDTO detailDB = new OperateDetailSaveReqDTO();
                BeanUtil.copyProperties(detail, detailDB);
                detailDB.setContent(jobItemMap.get("remarks"));
                saveDetails.add(detailDB);
            }
        });
    }

    @Override
    public Map<String, List<String>> getBatchIdsByGoodsId(List<String> goodsIds, Long businessId, Integer blockState) {
        Map<String, List<String>> resultMap = new HashMap<>();
        harvestBatchMapper.getBatchIdsByGoodsId(goodsIds, businessId, blockState).forEach(result -> resultMap.put(result.getGoodsId(), result.getBatchIds()));
        return resultMap;
    }

    /**
     * 根据商品批次id获取批次所有信息
     *
     * @param harvestBatchId 批次id
     */
    @Override
    public HarvestBatchDO getHarvestBatchByHarvesId(String harvestBatchId) {
        HarvestBatchDO batchDO = new HarvestBatchDO();
        batchDO.setHarvestBatchId(harvestBatchId);
        return harvestBatchMapper.selectOne(new QueryWrapper<>(batchDO));
    }

    /**
     * 根据商户ID，已上链，俩个条件查询出所有采收批次id
     * // 上链状态的条件删除 - 2023.07.17
     * @param businessId 商户编码
     * @param blockState 链状态
     * @return 操作批次编码
     */
    @Override
    public List<HarvestBatchDO> getHarvestBatchByBusinessId(String businessId, Integer blockState) {
        //字段交换
        BusinessInfoDTO businessInfo = businessInfoApi.getBusinessInfoByBusinessId(businessId).getData();
        if (businessInfo == null){
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.BUSINESS_INFO_NOT_EXISTS);
        }

        return harvestBatchMapper.selectList(new LambdaQueryWrapperX<HarvestBatchDO>().eq(HarvestBatchDO::getBelongBusinessId, businessInfo.getId()));
    }

    @Override
    public PreviewRespVO getPreviewData(String harvestBatchId, Long languageTypeId) {
        // 根据批次id 查询该采收批次信息
        HarvestBatchRespVO harvestBatch = harvestBatchMapper.getHarvestBatchDetail(null, harvestBatchId, languageTypeId);
        if(harvestBatch == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.HARVEST_BATCH_NOT_EXISTS);
        }

        PreviewRespVO previewResp = new PreviewRespVO();
        previewResp.setBlockState(harvestBatch.getBlockState());
        if (harvestBatch.getTemplateId() != null) {
            // 查询模板
            UniTemplateDTO uniTemplateDTO = uniTemplateApi.getTemplateById(harvestBatch.getTemplateId()).getData();
            if (uniTemplateDTO == null) {
                throw ServiceExceptionUtil.exception(ErrorCodeConstants.CAN_NOT_FIND__UNI_TEMPLATE);
            }
            previewResp.setUniTemplate(uniTemplateDTO);
        } else {
            // 查询默认模板
            UniTemplateDTO uniTemplateDTO = uniTemplateApi.getDefaultTemplate().getData();
            if (uniTemplateDTO == null) {
                throw ServiceExceptionUtil.exception(ErrorCodeConstants.CAN_NOT_FIND_DEFAULT_UNI_TEMPLATE);
            }
            previewResp.setUniTemplate(uniTemplateDTO);
        }

        this.getAndSetBlockCertificateData(harvestBatch, previewResp, Boolean.FALSE, languageTypeId);
        return previewResp;
    }

    private void getAndSetBlockCertificateData(HarvestBatchRespVO harvestBatch, PreviewRespVO previewResp, Boolean showAll, Long languageTypeId) {
        // 所有采收批次的类型
        BlockCertificateReqDTO blockCertificateDTO = new BlockCertificateReqDTO();
        blockCertificateDTO.setBatchType(BatchTypeEnum.HARVEST_BATCH.getType());// 查询类型为采收批次的类型
        blockCertificateDTO.setBatchId(harvestBatch.getHarvestBatchId());
        blockCertificateDTO.setLanguageTypeId(languageTypeId);
        List<BlockCertificateRespDTO> respDTOs = blockCertificateApi.getBlockCertificateList(blockCertificateDTO).getData();

        List<BlockCertificateSaveReqVO> links = new ArrayList<>();
        List<FarmingPlantReqVO> farmingPlans = new ArrayList<>();
        Map<String, List<BlockCertificateSaveReqVO>> jobMaps = new HashMap<>();
        if(respDTOs != null && !respDTOs.isEmpty()) {
            respDTOs.forEach(respDTO -> {
                if(showAll || respDTO.getScanShow()) {
                    BlockCertificateSaveReqVO blockCertificate = new BlockCertificateSaveReqVO();
                    if (respDTO.getOperateType().equals(OperateTypeEnum.BUSINESS_INFO.getType())) {
                        // 商户信息
                        List<OperateDetailSaveReqVO> details = this.getOperateDetails(respDTO, blockCertificate);
                        blockCertificate.setOperateDetails(details);
                        previewResp.setBusinessInfo(blockCertificate);
                    } else if (respDTO.getOperateType().equals(OperateTypeEnum.GOODS_INFO.getType())) {
                        // 商品信息
                        List<OperateDetailSaveReqVO> details = this.getOperateDetails(respDTO, blockCertificate);
                        blockCertificate.setOperateDetails(details);
                        previewResp.setGoodsInfo(blockCertificate);
                    } else if (respDTO.getOperateType().equals(OperateTypeEnum.LINK.getType())) {
                        // 环节
                        BeanUtil.copyProperties(respDTO, blockCertificate);
                        List<OperateDetailSaveReqVO> details = this.getOperateDetails(respDTO.getOperateDetails());
                        blockCertificate.setOperateDetails(details);
                        links.add(blockCertificate);
                    } else if (respDTO.getOperateType().equals(OperateTypeEnum.PLAN.getType())) {
                        FarmingPlantReqVO farmingPlantReqVO = new FarmingPlantReqVO();
                        // 农事计划
                        BeanUtil.copyProperties(respDTO, farmingPlantReqVO);
                        List<OperateDetailSaveReqVO> details = this.getOperateDetails(respDTO.getOperateDetails());
                        farmingPlantReqVO.setOperateDetails(details);
                        farmingPlans.add(farmingPlantReqVO);
                    } else if ((respDTO.getOperateType().equals(OperateTypeEnum.JOB.getType()) || respDTO.getOperateType().equals(OperateTypeEnum.JOB_INPUT.getType()))) {
                        // 农事作业
                        BeanUtil.copyProperties(respDTO, blockCertificate);
                        List<OperateDetailSaveReqVO> details = this.getOperateDetails(respDTO.getOperateDetails());
                        blockCertificate.setOperateDetails(details);
                        List<BlockCertificateSaveReqVO> jobList = jobMaps.get(blockCertificate.getParentOperateId());
                        if(jobList == null) {
                            jobList = new ArrayList<>();
                        }
                        jobList.add(blockCertificate);
                        jobMaps.put(blockCertificate.getParentOperateId(), jobList);
                    }
                }
            });
        }
        previewResp.setLinkInfos(links);
        farmingPlans.forEach(plan -> {
            List<BlockCertificateSaveReqVO> jobList = new ArrayList<>();
            if(jobMaps.get(plan.getChainOperateId()) != null) {
                jobList.addAll(jobMaps.get(plan.getChainOperateId()));
            }
            plan.setFarmingJobs(jobList);
        });
        previewResp.setFarmingPlans(farmingPlans);

        // 查询检验批次类型
        BlockCertificateReqDTO inspectionBCReq = new BlockCertificateReqDTO();
        inspectionBCReq.setOperateType(OperateTypeEnum.BATCH.getType());
        inspectionBCReq.setBatchType(BatchTypeEnum.INSPECTION_BATCH.getType());// 查询类型为采收批次的类型
        inspectionBCReq.setBatchId(harvestBatch.getHarvestBatchId()); // 入库批次
        inspectionBCReq.setLanguageTypeId(languageTypeId);
        List<BlockCertificateRespDTO> inspectionDTOs = blockCertificateApi.getBlockCertificateList(inspectionBCReq).getData();

        List<InspectionReqVO> inspections = new ArrayList<>();
        if(inspectionDTOs != null && !inspectionDTOs.isEmpty()) {
            Map<String, List<BlockCertificateSaveReqVO>> itemMap = new HashMap<>();
            inspectionDTOs.forEach(respDTO -> {
                if(showAll || respDTO.getScanShow()) {
                    if (respDTO.getParentOperateId().isEmpty()) {
                        // 说明是主表
                        InspectionReqVO blockCertificate = new InspectionReqVO();
                        BeanUtil.copyProperties(respDTO, blockCertificate);
                        List<OperateDetailSaveReqVO> details = this.getOperateDetails(respDTO.getOperateDetails());
                        blockCertificate.setOperateDetails(details);
                        inspections.add(blockCertificate);
                    } else {
                        // 说明是item
                        BlockCertificateSaveReqVO item = new BlockCertificateSaveReqVO();
                        BeanUtil.copyProperties(respDTO, item);
                        if (itemMap.get(respDTO.getParentOperateId()) != null) {
                            itemMap.get(respDTO.getParentOperateId()).add(item);
                        } else {
                            List<BlockCertificateSaveReqVO> items = new ArrayList<>();
                            items.add(item);
                            itemMap.put(respDTO.getParentOperateId(), items);
                        }
                    }
                }
            });
            inspections.forEach(inspection -> {
                List<BlockCertificateSaveReqVO> items = itemMap.get(inspection.getChainOperateId());
                inspection.setInspectionItems(items);
            });
        }
        previewResp.setInspections(inspections);
    }

    @Override
    public List<BlockCertificateSaveReqVO> gatJobData(String chainOperateId) {
        // 所有采收批次的类型
        BlockCertificateReqDTO blockCertificateDTO = new BlockCertificateReqDTO();
//        blockCertificateDTO.setChainState(ChainStateEnum.ON_CHAIN.getState());
//        blockCertificateDTO.setChainStatus(ChainStatusEnum.ACTIVE.getStatus());
        blockCertificateDTO.setParentOperateId(chainOperateId);
        List<BlockCertificateRespDTO> respDTOs = blockCertificateApi.getBlockCertificateList(blockCertificateDTO).getData();
        List<BlockCertificateSaveReqVO> jobs = new ArrayList<>();
        if(respDTOs != null) {
            respDTOs.forEach(resp -> {
                if(resp.getScanShow()) {// 如果展示
                    BlockCertificateSaveReqVO blockCertificate = new BlockCertificateSaveReqVO();
                    BeanUtil.copyProperties(resp, blockCertificate);
                    List<OperateDetailSaveReqVO> details = this.getOperateDetails(resp.getOperateDetails());
                    blockCertificate.setOperateDetails(details);
                    jobs.add(blockCertificate);
                }
            });
        }
        return jobs;
    }

    /**
     * 根据采收批次ID获取采收批次信息
     *
     * @param harvestBatchId 批次ID
     * @return 批次
     */
    @Override
    public HarvestBatchDO getHarvestBatchById(String harvestBatchId) {
        QueryWrapper<HarvestBatchDO> querywrapper = new QueryWrapper<>();
        querywrapper.eq(  "harvest_batch_id",harvestBatchId);
        return harvestBatchMapper.selectOne(querywrapper);
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void updateChainStatus(Long id, Integer state) {
        HarvestBatchRespVO harvestBatchDO = this.verifyHarvestBatch(id, null);

        List<UpdateStatusReqDTO> batchsReqDTOS = new ArrayList<>();
        UpdateStatusReqDTO harvestReqDTO = new UpdateStatusReqDTO();
        harvestReqDTO.setChainOperateId(harvestBatchDO.getBlockChainId());
        harvestReqDTO.setChainStatus(state.equals(BlockStateEnum.ACTIVATION.getBlockState()) ? ChainStatusEnum.ACTIVE.getStatus() : ChainStatusEnum.FREEZE.getStatus());
        batchsReqDTOS.add(harvestReqDTO);

        if(blockCertificateApi.updateStatusBatch(batchsReqDTOS).isError()) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.UPDATE_CREATE_BLOCK_CERTIFICATE_FAIL);
        }

        HarvestBatchDO harvestBatch = new HarvestBatchDO();
        harvestBatch.setId(id);
        harvestBatch.setBlockState(state.equals(BlockStateEnum.ACTIVATION.getBlockState()) ? BlockStateEnum.ACTIVATION.getBlockState() : BlockStateEnum.FREEZE.getBlockState());
        harvestBatchMapper.updateById(harvestBatch);
    }

    @Override
    public HarvestBatchConfigRespVO getHarvestBatchConfig(Long id, Long languageTypeId) {
        // 根据批次id 查询该采收批次信息
        HarvestBatchRespVO harvestBatch = this.verifyHarvestBatch(id, languageTypeId);
        HarvestBatchConfigRespVO result = new HarvestBatchConfigRespVO();

        PreviewRespVO previewRespVO = new PreviewRespVO();
        this.getAndSetBlockCertificateData(harvestBatch, previewRespVO, Boolean.TRUE, languageTypeId);
        BeanUtil.copyProperties(previewRespVO, result);
        BeanUtil.copyProperties(harvestBatch, result);
        if (previewRespVO.getUniTemplate() != null) {
            result.setTemplateId(previewRespVO.getUniTemplate().getId());
        }
        // 商品和企业信息是否为空， 如果是空的填充默认值进去。。。

        // 先改成前端点击【一键导入】，这里暂时不自动填充
        return result;
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void updateHarvestBatchConfig(HarvestBatchConfigSaveReqVO saveReqVO) {
        // 获得数据库已有的配置信息
        HarvestBatchConfigRespVO configRespVO = this.getHarvestBatchConfig(saveReqVO.getId(), saveReqVO.getLanguageTypeId());
        // 校验所选的模板是否存在
        UniTemplateDTO templateDTO = uniTemplateApi.getTemplateById(saveReqVO.getTemplateId()).getData();
        if (templateDTO == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.SELECTED_UNI_TEMPLATE_NOT_EXITS);
        }
        // 获取数据库对应的批次配置
        HarvestBatchConfigDO harvestBatchConfig = harvestBatchConfigMapper.selectOne(new LambdaQueryWrapperX<HarvestBatchConfigDO>()
                .eq(HarvestBatchConfigDO::getHarvestBatchId, configRespVO.getHarvestBatchId()).eq(HarvestBatchConfigDO::getLanguageTypeId, saveReqVO.getLanguageTypeId()));

        HarvestBatchRespVO harvestBatch = new HarvestBatchRespVO();
        BeanUtil.copyProperties(configRespVO, harvestBatch);
        // 获取环境配置
        List<EnvTypeDeviceConfigRespVO> envTypeConfigs = envTypeService.getEnvTypeConfigGroupByLandId(harvestBatch.getBelongBusinessId());

        //******************** 环节相关参数  ********************/
        Map<Long, List<Long>> linkDetailIdsDBMap = new HashMap<>();// 数据库中已有的操作ID集合, 以map存储
        Map<Long, OperateDetailSaveReqVO> linkDetailDBMap = new HashMap<>();
        Map<Long, BlockCertificateSaveReqVO> linkDBMap = new HashMap<>();
        List<Long> linkIdsDB = configRespVO.getLinkInfos().stream().map(link -> {
            linkDBMap.put(link.getId(), link);
            link.getOperateDetails().forEach(detail -> linkDetailDBMap.put(detail.getId(), detail));
            // 懒得另外定义一个变量， 这边再次循环一次
            linkDetailIdsDBMap.put(link.getId(), link.getOperateDetails().stream().map(OperateDetailSaveReqVO::getId).collect(Collectors.toList()));
            return link.getId();
        }).collect(Collectors.toList());// 数据库中已有的环节ID集合

        //******************** 农事计划/作业相关参数  ********************/
//        List<Long> willUpdatePlanIds = new ArrayList<>();
//        List<Long> willUpdateJobIds = new ArrayList<>();
//        Map<Long, FarmingPlantSaveReqVO> reqPlanMap = new HashMap<>();
//        Map<String, BlockCertificateSaveReqVO> reqJobMap = new HashMap<>();
//        Map<Long, FarmingPlantSaveReqVO> willUpdatePlanMap = new HashMap<>();
//        Map<Long, BlockCertificateSaveReqVO> willUpdateJobMap = new HashMap<>();
//        Map<Long, String> planRemarksMap = new HashMap<>();
//        Map<String, Map<String, String>> jobMap = new HashMap<>();
//        List<Long> planIds = new ArrayList<>();
//        saveReqVO.getFarmingPlans().forEach(plan -> {
//            if(plan.getId() != null) {
//                willUpdatePlanIds.add(plan.getId());
//                willUpdatePlanMap.put(plan.getId(), plan);
//            }
//            if(plan.getOperateObjId() != null) {
//                reqPlanMap.put(plan.getOperateObjId(), plan);
//                planIds.add(plan.getOperateObjId());
//                plan.getOperateDetails().forEach(detail -> {
//                    if(detail.getTitle().equals("说明")) {
//                        planRemarksMap.put(plan.getOperateObjId(), detail.getContent());
//                    }
//                });
//            }
//            if(plan.getFarmingJobs() != null) {
//                plan.getFarmingJobs().forEach(job -> {
//                    if (job.getOperateType() == null) {
//                        throw ServiceExceptionUtil.exception(ErrorCodeConstants.JOB_OPERATE_TYPE_CAN_NOT_BE_NULL);
//                    }
//                    if (job.getId() != null) {
//                        willUpdateJobIds.add(job.getId());
//                        willUpdateJobMap.put(job.getId(), job);
//                    }
//                    if (job.getOperateObjId() != null) {
//                        reqJobMap.put(job.getOperateType() + "" + job.getOperateObjId(), job);
//                        Map<String, String> jobItemMap = jobMap.get(job.getOperateType() + "" + job.getOperateObjId());
//                        if (jobItemMap == null) {
//                            jobItemMap = new HashMap<>();
//                        }
//
//                        Map<String, String> finalJobItemMap = jobItemMap;
//                        job.getOperateDetails().forEach(detail -> {
//                            if(detail.getTitle().equals("任务类型")) {
//                                finalJobItemMap.put("jobType", detail.getContent());
//                            }
//                            if(detail.getTitle().equals("投入品名称")) {
//                                finalJobItemMap.put("inputsName", detail.getContent());
//                            }
//                            if(detail.getTitle().equals("作业日期")) {
//                                finalJobItemMap.put("jobDate", detail.getContent());
//                            }
//                            if(detail.getTitle().equals("作业员工")) {
//                                finalJobItemMap.put("jobWorker", detail.getContent());
//                            }
//                            if(detail.getTitle().equals("说明")) {
//                                finalJobItemMap.put("remarks", detail.getContent());
//                            }
//                        });
//
//                        jobMap.put(job.getOperateType() + "" + job.getOperateObjId(), finalJobItemMap);
//                    }
//                });
//            }
//        });

        //******************** 检验检疫相关参数  ********************/
        Map<Long, List<Long>> inspectionDetailIdsDBMap = new HashMap<>();// 数据库中已有的操作ID集合, 以map存储
        Map<Long, OperateDetailSaveReqVO> inspectionDetailDBMap = new HashMap<>();
        Map<Long, InspectionSaveReqVO> inspectionDBMap = new HashMap<>();
        Map<Long, BlockCertificateSaveReqVO> inspectionItemDBMap = new HashMap<>();
        Map<Long, List<Long>> inspectionItemDBIdsMap = new HashMap<>();
        Map<Long, OperateDetailSaveReqVO> inspectionItemDetailMap = new HashMap<>();
        List<Long> inspectionDBIds = configRespVO.getInspections().stream().map(inspection -> {
            inspectionDBMap.put(inspection.getId(), inspection);
            inspection.getOperateDetails().forEach(detail -> inspectionDetailDBMap.put(detail.getId(), detail));
            // 懒得另外定义一个变量， 这边再次循环一次
            inspectionDetailIdsDBMap.put(inspection.getId(), inspection.getOperateDetails().stream().map(OperateDetailSaveReqVO::getId).collect(Collectors.toList()));

            inspectionItemDBIdsMap.put(inspection.getId(), inspection.getInspectionItems() == null ? new ArrayList<>() : inspection.getInspectionItems().stream().map(item -> {
                inspectionItemDBMap.put(item.getId(), item);
                return item.getId();
            }).collect(Collectors.toList()));
            return inspection.getId();
        }).collect(Collectors.toList());
        // 校验检验检疫是否重复添加
        if(saveReqVO.getInspections() != null) {
            Set<Long> willUpdateInspectionSet = saveReqVO.getInspections().stream().map(InspectionSaveReqVO::getOperateObjId).collect(Collectors.toSet());
            if (willUpdateInspectionSet.size() != saveReqVO.getInspections().size()) {
                throw ServiceExceptionUtil.exception(ErrorCodeConstants.EXISTS_THE_SAME_INSPECTION_CONFIG);
            }

            saveReqVO.getInspections().forEach(inspection -> {
                if (!CollectionUtil.isEmpty(inspection.getInspectionItems())) {
                    inspection.getInspectionItems().forEach(item -> {
                        if (!CollectionUtil.isEmpty(item.getOperateDetails())) {
                            item.getOperateDetails().forEach(detail -> {
                                inspectionItemDetailMap.put(detail.getId(), detail);
                            });
                        }
                    });
                }
            });
        }

        //******************** 环境类型配置相关参数  ********************/
        Map<String, List<Long>> envTypeDBMaps = new HashMap<>();
        List<String> hasConfigLandDBIds = new ArrayList<>();
        envTypeConfigs.forEach(config -> {
            envTypeDBMaps.put(config.getLandId(), config.getEnvTypes().stream().map(EnvTypeConfigRespVO::getConfigId).collect(Collectors.toList()));
            hasConfigLandDBIds.add(config.getLandId());
        });


        List<Long> deleteCertificateIds = new ArrayList<>();// 需要删除的证书列表
        List<BlockCertificateCreateReqDTO> createBlockCertificates = new ArrayList<>();// 需要新增的证书列表
        List<BlockCertificateUpdateReqDTO> updateBlockCertificates = new ArrayList<>(); // 待更新的列表

        List<Long> deleteOperateDetailIds = new ArrayList<>();// 需要删除的操作明细列表
        List<OperateDetailSaveReqDTO> createOperateDetails = new ArrayList<>();// 需要新增的操作明细列表

        List<DeviceEnvTypeCreateReqDTO> createDeviceEnvTypes = new ArrayList<>();// 需要新增的环境类型配置
        List<Long> deleteDeviceEnvTypeIds = new ArrayList<>();// 需要删除的环境类型配置

        //********************************* 更新企业信息  **************************************//
        if (saveReqVO.getBusinessInfo() != null) {
            if (configRespVO.getBusinessInfo() != null && saveReqVO.getBusinessInfo().getId() != null) {
                // 编辑流程
                if (!configRespVO.getBusinessInfo().getId().equals(saveReqVO.getBusinessInfo().getId())) {
                    throw ServiceExceptionUtil.exception(ErrorCodeConstants.CONFIG_IS_NOT_EXISTS);
                }
                BlockCertificateUpdateReqDTO businessInfo = new BlockCertificateUpdateReqDTO();
                BlockCertificateSaveReqVO businessInfoReq = saveReqVO.getBusinessInfo();

                BeanUtil.copyProperties(configRespVO.getBusinessInfo(), businessInfo);
                businessInfo.setLinkName(businessInfoReq.getLinkName());
                businessInfo.setScanShow(businessInfoReq.getScanShow());
                businessInfo.setBelongBusinessId(configRespVO.getBelongBusinessId());
                businessInfo.setBelongBusinessName(configRespVO.getBelongBusinessName());

                List<Long> willUpdateIds = new ArrayList<>();
                this.setOperateDetailsForUpdate(businessInfoReq, createOperateDetails, willUpdateIds, businessInfo);
                updateBlockCertificates.add(businessInfo);

                // 找出需要删除的操作明细id
                deleteOperateDetailIds.addAll(configRespVO.getBusinessInfo().getOperateDetails().stream().map(OperateDetailSaveReqVO::getId)
                        .filter(id -> !willUpdateIds.contains(id)).collect(Collectors.toList()));
            } else {
                // 新增流程
                if (configRespVO.getBusinessInfo() != null) { // 重新添加一个新的，所以这里必须删除旧的
                    deleteCertificateIds.add(configRespVO.getBusinessInfo().getId());
                }

                // 商户环节信息
                BlockCertificateCreateReqDTO businessInfo = new BlockCertificateCreateReqDTO();
                businessInfo.setChainOperateId(CodeEnum.CHAIN_OPERATE_CODE.getCode());
                businessInfo.setOperateType(OperateTypeEnum.BUSINESS_INFO.getType()); // 操作类型: 商户信息类型
                businessInfo.setOperateName(OperateTypeEnum.BUSINESS_INFO.getName()); //
                businessInfo.setOperateObjId(configRespVO.getBelongBusinessId()); // 所对应的商户id
                businessInfo.setBatchId(configRespVO.getHarvestBatchId());
                businessInfo.setBatchType(BatchTypeEnum.HARVEST_BATCH.getType());
                businessInfo.setChainState(ChainStateEnum.NOT_ON_CHAIN.getState()); // 上链状态（目前不用了，这里都写入未上链，
                businessInfo.setBelongBusinessId(configRespVO.getBelongBusinessId());
                businessInfo.setBelongBusinessName(configRespVO.getBelongBusinessName());
                businessInfo.setLinkId(CodeEnum.TRACE_LINK_CODE.getCode());
                businessInfo.setLinkName(saveReqVO.getBusinessInfo().getLinkName());
                businessInfo.setLanguageTypeId(saveReqVO.getLanguageTypeId());

                // 设置环节明细
                this.setOperateDetails(saveReqVO.getBusinessInfo().getOperateDetails(), businessInfo);
                createBlockCertificates.add(businessInfo);
            }
        } else if (configRespVO.getBusinessInfo() != null) {
            // 删除旧的
            deleteCertificateIds.add(configRespVO.getBusinessInfo().getId());
        }

        //********************************* 更新商品信息  **************************************//
        if(configRespVO.getGoodsInfo() != null && saveReqVO.getGoodsInfo().getId() != null) {
            // 编辑流程
            if(!configRespVO.getGoodsInfo().getId().equals(saveReqVO.getGoodsInfo().getId())) {
                throw ServiceExceptionUtil.exception(ErrorCodeConstants.CONFIG_IS_NOT_EXISTS);
            }
            BlockCertificateUpdateReqDTO goodsInfo = new BlockCertificateUpdateReqDTO();
            BlockCertificateSaveReqVO goodsInfoReq = saveReqVO.getGoodsInfo();

            BeanUtil.copyProperties(configRespVO.getGoodsInfo(), goodsInfo);
            goodsInfo.setLinkName(goodsInfoReq.getLinkName());
            goodsInfo.setScanShow(goodsInfoReq.getScanShow());
            goodsInfo.setBelongBusinessId(configRespVO.getBelongBusinessId());
            goodsInfo.setBelongBusinessName(configRespVO.getBelongBusinessName());

            List<Long> willUpdateIds = new ArrayList<>();
            this.setOperateDetailsForUpdate(goodsInfoReq, createOperateDetails, willUpdateIds, goodsInfo);
            updateBlockCertificates.add(goodsInfo);

            // 找出需要删除的操作明细id
            deleteOperateDetailIds.addAll(configRespVO.getGoodsInfo().getOperateDetails().stream().map(OperateDetailSaveReqVO::getId)
                    .filter(id -> !willUpdateIds.contains(id)).collect(Collectors.toList()));
        } else {
            // 新增流程
            if(configRespVO.getGoodsInfo() != null) { // 重新添加一个新的，所以这里必须删除旧的
                deleteCertificateIds.add(configRespVO.getGoodsInfo().getId());
            }
            GoodsInfoRespDTO goodsInfoResp = this.getGoodsInfoByGoodsId(configRespVO.getGoodsId(), configRespVO.getBelongBusinessId());

            // 商品环节信息
            BlockCertificateCreateReqDTO goodsInfo = new BlockCertificateCreateReqDTO();
            goodsInfo.setChainOperateId(CodeEnum.CHAIN_OPERATE_CODE.getCode());
            goodsInfo.setOperateType(OperateTypeEnum.GOODS_INFO.getType()); // 操作类型: 商户信息类型
            goodsInfo.setOperateName(OperateTypeEnum.GOODS_INFO.getName()); //
            goodsInfo.setOperateObjId(goodsInfoResp.getId()); // 所对应的商品id
            goodsInfo.setBatchId(configRespVO.getHarvestBatchId());
            goodsInfo.setBatchType(BatchTypeEnum.HARVEST_BATCH.getType());
            goodsInfo.setChainState(ChainStateEnum.NOT_ON_CHAIN.getState()); // 上链状态（目前不用了，这里都写入未上链，
            goodsInfo.setBelongBusinessId(configRespVO.getBelongBusinessId());
            goodsInfo.setBelongBusinessName(configRespVO.getBelongBusinessName());
            goodsInfo.setLinkId(CodeEnum.TRACE_LINK_CODE.getCode());
            goodsInfo.setLinkName(saveReqVO.getGoodsInfo().getLinkName());
            goodsInfo.setLanguageTypeId(saveReqVO.getLanguageTypeId());

            // 设置环节明细
            this.setOperateDetails(saveReqVO.getGoodsInfo().getOperateDetails(), goodsInfo);
            createBlockCertificates.add(goodsInfo);
        }

        //********************************* 更新环节信息  **************************************//
        if(saveReqVO.getLinkInfos() != null && !saveReqVO.getLinkInfos().isEmpty()) {
            List<Long> willUpdateLinkIds = new ArrayList<>();

            saveReqVO.getLinkInfos().forEach(linkReq -> {
                // 根据id判断是更新还是新增
                if(linkReq.getId() != null) {
                    // 更新
                    if(!linkIdsDB.contains(linkReq.getId())) { // 环节配置不存在
                        throw ServiceExceptionUtil.exception(ErrorCodeConstants.LINK_CONFIG_NOT_EXISTS);
                    }
                    // 放入将要更新的环节id集合
                    willUpdateLinkIds.add(linkReq.getId());
                    BlockCertificateUpdateReqDTO blockCertificate = new BlockCertificateUpdateReqDTO();
                    BeanUtil.copyProperties(linkDBMap.get(linkReq.getId()), blockCertificate);

                    blockCertificate.setLinkName(linkReq.getLinkName());
                    blockCertificate.setScanShow(linkReq.getScanShow());
                    blockCertificate.setSort(linkReq.getSort());

                    List<Long> willUpdateDetailIds = new ArrayList<>();// 将要更新的操作明细集合
                    List<OperateDetailSaveReqDTO> operateDetails = new ArrayList<>();
                    linkReq.getOperateDetails().forEach(detail -> {
                        OperateDetailSaveReqDTO operateDetail = new OperateDetailSaveReqDTO();
                        if(detail.getId() != null) {
                            if(!linkDetailIdsDBMap.get(linkReq.getId()).contains(detail.getId())) {
                                throw ServiceExceptionUtil.exception(ErrorCodeConstants.OPERATE_DETAIL_NOT_EXISTS);
                            }
                            BeanUtil.copyProperties(linkDetailDBMap.get(detail.getId()), operateDetail);
                            operateDetail.setType(detail.getType());
                            operateDetail.setTitle(detail.getTitle());
                            operateDetail.setContent(detail.getContent());
                            this.verifyFieldAndSetOperateDetail(detail, operateDetail);

                            operateDetails.add(operateDetail);
                            willUpdateDetailIds.add(detail.getId());
                        } else {
                            // 新增操作
                            this.setOperateDetail(detail, operateDetail, blockCertificate);
                            operateDetail.setBelongBusinessId(configRespVO.getBelongBusinessId());
                            operateDetail.setBelongBusinessName(configRespVO.getBelongBusinessName());
                            createOperateDetails.add(operateDetail);
                        }
                    });
                    blockCertificate.setDetails(operateDetails);

                    deleteOperateDetailIds.addAll(linkDetailIdsDBMap.get(linkReq.getId()).stream().filter(id -> !willUpdateDetailIds.contains(id)).collect(Collectors.toList()));

                    updateBlockCertificates.add(blockCertificate);
                } else {
                    // 新增
                    BlockCertificateCreateReqDTO blockCertificate = new BlockCertificateCreateReqDTO();
                    blockCertificate.setChainOperateId(CodeEnum.CHAIN_OPERATE_CODE.getCode());
                    blockCertificate.setOperateType(OperateTypeEnum.LINK.getType()); // 操作类型
                    blockCertificate.setOperateName(OperateTypeEnum.LINK.getName()); //
                    blockCertificate.setBatchId(configRespVO.getHarvestBatchId());
                    blockCertificate.setBatchType(BatchTypeEnum.HARVEST_BATCH.getType());
                    blockCertificate.setChainState(ChainStateEnum.NOT_ON_CHAIN.getState());
                    blockCertificate.setBelongBusinessId(configRespVO.getBelongBusinessId());
                    blockCertificate.setBelongBusinessName(configRespVO.getBelongBusinessName());
                    blockCertificate.setLinkId(CodeEnum.TRACE_LINK_CODE.getCode());
                    blockCertificate.setLinkName(linkReq.getLinkName());
                    blockCertificate.setScanShow(linkReq.getScanShow());
                    blockCertificate.setSort(linkReq.getSort());
                    blockCertificate.setLanguageTypeId(saveReqVO.getLanguageTypeId());
                    this.setOperateDetails(linkReq.getOperateDetails(), blockCertificate);

                    createBlockCertificates.add(blockCertificate);
                }
            });

            deleteCertificateIds.addAll(linkIdsDB.stream().filter(id -> !willUpdateLinkIds.contains(id)).collect(Collectors.toList()));
        } else if(!linkIdsDB.isEmpty()) {
            // 说明是全部删除
            deleteCertificateIds.addAll(linkIdsDB);
        }

        //*********************************  更新检验检疫  **************************************//
        if(saveReqVO.getInspections() != null && !saveReqVO.getInspections().isEmpty()) {
            List<Long> willUpdateInspectionIds = new ArrayList<>();
            saveReqVO.getInspections().forEach(inspection -> {
                // 根据id判断是更新还是新增
                if(inspection.getId() != null) {
                    // 更新
                    InspectionSaveReqVO inspectionDB = inspectionDBMap.get(inspection.getId());
                    if(inspectionDB == null) {
                        throw ServiceExceptionUtil.exception(ErrorCodeConstants.INSPECTION_CONFIG_NOT_EXISTS);
                    }

                    BlockCertificateUpdateReqDTO inspectionDTO = new BlockCertificateUpdateReqDTO();
                    BeanUtil.copyProperties(inspectionDB, inspectionDTO);

                    inspectionDTO.setLinkName(inspection.getLinkName());
                    inspectionDTO.setScanShow(inspection.getScanShow());
                    inspectionDTO.setSort(inspection.getSort());

                    List<Long> willUpdateDetailIds = new ArrayList<>();// 将要更新的操作明细集合
                    List<OperateDetailSaveReqDTO> operateDetails = new ArrayList<>();
                    inspection.getOperateDetails().forEach(detail -> {
                        OperateDetailSaveReqDTO operateDetail = new OperateDetailSaveReqDTO();
                        if(detail.getId() != null) {
                            // 编辑检验检疫操作明细
                            OperateDetailSaveReqVO detailDB = inspectionDetailDBMap.get(detail.getId());
                            if(detailDB == null) {
                                throw ServiceExceptionUtil.exception(ErrorCodeConstants.OPERATE_DETAIL_NOT_EXISTS);
                            }
                            BeanUtil.copyProperties(detailDB, operateDetail);
                            operateDetail.setType(detail.getType());
                            operateDetail.setTitle(detail.getTitle());
                            operateDetail.setContent(detail.getContent());
                            operateDetail.setLinkText(detail.getLinkText());
                            this.verifyFieldAndSetOperateDetail(detail, operateDetail);

                            operateDetails.add(operateDetail);
                            willUpdateDetailIds.add(detail.getId());
                        } else {
                            // 新增检验检疫操作明细
                            this.setOperateDetail(detail, operateDetail, inspectionDTO);
                            operateDetail.setBelongBusinessId(configRespVO.getBelongBusinessId());
                            operateDetail.setBelongBusinessName(configRespVO.getBelongBusinessName());
                            createOperateDetails.add(operateDetail);
                        }
                    });
                    inspectionDTO.setDetails(operateDetails);

                    // 更新检测项目，不更新项目的操作明细
                    if(inspection.getInspectionItems() != null) {
                        List<Long> willUpdateItemIds = new ArrayList<>();
                        // 循环检验项目
                        inspection.getInspectionItems().forEach(item -> {
                            if(item.getId() != null) {
                                // 编辑
                                BlockCertificateSaveReqVO itemDB = inspectionItemDBMap.get(item.getId());
                                if(itemDB == null) {
                                    throw ServiceExceptionUtil.exception(ErrorCodeConstants.OPERATE_DETAIL_NOT_EXISTS);
                                }
                                BlockCertificateUpdateReqDTO inspectionItem = new BlockCertificateUpdateReqDTO();
                                BeanUtil.copyProperties(itemDB, inspectionItem);
                                inspectionItem.setLinkName(item.getLinkName());
                                inspectionItem.setScanShow(item.getScanShow());
                                inspectionItem.setSort(item.getSort());

                                // 更新项目明细
                                List<OperateDetailSaveReqDTO> itemDetails = new ArrayList<>();
                                itemDB.getOperateDetails().forEach(detail -> {
                                    OperateDetailSaveReqVO detailReq = inspectionItemDetailMap.get(detail.getId());
                                    OperateDetailSaveReqDTO updateItemDetail = new OperateDetailSaveReqDTO();
                                    BeanUtil.copyProperties(detail, updateItemDetail);
                                    if (detailReq != null) {
                                        updateItemDetail.setContent(detailReq.getContent());
                                    }
                                    itemDetails.add(updateItemDetail);
                                });
                                inspectionItem.setDetails(itemDetails);

                                updateBlockCertificates.add(inspectionItem);

                                willUpdateItemIds.add(item.getId());
                            }
                            // 没有新增, 项目固定只读取原有的
                        });

                        // 需删除的检测项目
                        deleteCertificateIds.addAll(inspectionItemDBIdsMap.get(inspection.getId()).stream().filter(id -> !willUpdateItemIds.contains(id)).collect(Collectors.toList()));
                    } else {
                        // 判断数据库表中是否有检验项目， 如果有 全部删除
                        List<Long> inspectionItemDBIds = inspectionItemDBIdsMap.get(inspection.getId());
                        if(inspectionItemDBIds != null) {
                            deleteCertificateIds.addAll(inspectionItemDBIds);
                        }
                    }

                    // 删除检验检疫的操作明细
                    deleteOperateDetailIds.addAll(inspectionDetailIdsDBMap.get(inspection.getId()).stream().filter(id -> !willUpdateDetailIds.contains(id)).collect(Collectors.toList()));

                    updateBlockCertificates.add(inspectionDTO);
                    willUpdateInspectionIds.add(inspection.getId());
                } else {
                    // 新增流程：新增其他检验检疫
                    BlockCertificateCreateReqDTO createInspection = new BlockCertificateCreateReqDTO();
                    BeanUtil.copyProperties(inspection, createInspection);
                    createInspection.setChainOperateId(CodeEnum.CHAIN_OPERATE_CODE.getCode());
                    createInspection.setOperateType(OperateTypeEnum.BATCH.getType()); // 操作类型
                    createInspection.setOperateName(OperateTypeEnum.BATCH.getName()); //
                    createInspection.setBatchId(harvestBatch.getHarvestBatchId());
                    createInspection.setBatchType(BatchTypeEnum.INSPECTION_BATCH.getType());// 检验批次
                    createInspection.setChainState(ChainStateEnum.NOT_ON_CHAIN.getState()); // 上链状态
                    createInspection.setBelongBusinessId(harvestBatch.getBelongBusinessId());
                    createInspection.setBelongBusinessName(harvestBatch.getBelongBusinessName());
                    createInspection.setLinkId(CodeEnum.TRACE_LINK_CODE.getCode());
                    createInspection.setLanguageTypeId(saveReqVO.getLanguageTypeId());
                    this.setOperateDetails(inspection.getOperateDetails(), createInspection);

                    createBlockCertificates.add(createInspection);
                    // 新增检测项目
                    if(inspection.getInspectionItems() != null) {
                        inspection.getInspectionItems().forEach(item -> {
                            BlockCertificateCreateReqDTO createItem = new BlockCertificateCreateReqDTO();
                            BeanUtil.copyProperties(item, createItem);
                            createItem.setChainOperateId(CodeEnum.CHAIN_OPERATE_CODE.getCode());
                            createItem.setOperateType(OperateTypeEnum.BATCH.getType()); // 操作类型
                            createItem.setOperateName(OperateTypeEnum.BATCH.getName()); //
                            createItem.setBatchId(harvestBatch.getHarvestBatchId());
                            createItem.setBatchType(BatchTypeEnum.INSPECTION_BATCH.getType());// 检验批次
                            createItem.setChainState(ChainStateEnum.NOT_ON_CHAIN.getState()); // 上链状态
                            createItem.setBelongBusinessId(harvestBatch.getBelongBusinessId());
                            createItem.setBelongBusinessName(harvestBatch.getBelongBusinessName());
                            createItem.setLinkId(CodeEnum.TRACE_LINK_CODE.getCode());
                            createItem.setParentOperateId(createInspection.getChainOperateId());
                            createItem.setLanguageTypeId(saveReqVO.getLanguageTypeId());
                            this.setOperateDetails(item.getOperateDetails(), createItem);

                            createBlockCertificates.add(createItem);
                        });
                    }
                }
            });

            // 删除未传上来的检验检疫
            deleteCertificateIds.addAll(inspectionDBIds.stream().filter(id -> !willUpdateInspectionIds.contains(id)).collect(Collectors.toList()));
        } else if(!configRespVO.getInspections().isEmpty()) {
            // 删除已有的检验检疫
            deleteCertificateIds.addAll(configRespVO.getInspections().stream().map(inspection -> {
                // 同步删除已有检验检疫的检测项目
                deleteCertificateIds.addAll(inspection.getInspectionItems().stream().map(BlockCertificateSaveReqVO::getId).collect(Collectors.toList()));
                return inspection.getId();
            }).collect(Collectors.toList()));
        }

        //********************************* 更新环境类型配置信息  **************************************//
        if(saveReqVO.getEnvTypeConfigs() != null && !saveReqVO.getEnvTypeConfigs().isEmpty()) {
            List<Long> willUpdateIds = new ArrayList<>();
            saveReqVO.getEnvTypeConfigs().forEach(config -> {
                if(config.getId() != null) {
                    // 编辑
                    // 正常情况下无法更新 所以这里不管
//                    DeviceEnvTypeUpdateReqDTO deviceEnvType = new DeviceEnvTypeUpdateReqDTO();
//                    BeanUtil.copyProperties(config, deviceEnvType);
                    willUpdateIds.add(config.getId());
                } else {
                    // 新增
                    DeviceEnvTypeCreateReqDTO deviceEnvType = new DeviceEnvTypeCreateReqDTO();
                    BeanUtil.copyProperties(config, deviceEnvType);
                    createDeviceEnvTypes.add(deviceEnvType);
                }
            });
            // 删除未上传的配置
            hasConfigLandDBIds.forEach(landId -> {
                envTypeDBMaps.get(landId).forEach(id -> {
                    if(!willUpdateIds.contains(id)) {
                        deleteDeviceEnvTypeIds.add(id);
                    }
                });
            });
        } else {
            // 删除所有类型配置
            hasConfigLandDBIds.forEach(id -> {
                deleteDeviceEnvTypeIds.addAll(envTypeDBMaps.get(id));
            });
        }

        if (harvestBatchConfig != null) {
            harvestBatchConfig.setTemplateId(saveReqVO.getTemplateId());
            // 插入批次配置表
            harvestBatchConfigMapper.updateById(harvestBatchConfig);
        } else {
            harvestBatchConfig = new HarvestBatchConfigDO();
            harvestBatchConfig.setTemplateId(saveReqVO.getTemplateId());
            harvestBatchConfig.setHarvestBatchId(configRespVO.getHarvestBatchId());
            harvestBatchConfig.setLanguageTypeId(saveReqVO.getLanguageTypeId());
            harvestBatchConfigMapper.insert(harvestBatchConfig);
        }

        if(!deleteCertificateIds.isEmpty()) {
            blockCertificateApi.deleteBlockCertificateBatch(deleteCertificateIds);
        }

        if(!deleteOperateDetailIds.isEmpty()) {
            operateDetailApi.deleteOperateDetailBatch(deleteOperateDetailIds);
        }

        if(!createBlockCertificates.isEmpty()) {
            blockCertificateApi.createBlockCertificateBatch(createBlockCertificates);
        }

        if(!createOperateDetails.isEmpty()) {
            operateDetailApi.createOperateDetailBatch(createOperateDetails);
        }

        if(!updateBlockCertificates.isEmpty()) {
            blockCertificateApi.updateBlockCertificateBatch(updateBlockCertificates);
        }

        if(!createDeviceEnvTypes.isEmpty()) {
            deviceEnvTypeApi.createDeviceEnvTypeBatch(createDeviceEnvTypes);
        }

        if(!deleteDeviceEnvTypeIds.isEmpty()) {
            deviceEnvTypeApi.deleteDeviceEnvTypeBatch(deleteDeviceEnvTypeIds);
        }
    }

    @Override
    public void initHarvestBatchConfig() {
        // 查询所有的批次配置
        List<HarvestBatchConfigDO> configList = harvestBatchConfigMapper.selectList();
        // 查询所有的语言类型
        List<LanguageTypeRespDTO> languageTypeList = languageTypeApi.getAllLanguageType().getData();
        // 查询所有的批次
        List<HarvestBatchDO> harvestBatchList = this.harvestBatchMapper.selectList();

        if (languageTypeList.isEmpty() || harvestBatchList.isEmpty()) {
            return;
        }
        // 获取默认模板
        UniTemplateDTO templateDTO = uniTemplateApi.getDefaultTemplate().getData();
        if (templateDTO == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.CAN_NOT_FIND_DEFAULT_UNI_TEMPLATE);
        }


        Map<String, HarvestBatchConfigDO> configMap = new HashMap<>();
        configList.forEach(config -> {
            String key = "batchId:" + config.getHarvestBatchId() + ";typeId:" + config.getLanguageTypeId();
            configMap.put(key, config);
        });

        List<HarvestBatchConfigDO> createList = new ArrayList<>();

        languageTypeList.forEach(languageType -> {
            harvestBatchList.forEach(batch -> {
                String key = "batchId:" + batch.getHarvestBatchId() + ";typeId:" + languageType.getId();
                HarvestBatchConfigDO config = configMap.get(key);
                if (config == null) {
                    config = new HarvestBatchConfigDO();
                    config.setLanguageTypeId(languageType.getId());
                    config.setHarvestBatchId(batch.getHarvestBatchId());
                    config.setTemplateId(templateDTO.getId());
                    createList.add(config);
                }
            });
        });

        if (!createList.isEmpty()) {
            harvestBatchConfigMapper.insertBatch(createList);
        }
    }


    private void setOperateDetailsForUpdate(BlockCertificateSaveReqVO saveReqVO, List<OperateDetailSaveReqDTO> createOperateDetails,
            List<Long> willUpdateIds, BlockCertificateUpdateReqDTO updateReqDTO) {
        List<OperateDetailSaveReqDTO> operateDetailSaves = new ArrayList<>();
        saveReqVO.getOperateDetails().forEach(detail -> {
            OperateDetailSaveReqDTO operateDetail = new OperateDetailSaveReqDTO();
            if(detail.getId() != null) {
                BeanUtil.copyProperties(detail, operateDetail);
                operateDetailSaves.add(operateDetail);
                willUpdateIds.add(detail.getId());
            } else {
                // 新增操作
                this.setOperateDetail(detail, operateDetail, updateReqDTO);
                createOperateDetails.add(operateDetail);
            }
        });
        updateReqDTO.setDetails(operateDetailSaves);
    }


}
