package com.cf.imes.module.executor.service.plate;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.cf.imes.framework.common.enums.*;
import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.Assert.AssertUtils;
import com.cf.imes.framework.common.util.json.JsonUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.id.core.util.SnowflakeIdWorker3rd;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.framework.mybatis.core.query.MPJLambdaWrapperX;
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.module.executor.controller.admin.goods.vo.GoodsSaveReqVO;
import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderCadViewPlatePageReqVO;
import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderPlanPlateNumAndAreaRespVO;
import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderRespVO;
import com.cf.imes.module.executor.controller.admin.order.vo.order.OrdersViewCadViewInfoRespVO;
import com.cf.imes.module.executor.controller.admin.ordercomponent.vo.OrderDetailComponentPageReqVO;
import com.cf.imes.module.executor.controller.admin.plan.vo.OrderGoodsResp;
import com.cf.imes.module.executor.controller.admin.plan.vo.PlateDetailRespVO;
import com.cf.imes.module.executor.controller.admin.plate.vo.*;
import com.cf.imes.module.executor.dal.dataobject.goods.GoodsDO;
import com.cf.imes.module.executor.dal.dataobject.order.OrderDO;
import com.cf.imes.module.executor.dal.dataobject.orderBody.OrderBodyDO;
import com.cf.imes.module.executor.dal.dataobject.orderGroup.OrderGroupDO;
import com.cf.imes.module.executor.dal.dataobject.orderItem.OrderItemDO;
import com.cf.imes.module.executor.dal.dataobject.orderItem.OrderItemTempDO;
import com.cf.imes.module.executor.dal.dataobject.orderItem.OrdersViewPartsPageDO;
import com.cf.imes.module.executor.dal.dataobject.orderItem.OrdersViewPlatesPageDO;
import com.cf.imes.module.executor.dal.dataobject.ordercomponent.OrderComponentDO;
import com.cf.imes.module.executor.dal.dataobject.ordermodel.OrderModelDO;
import com.cf.imes.module.executor.dal.dataobject.plan.PlanDO;
import com.cf.imes.module.executor.dal.dataobject.plate.PlateDO;
import com.cf.imes.module.executor.dal.dataobject.plate.PlateDetailDO;
import com.cf.imes.module.executor.dal.dataobject.plate.PlateGoodDO;
import com.cf.imes.module.executor.dal.mysql.goods.GoodsMapper;
import com.cf.imes.module.executor.dal.mysql.order.OrderMapper;
import com.cf.imes.module.executor.dal.mysql.orderBody.OrderBodyMapper;
import com.cf.imes.module.executor.dal.mysql.orderGroup.OrderGroupMapper;
import com.cf.imes.module.executor.dal.mysql.orderItem.OrderItemMapper;
import com.cf.imes.module.executor.dal.mysql.orderItem.OrderItemTempMapper;
import com.cf.imes.module.executor.dal.mysql.ordercomponent.OrderComponentMapper;
import com.cf.imes.module.executor.dal.mysql.plan.PlanMapper;
import com.cf.imes.module.executor.dal.mysql.plate.PlateGoodMapper;
import com.cf.imes.module.executor.dal.mysql.plate.PlateMapper;
import com.cf.imes.module.executor.enums.OrderItemType;
import com.cf.imes.module.executor.enums.OrderStatusEnum;
import com.cf.imes.module.executor.service.order.OrderService;
import com.cf.imes.module.executor.service.orderbody.OrderBodyService;
import com.cf.imes.module.executor.service.ordercomponent.OrderComponentService;
import com.cf.imes.module.executor.service.orderitem.OrderItemService;
import com.cf.imes.module.system.api.organ.OrganApi;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import jakarta.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getUserOrganId;
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.*;
import static com.cf.imes.module.executor.enums.EsIndexEnum.ORDER_PLATE_MODEL;

/**
 * 订单板件 Service 实现类
 *
 * @author 晨丰科技
 */
@Service
@Validated
@Slf4j
public class PlateServiceImpl implements PlateService {

    @Resource
    private PlateMapper plateMapper;

    @Resource
    private OrderItemMapper orderItemMapper;

    @Resource
    private OrderItemTempMapper orderItemTempMapper;

    @Resource
    private GoodsMapper goodsMapper;

    @Resource
    private PlanMapper planMapper;

    @Resource
    private OrderBodyMapper orderBodyMapper;

    @Resource
    private PlateGoodMapper plateGoodMapper;

    @Resource
    private OrderMapper orderMapper;


    @Resource
    private SnowflakeIdWorker3rd idWorker;

    @Resource
    private IdentifierGenerator identifierGenerator;

    @Resource
    private OrganApi organApi;

    @Resource
    private OrderService orderService;

    @Resource
    private OrderBodyService orderBodyService;

    @Resource
    private OrderComponentService orderComponentService;

    @Resource
    private OrderItemService orderItemService;

    @Resource
    private OrderGroupMapper orderGroupMapper;

    @Resource
    private OrderComponentMapper orderComponentMapper;

    private static final String FIELD_PLATE_ID = "plateId";

    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Override
    public PlateDO getPlate(Long plateId) {
        return plateMapper.selectById(plateId);
    }

    @Override
    public PlateDO getPlateByNo(String plateNo, Long... orderIds) {
        return plateMapper.selectOne(new LambdaQueryWrapperX<PlateDO>()
                .eq(PlateDO::getPlateNo, plateNo)
                .inIfPresent(PlateDO::getOrderId, orderIds)
        );
    }

    @Override
    public Long createPlate(PlateSaveReqVO createReqVO) {
        // 插入
        PlateDO plate = BeanUtils.toBean(createReqVO, PlateDO.class);
        plateMapper.insert(plate);
        // 返回
        return plate.getId();
    }

    @Override
    public void updatePlate(PlateSaveReqVO updateReqVO) {
        // 校验存在
        validatePlateExists(updateReqVO.getId());
        // 更新
        PlateDO updateObj = BeanUtils.toBean(updateReqVO, PlateDO.class);
        plateMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletePlate(List<Long> plateIds, Long planId) {

        if (CollUtil.isEmpty(plateIds)) {
            return;
        }

        PlanDO planDO = planMapper.selectById(planId);

        AssertUtils.notEmpty(planDO, ORDER_PLAN_DATA_ERROR);

        List<PlateDO> plateDOS = plateMapper.selectByIds(plateIds);

        AssertUtils.notEmpty(plateDOS, REMAIN_PLATE_NOT_EXISTS);


        for (PlateDO plateDO : plateDOS) {

            if (!plateDO.getType().equals(OrderPlateTypeEnum.SELFINCREASINGBOARD.getType())) {
                throw new ServiceException(PLATE_IS_SOURCE, plateDO.getPlateNo());
            }

            if (!plateDO.getIsCutted().equals(OrderPlateCutStatusEnum.NOCUTTING.getStatus())) {

                throw new ServiceException(PLATE_IS_OPTIMIZE, plateDO.getPlateNo());
            }
        }


        List<Long> plateIdList = plateDOS.stream().map(PlateDO::getId).toList();

        List<Long> orderIds = plateDOS.stream().map(PlateDO::getOrderId).distinct().toList();

        List<Long> goodsIds = plateDOS.stream().map(PlateDO::getGoodsId).distinct().toList();


        List<OrderItemDO> orderItemDOS = orderItemMapper.selectPlateList(plateIdList, orderIds, getUserOrganId());

        List<Long> bodyIds = orderItemDOS.stream().map(OrderItemDO::getBodyId).distinct().toList();

        List<OrderBodyDO> orderBodyDOS = orderBodyMapper.selectByIds(bodyIds);

        orderBodyDOS.forEach(f -> {
            int plateNum = orderItemDOS.stream().filter(o -> f.getId().equals(o.getBodyId())).toList().size();
            f.setPlateNum(f.getPlateNum() - plateNum);

        });

        orderBodyMapper.updateBatch(orderBodyDOS);

        // 删除小板ID
        plateMapper.deleteByIds(plateIdList);

        // 删除小板明细信息
        orderItemMapper.deleteByPlateId(plateIdList, orderIds, getUserOrganId());

        // 删除添加自增板时新增的大板ID
        List<Long> orderGoodsIdList = goodsMapper.selectInsertGoodsIds(orderIds, goodsIds, getUserOrganId());
        if (CollUtil.isNotEmpty(orderGoodsIdList)) {
            goodsMapper.deleteByIds(orderGoodsIdList);
        }

        // 统计更新板件数量和面积
        computePlatePlanAndComputeOrderGoodsInfo(plateDOS.stream()
                .collect(Collectors.groupingBy(
                        PlateDO::getGoodsId,
                        Collectors.mapping(PlateDO::getId, Collectors.toList())
                )));
        computeOrderInfo(orderIds);

    }

    /**
     * 统计更新order_goods的小板数量和面积
     *
     * @param goodsPlateIdMap
     */
    public void computePlatePlanAndComputeOrderGoodsInfo(Map<Long, List<Long>> goodsPlateIdMap) {
        for (Map.Entry<Long, List<Long>> entry : goodsPlateIdMap.entrySet()) {
            Long orderGoodsId = entry.getKey();
            // 查询version
            GoodsDO goodsDO = goodsMapper.selectById(orderGoodsId);

            int version = goodsDO.getVersion();
            // 统计每个order_goods下的未排单面积，更新到order_goods中
            OrderPlanPlateNumAndAreaRespVO goodsPlateNumAndAreaPlanInfo = goodsMapper.selectPlannedPlateNumAndArea(orderGoodsId);
            int update = goodsMapper.update(new LambdaUpdateWrapper<GoodsDO>()
                    .eq(GoodsDO::getId, orderGoodsId)
                    .eq(GoodsDO::getVersion, version)
                    .set(GoodsDO::getPlannedPlateArea, goodsPlateNumAndAreaPlanInfo.getArea())
                    .set(GoodsDO::getPlannedPlateNum, goodsPlateNumAndAreaPlanInfo.getNum())
                    .set(GoodsDO::getVersion, version + 1));
            if (update == 0) {
                throw new ServiceException(com.cf.imes.module.executor.enums.ErrorCodeConstants.GOODS_PLATE_UPDATE_CONCURRENCY_ERROR, orderGoodsId);
            }
        }
    }

    /**
     * 统计更新orders的小板数量和面积
     *
     * @param orderIdList
     */
    public void computeOrderInfo(List<Long> orderIdList) {
        for (Long orderId : orderIdList) {
            // 统计每个orders下的未排单面积，更新到orders中
            OrderDO orderDO = orderMapper.selectById(orderId);
            OrderPlanPlateNumAndAreaRespVO orderPlateNumAndAreaPlanInfo = orderMapper.selectPlannedPlateNumAndArea(orderId);

            // 当前订单下排单的板件数量
            Integer num = orderPlateNumAndAreaPlanInfo.getNum();

            int version = orderDO.getVersion();
            LambdaUpdateWrapper<OrderDO> updateWrapper = new LambdaUpdateWrapper<OrderDO>()
                    .eq(OrderDO::getId, orderId)
                    .eq(OrderDO::getVersion, version)
                    .set(OrderDO::getPlannedPlateArea, orderPlateNumAndAreaPlanInfo.getArea())
                    .set(OrderDO::getPlannedPlateNum, num)
                    .set(OrderDO::getVersion, version + 1);
            Integer orderDOStatus = orderDO.getStatus();
            // 更新订单排单状态
            if (ObjectUtil.notEqual(orderDOStatus, OrderStatusEnum.IN_PRODUCTION.getStatus()) && ObjectUtil.notEqual(orderDOStatus, OrderStatusEnum.SORTED.getStatus())) {
                // 如果订单下已经没有排单板件，更新订单为新单
                if (num == 0) {
                    updateWrapper.set(OrderDO::getStatus, OrderStatusEnum.NEW_ORDER.getStatus());
                } else {
                    updateWrapper.set(OrderDO::getStatus, OrderStatusEnum.SORTED.getStatus());
                }
            }
            int update = orderMapper.update(updateWrapper);
            if (update == 0) {
                throw new ServiceException(com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_PLATE_UPDATE_CONCURRENCY_ERROR, orderId);
            }
        }
    }

    private void validatePlateExists(Long id) {
        if (plateMapper.selectById(id) == null) {
            throw new ServiceException(REMAIN_PLATE_NOT_EXISTS);
        }
    }


    @Override
    public PageResult<PlateDO> getPlatePage(PlatePageReqVO pageReqVO) {
        return plateMapper.selectPage(pageReqVO);
    }


    @Override
    public PageResult<PlateGoodDO> getGoodsPlate(GoodsPlateFilterPageReqVO pageReqVO) {

        return plateGoodMapper.selectGoodsPage(pageReqVO, getUserOrganId());

    }


    @Override
    public NoPlanPlateRespVO getOrdersNoPlanPlate(NoPlanPlatePageReqVO pageReqVO) {
        // 置空内部条件
        pageReqVO.setMaterialList(null);
        pageReqVO.setColorList(null);
        pageReqVO.setBrandList(null);
        pageReqVO.setThicknessList(null);
        pageReqVO.setTextureList(null);

        Long organId = getUserOrganId();

        if (pageReqVO.getPlanId() != null) {

            Long planId = pageReqVO.getPlanId();

            PlanDO planDO = planMapper.selectById(planId);

            AssertUtils.notEmpty(planDO, PLAN_NOT_EXISTS);

            List<OrderGoodsResp> goodsRespVOS = planMapper.selectPlanGoodsList(planId, organId);

            AssertUtils.notEmpty(goodsRespVOS, PLAN_NOT_EXISTS);

            List<String> material = goodsRespVOS.stream().map(OrderGoodsResp::getMaterial).distinct().toList();

            List<String> color = goodsRespVOS.stream().map(OrderGoodsResp::getColor).distinct().toList();

            List<String> brand = goodsRespVOS.stream().map(OrderGoodsResp::getBrand).distinct().toList();

            List<BigDecimal> thickness = goodsRespVOS.stream().map(OrderGoodsResp::getThickness).distinct().toList();

            List<Boolean> texture = goodsRespVOS.stream().map(OrderGoodsResp::getTexture).distinct().toList();


            // 混单
            if (planDO.getType().equals(PlanTypeEnum.MIXEDORDERPLAN.getType())) {

                // 混单添加查询条件
                mixedInsertQuery(pageReqVO, planDO, material, thickness);

            }
            // 非混单
            else {

                // 非混单条件查询条件
                noMixedInsertQuery(pageReqVO, planDO, material, brand, color, thickness, texture);

            }
        }

        // 查询订单未排单小板
        List<PlateDetailDO> plateDetailDOS = plateMapper.selectNoPlanPlateWithFilter(pageReqVO, organId);
        // 合并加工组
        List<PlateDetailDO> resultPlateList = mergeGroupAndComponentName(plateDetailDOS);

        List<OrderModelDO> models =
                resultPlateList.stream()
                        .map(PlateDetailDO::getModelData)
                        .filter(StringUtils::isNotBlank)
                        .map(json -> JsonUtils.parseObject(json, OrderModelDO.class))
                        .toList();

        return NoPlanPlateRespVO.builder()
                .plateList(BeanUtil.copyToList(resultPlateList, PlateDetailRespVO.class))
                .plateModels(models)
                .build();
    }
    
    /**
     * 合并加工组、部件名称
     *
     * @param list
     */
    public List<PlateDetailDO> mergeGroupAndComponentName(List<PlateDetailDO> list) {

        if (list == null || list.isEmpty()) {
            return Collections.emptyList();
        }

        // plateId -> (groupName + 代表对象)
        Map<Long, PlateDetailDO> resultMap = new LinkedHashMap<>();
        Map<Long, Set<String>> groupNameMap = new HashMap<>();
        Map<Long, Set<String>> componentNameMap = new HashMap<>();

        for (PlateDetailDO item : list) {

            Long plateId = item.getPlateId();
            if (plateId == null) {
                continue;
            }

            // 保留第一条作为代表对象（或你也可以自定义取最新）
            resultMap.putIfAbsent(plateId, item);

            if (StringUtils.isNotBlank(item.getProcessGroupName())) {
                groupNameMap
                        .computeIfAbsent(plateId, k -> new LinkedHashSet<>())
                        .add(item.getProcessGroupName());
            }
            if (StringUtils.isNotBlank(item.getComponentName())) {
                componentNameMap
                        .computeIfAbsent(plateId, k -> new LinkedHashSet<>())
                        .add(item.getComponentName());
            }
        }

        // 组装最终结果
        List<PlateDetailDO> result = new ArrayList<>(resultMap.size());

        for (Map.Entry<Long, PlateDetailDO> entry : resultMap.entrySet()) {

            Long plateId = entry.getKey();
            PlateDetailDO item = entry.getValue();

            Set<String> groupNames = groupNameMap.get(plateId);
            if (groupNames != null && !groupNames.isEmpty()) {
                item.setProcessGroupName(String.join(",", groupNames));
            }
            Set<String> componentNames = componentNameMap.get(plateId);
            if (CollUtil.isNotEmpty(componentNames)) {
                item.setComponentName(String.join(",", componentNames));
            }

            result.add(item);
        }

        return result;
    }


    @Override
    @Transactional(rollbackFor = Exception.class) // 添加事务，异常则回滚所有导入
    public PlateImportRespVO importPlatesList(List<PlateSaveReqVO> importPlates, Long orderId) {
        if (CollUtil.isEmpty(importPlates)) {
            throw new ServiceException(RAW_GOODS_IMPORT_LIST_IS_EMPTY);
        }
        PlateImportRespVO respVO = PlateImportRespVO.builder().createPlates(new ArrayList<>())
                .updatePlates(new ArrayList<>()).failurePlates(new LinkedHashMap<>()).build();
        importPlates.forEach(plateSaveReqVO -> {
            try {
//                改成plateMapper.insertBatch()
                plateMapper.insert(BeanUtils.toBean(plateSaveReqVO, PlateDO.class)
                        .setOrderId(orderId));
                respVO.getCreatePlates().add(plateSaveReqVO);
            } catch (ServiceException ex) {
                respVO.getFailurePlates().put(plateSaveReqVO.getName(), ex.getMessage());
            }
        });
        return respVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletePlates(Set<Long> ids) {
        plateMapper.deleteByIds(ids);
    }

    @Override
    public List<PlateDO> getPlatesByOrderId(Long orderId) {
        return plateMapper.selectList(new LambdaQueryWrapper<PlateDO>().eq(PlateDO::getOrderId, orderId));
    }

    @Override
    public PageResult<PlateRespVO> getPlatePageByTerms(PlateTermsPageReqVO pageReqVO) {
        PageDTO<PlateRespVO> page = new PageDTO<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
        IPage<PlateRespVO> pageRes = plateMapper.selectProductList(page, pageReqVO.getOrderId(), pageReqVO.getRoomId(), pageReqVO.getBodyId(), getUserOrganId());
        return new PageResult<>(pageRes.getRecords(), pageRes.getTotal());
    }

    @Override
    public void updatePlateByRawGoodsId(List<GoodsSaveReqVO> createReqVOS) {
        // 根据订单id和goods_id查到数据，再更新goods_id
        createReqVOS.forEach(createReqVO -> {

        });

    }


    @SneakyThrows
    @Override
    public List<BodyPlateDetailVO> getPlateModelByPlateId(List<Long> bodyIds) {
        List<BodyPlateIdDTO> list = plateMapper.selectJoinList(BodyPlateIdDTO.class, new MPJLambdaWrapperX<PlateDO>()
                .selectAs(PlateDO::getId, FIELD_PLATE_ID)
                .leftJoin(OrderItemDO.class, OrderItemDO::getPlateId, PlateDO::getId)
                .eq(OrderItemDO::getOrganId, getUserOrganId())
                .in(OrderItemDO::getBodyId, bodyIds)
                .select(OrderItemDO::getBodyId)
        );
        List<Long> plateIds = list.stream().map(BodyPlateIdDTO::getPlateId).toList();
        List<OrderModelDO> orderModelDOS = buildRespByPlateIds(plateIds, ORDER_PLATE_MODEL.getIndex());
        Map<Long, List<OrderModelDO>> map = orderModelDOS.stream().collect(Collectors.groupingBy(e -> list.stream().filter(f -> Objects.equals(f.getPlateId(), e.getPlateId())).map(BodyPlateIdDTO::getBodyId).findAny().orElse(null)));

        List<BodyPlateDetailVO> bodyPlateDetailVOS = new ArrayList<>();
        map.entrySet().forEach(e -> bodyPlateDetailVOS.add(BodyPlateDetailVO.builder()
                .orderModelList(e.getValue())
                .bodyId(e.getKey())
                .build()
        ));
        return bodyPlateDetailVOS;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<InsertPlateRespVO> createNewPlate(List<OptimizationSavePlateReqVO> reqVO) {

        List<PlateDO> plateDOS = new ArrayList<>();

        List<OrderItemDO> orderItemDOS = new ArrayList<>();

        List<InsertPlateRespVO> insertPlateRespVOS = new ArrayList<>();

        List<OrderBodyNumVO> orderBodyNumVOS = new ArrayList<>();

        List<OrderModelDO> orderPlateModelDOS = new ArrayList<>();

        Long planId = Optional.ofNullable(reqVO.get(0).getPlanId()).orElseThrow(() -> new ServiceException(ORDER_PLAN_PLATE_ERROR));

        PlanDO planDO = planMapper.selectById(planId);
        AssertUtils.notEmpty(planDO, ORDER_PLAN_DATA_ERROR);

        List<Long> orderIds = reqVO.stream().map(OptimizationSavePlateReqVO::getOrderId).distinct().toList();

        // 查询排单下的orderGoodsId列表
        List<Long> goodsId = planMapper.selectPlanOrderGoodsId(planId, orderIds, getUserOrganId());

        List<GoodsDO> goodsDOS = goodsMapper.selectByIds(goodsId);

        Map<Long, OrderPlanPlateNumAndAreaRespVO> orderPlanPlateNumAndAreaRespVOMap = new HashMap<>();

        Map<Long, OrderPlanPlateNumAndAreaRespVO> orderGoodsPlanPlateNumAndAreaRespVOMap = new HashMap<>();

        // 组装新增数据
        reqVO.forEach(f -> {

            Map<String, String> plateIdAndNo = new HashMap<>();

            Long orderId = f.getOrderId();

            GoodsDO goodsDO = goodsDOS.stream().filter(g -> g.getOrderId().equals(f.getOrderId())).toList().get(0);

            orderBodyNumVOS.add(OrderBodyNumVO.builder()
                    .bodyId(f.getBodyId())
                    .plateNum(f.getMultiple())
                    .build());

            // 生成板编号
            long obtainingTime = SnowflakeIdWorker3rd.obtainingTime();

            String plateNo = (obtainingTime) + Long.toString(idWorker.nextId()).substring(2);

            String remake1 = f.getRemake1() == null ? "" : f.getRemake1() + ";";

            String remake2 = f.getRemake2() == null ? "" : f.getRemake2();

            // 小板ID
            Long plateId = (Long) identifierGenerator.nextId(null);

            plateIdAndNo.put(plateId.toString(), plateNo);

            // 计算面积
            BigDecimal area = f.getWidth().multiply(f.getHeight()).movePointLeft(6).stripTrailingZeros();

            plateDOS.add(PlateDO.builder()
                    .id(plateId)
                    .orderId(orderId)
                    .name(f.getName())
                    .plateNo(plateNo)
                    .type(OrderPlateTypeEnum.SELFINCREASINGBOARD.getType())
                    .isOptimized(true)
                    .thickness(goodsDO.getThickness())
                    .goodsId(goodsDO.getId())
                    .holeFace(f.getPlaceHole())
                    .remark(remake1 + remake2)
                    .area(area)
                    .width(f.getWidth())
                    .height(f.getHeight())
                    .texture(f.getTexture())
                    .sealLeft(f.getSealLeft())
                    .sealRight(f.getSealRight())
                    .sealUp(f.getSealUp())
                    .sealDown(f.getSealDown())
                    .planId(f.getPlanId())
                    .build());


            // 订单造型数据
            orderPlateModelDOS.add(OrderModelDO.builder()
                    .plateId(plateId)
                    .orderId(orderId)
                    .goodsId(goodsDO.getGoodsId())
                    .plateGoodsId(goodsDO.getId())
                    .texture(f.getTexture())
                    .boardType(OrderPlateTypeEnum.SELFINCREASINGBOARD.getDescription())
                    .build());


            // 订单明细表新增数据
            orderItemDOS.add(OrderItemDO.builder()
                    .orderId(f.getOrderId())
                    .type(OrderItemType.BOARD.getCode())
                    .roomId(f.getRoomId())
                    .bodyId(f.getBodyId())
                    .plateId(plateId)
                    .build());

            insertPlateRespVOS.add(InsertPlateRespVO.builder()
                    .blockKey(f.getBlockKey())
                    .plateNo(plateIdAndNo)
                    .build());

            // 累加订单板数和面积
            orderPlanPlateNumAndAreaRespVOMap.putIfAbsent(orderId, new OrderPlanPlateNumAndAreaRespVO().setNum(0).setArea(BigDecimal.ZERO));
            OrderPlanPlateNumAndAreaRespVO orderPlanPlateNumAndAreaRespVO = orderPlanPlateNumAndAreaRespVOMap.get(orderId);
            orderPlanPlateNumAndAreaRespVO.setArea(orderPlanPlateNumAndAreaRespVO.getArea().add(area)).setNum(orderPlanPlateNumAndAreaRespVO.getNum() + 1);

            // 累加订单材质板数和面积
            orderGoodsPlanPlateNumAndAreaRespVOMap.putIfAbsent(orderId, new OrderPlanPlateNumAndAreaRespVO().setNum(0).setArea(BigDecimal.ZERO));
            OrderPlanPlateNumAndAreaRespVO orderGoodsPlanPlateNumAndAreaRespVO = orderGoodsPlanPlateNumAndAreaRespVOMap.get(orderId);
            orderGoodsPlanPlateNumAndAreaRespVO.setArea(orderGoodsPlanPlateNumAndAreaRespVO.getArea().add(area)).setNum(orderGoodsPlanPlateNumAndAreaRespVO.getNum() + 1);
        });

        plateMapper.insertBatch(plateDOS);

        List<OrderBodyNumVO> numVOS = mergeOrderBody(orderBodyNumVOS);

        List<Long> bodyIds = numVOS.stream().map(OrderBodyNumVO::getBodyId).toList();


        List<OrderBodyDO> orderBodyDOS = orderBodyMapper.selectByIds(bodyIds);

        orderBodyDOS.forEach(f -> {

            Integer plateNum = numVOS.stream()
                    .filter(n -> n.getBodyId().equals(f.getId()))
                    .map(OrderBodyNumVO::getPlateNum)
                    .findFirst().orElse(0);

            f.setPlateNum(f.getPlateNum() + plateNum);

        });

        orderBodyMapper.updateBatch(orderBodyDOS);

        orderItemMapper.insertBatch(orderItemDOS);

        // 更新订单和材质板数量和面积
        updateOrdersPlanPlateNumAndArea(orderPlanPlateNumAndAreaRespVOMap);
        updateOrderGoodsPlanPlateNumAndArea(orderGoodsPlanPlateNumAndAreaRespVOMap);

        return insertPlateRespVOS;
    }

    /**
     * 更新订单板件数量和面积
     *
     * @param orderPlanPlateNumAndAreaRespVOS
     */
    private void updateOrdersPlanPlateNumAndArea(Map<Long, OrderPlanPlateNumAndAreaRespVO> orderPlanPlateNumAndAreaRespVOS) {
        for (Map.Entry<Long, OrderPlanPlateNumAndAreaRespVO> entry : orderPlanPlateNumAndAreaRespVOS.entrySet()) {
            Long orderId = entry.getKey();
            OrderDO orderDO = orderMapper.selectById(orderId);

            OrderPlanPlateNumAndAreaRespVO orderPlateNumAndAreaPlanInfo = entry.getValue();

            int version = orderDO.getVersion();
            LambdaUpdateWrapper<OrderDO> updateWrapper = new LambdaUpdateWrapper<OrderDO>()
                    .eq(OrderDO::getId, orderId)
                    .eq(OrderDO::getVersion, version)
                    .set(OrderDO::getArea, orderPlateNumAndAreaPlanInfo.getArea().add(BigDecimal.valueOf(orderDO.getArea())))
                    .set(OrderDO::getPlannedPlateArea, orderPlateNumAndAreaPlanInfo.getArea())
                    .set(OrderDO::getPlannedPlateNum, orderPlateNumAndAreaPlanInfo.getNum())
                    .set(OrderDO::getPlateNum, orderPlateNumAndAreaPlanInfo.getNum() + orderDO.getPlateNum())
                    .set(OrderDO::getVersion, version + 1);
            int update = orderMapper.update(updateWrapper);
            if (update == 0) {
                throw new ServiceException(com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_PLATE_UPDATE_CONCURRENCY_ERROR, orderId);
            }
        }
    }

    /**
     * 更新订单材质板件数量和面积
     *
     * @param orderGoodsPlanPlateNumAndAreaRespVOS
     */
    private void updateOrderGoodsPlanPlateNumAndArea(Map<Long, OrderPlanPlateNumAndAreaRespVO> orderGoodsPlanPlateNumAndAreaRespVOS) {
        for (Map.Entry<Long, OrderPlanPlateNumAndAreaRespVO> entry : orderGoodsPlanPlateNumAndAreaRespVOS.entrySet()) {
            Long orderGoodsId = entry.getKey();
            // 查询version
            GoodsDO goodsDO = goodsMapper.selectById(orderGoodsId);

            int version = goodsDO.getVersion();
            OrderPlanPlateNumAndAreaRespVO goodsPlateNumAndAreaPlanInfo = entry.getValue();
            int update = goodsMapper.update(new LambdaUpdateWrapper<GoodsDO>()
                    .eq(GoodsDO::getId, orderGoodsId)
                    .eq(GoodsDO::getVersion, version)
                    .set(GoodsDO::getArea, goodsPlateNumAndAreaPlanInfo.getArea().add(BigDecimal.valueOf(goodsDO.getArea())))
                    .set(GoodsDO::getPlannedPlateArea, goodsPlateNumAndAreaPlanInfo.getArea().add(BigDecimal.valueOf(goodsDO.getPlannedPlateArea())))
                    .set(GoodsDO::getPlannedPlateNum, goodsPlateNumAndAreaPlanInfo.getNum() + goodsDO.getPlannedPlateNum())
                    .set(GoodsDO::getPlateNum, goodsPlateNumAndAreaPlanInfo.getNum() + goodsDO.getPlateNum())
                    .set(GoodsDO::getVersion, version + 1));
            if (update == 0) {
                throw new ServiceException(com.cf.imes.module.executor.enums.ErrorCodeConstants.GOODS_PLATE_UPDATE_CONCURRENCY_ERROR, orderGoodsId);
            }
        }
    }


    public static List<OrderBodyNumVO> mergeOrderBody(List<OrderBodyNumVO> dataList) {
        if (dataList == null || dataList.isEmpty()) {
            return Collections.emptyList();
        }

        // 使用 HashMap 来聚合数据，key 为 filed1，value 为 TestData 对象
        Map<Long, Integer> mergedMap = new HashMap<>();
        for (OrderBodyNumVO data : dataList) {
            // 合并逻辑：将 filed2 的值累加
            mergedMap.merge(data.getBodyId(), data.getPlateNum(), Integer::sum);
        }

        // 将结果转换回 List<TestData>
        return mergedMap.entrySet().stream()
                .map(entry -> new OrderBodyNumVO(entry.getKey(), entry.getValue()))
                .toList();
    }


    private List<OrderModelDO> buildRespByPlateIds(Collection<Long> plateIds, String index) {
        return new ArrayList<>();
    }


    private void mixedInsertQuery(NoPlanPlatePageReqVO pageReqVO,
                                  PlanDO planDO,
                                  List<String> material,
                                  List<BigDecimal> thickness) {


        if (Boolean.TRUE.equals(pageReqVO.getIsMixed())) {
            throw new ServiceException(PLAN_IS_MIXED_ERROR);
        }

        // 相同材质和厚度
        if (planDO.getFilter().equals(MixConfigTypeEnum.SAMEMATERIALANDTHICKNESS.getType())) {

            pageReqVO.setMaterialList(material);
            pageReqVO.setThicknessList(thickness);

        }
        // 相同厚度
        else {

            pageReqVO.setThicknessList(thickness);

        }


    }


    private void noMixedInsertQuery(NoPlanPlatePageReqVO pageReqVO,
                                    PlanDO planDO,
                                    List<String> material,
                                    List<String> brand,
                                    List<String> color,
                                    List<BigDecimal> thickness,
                                    List<Boolean> texture) {

        // 是否开启混单
        if (Boolean.TRUE.equals(pageReqVO.getIsMixed())) {

            if (!planDO.getStatus().equals(PlanStatusEnum.NOCUTTING.getStatus())) {
                throw new ServiceException(PLAN_PLATE_IS_CUTTING);
            }

            // 相同材质和厚度 混单
            if (pageReqVO.getMixedType().equals(MixConfigTypeEnum.SAMEMATERIALANDTHICKNESS.getType())) {
                pageReqVO.setMaterialList(material);
                pageReqVO.setThicknessList(thickness);

            }
            // 相同厚度 混单
            else {
                pageReqVO.setThicknessList(thickness);

            }
        } else {
            // 非混单
            pageReqVO.setMaterialList(material);
            pageReqVO.setBrandList(brand);
            pageReqVO.setColorList(color);
            pageReqVO.setThicknessList(thickness);
            pageReqVO.setTextureList(texture);

        }

    }

    @Override
    public PageResult<OrderViewPlatePageRespVO> getBodyViewPlatesPage(OrderCadViewPlatePageReqVO pageReqVO) {
        Set<Long> bodyIds = pageReqVO.getBodyIds();
        Set<Long> groupIds = pageReqVO.getGroupIds();
        if (CollUtil.isEmpty(bodyIds)) {
            return new PageResult<>(Collections.emptyList(), 0L);
        }
        List<OrderBodyDO> orderBodyDOList = orderBodyMapper.selectByIds(bodyIds);
        if (CollUtil.isEmpty(orderBodyDOList)) {
            throw new ServiceException(ORDER_BODY_NOT_EXISTS);
        }

        // 整理出body_id和cad图纸id的关系
        Map<Long, OrderBodyDO> bodyIdAndCadViewFileIdMap = orderBodyDOList.stream()
                .filter(item -> item.getCadViewFileId() != null)
                .collect(Collectors.toMap(
                        OrderBodyDO::getId,
                        Function.identity(),
                        (a, b) -> a
                ));

        List<Long> orderIds = List.of(pageReqVO.getOrderId());

        Boolean deleted = pageReqVO.getDeleted();

        // 分页获取板件id
        IPage<Long> plateIdPage = orderItemMapper.selectOrdersViewPlateIdsPage(new PageDTO<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()),
                orderIds, bodyIds, groupIds, null, deleted);

        List<Long> plateIdPageRecords = plateIdPage.getRecords();
        if(CollUtil.isEmpty(plateIdPageRecords)) {
            return new PageResult<>(Collections.emptyList(), 0L);
        }

        // 查询板件+板材信息
        List<OrdersViewPlatesPageDO> ordersViewPlatesPageDOS = plateMapper.selectPlateGoodsByIds(orderIds, plateIdPageRecords, deleted);

        if (CollUtil.isEmpty(plateIdPageRecords)) {
            return new PageResult<>();
        }
        List<OrderItemDO> orderItemRelation;
        // 查询关联关系
        if(!deleted) {
            orderItemRelation = orderItemMapper.selectList(new LambdaQueryWrapperX<OrderItemDO>()
                    .eq(OrderItemDO::getOrderId, pageReqVO.getOrderId())
                    .inIfPresent(OrderItemDO::getBodyId, bodyIds)
                    .inIfPresent(OrderItemDO::getGroupId, groupIds)
                    .in(OrderItemDO::getPlateId, plateIdPageRecords)
                    .select(OrderItemDO::getPlateId, OrderItemDO::getRoomId, OrderItemDO::getBodyId, OrderItemDO::getCadViewId, OrderItemDO::getGroupId, OrderItemDO::getCompId)
            );
        } else {
            List<OrderItemTempDO> orderItemTempDOS = orderItemTempMapper.selectList(new LambdaQueryWrapperX<OrderItemTempDO>()
                    .eq(OrderItemTempDO::getOrderId, pageReqVO.getOrderId())
                    .inIfPresent(OrderItemTempDO::getBodyId, bodyIds)
                    .inIfPresent(OrderItemTempDO::getGroupId, groupIds)
                    .in(OrderItemTempDO::getPlateId, plateIdPageRecords)
                    .select(OrderItemTempDO::getPlateId, OrderItemTempDO::getRoomId, OrderItemTempDO::getBodyId, OrderItemTempDO::getCadViewId, OrderItemTempDO::getGroupId, OrderItemTempDO::getCompId)
            );
            orderItemRelation = BeanUtil.copyToList(orderItemTempDOS, OrderItemDO.class);
        }


        // 暂存plateId:set<groupId>
        Map<Long, Set<Long>> plateGroupMap = new HashMap<>();
        // 暂存plateId:set<compId>
        Map<Long, Set<Long>> plateCompMap = new HashMap<>();

        Map<Long, OrdersViewPlatesPageDO> plateMap =
                ordersViewPlatesPageDOS.stream()
                        .collect(Collectors.toMap(
                                OrdersViewPlatesPageDO::getId,
                                Function.identity(),
                                (a, b) -> a
                        ));

        for (OrderItemDO item : orderItemRelation) {

            Long plateId = item.getPlateId();

            // 累计plateId下group_id
            if (item.getGroupId() != null) {
                plateGroupMap
                        .computeIfAbsent(plateId, k -> new HashSet<>())
                        .add(item.getGroupId());
            }

            // 累计plateId下comp_id
            if (item.getCompId() != null) {
                plateCompMap
                        .computeIfAbsent(plateId, k -> new HashSet<>())
                        .add(item.getCompId());
            }

            // 单值字段
            OrdersViewPlatesPageDO plate = plateMap.get(plateId);
            if (plate != null) {
                plate.setBodyId(item.getBodyId());
                plate.setCadViewId(item.getCadViewId());
            }
        }

        // 查询加工组
        Set<Long> allGroupIds = plateGroupMap.values()
                .stream()
                .flatMap(Set::stream)
                .collect(Collectors.toSet());

        Map<Long, String> groupNameMap = Collections.emptyMap();

        if (!allGroupIds.isEmpty()) {
            groupNameMap = orderGroupMapper.selectByIds(allGroupIds)
                    .stream()
                    .collect(Collectors.toMap(
                            OrderGroupDO::getId,
                            OrderGroupDO::getName,
                            (a, b) -> a
                    ));
        }

        // 查询部件
        Set<Long> allCompIds = plateCompMap.values()
                .stream()
                .flatMap(Set::stream)
                .collect(Collectors.toSet());

        Map<Long, String> compNameMap = Collections.emptyMap();

        if (!allCompIds.isEmpty()) {
            compNameMap = orderComponentMapper.selectByIds(allCompIds)
                    .stream()
                    .collect(Collectors.toMap(
                            OrderComponentDO::getId,
                            OrderComponentDO::getName,
                            (a, b) -> a
                    ));
        }

        List<OrderViewPlatePageRespVO> records = new ArrayList<>();
        for (Map.Entry<Long, OrdersViewPlatesPageDO> entry : plateMap.entrySet()) {

            Long plateId = entry.getKey();
            OrdersViewPlatesPageDO plate = entry.getValue();

            OrderViewPlatePageRespVO plateRespVO = BeanUtil.copyProperties(plate, OrderViewPlatePageRespVO.class);

            // 用逗号拼接加工组名称
            Set<Long> plateGroupIds = plateGroupMap.getOrDefault(plateId, Collections.emptySet());
            List<String> groupNames = plateGroupIds.stream()
                    .map(groupNameMap::get)
                    .filter(Objects::nonNull)
                    .toList();

            plateRespVO.setProcessGroupName(String.join(",", groupNames));

            // 用逗号拼接部件组名称
            Set<Long> plateCompIds = plateCompMap.getOrDefault(plateId, Collections.emptySet());
            List<String> compNames = plateCompIds.stream()
                    .map(compNameMap::get)
                    .filter(Objects::nonNull)
                    .toList();

            plateRespVO.setComponentName(String.join(",", compNames));

            // 匹配房间名、柜体名、图纸id
            OrderBodyDO orderBodyDO = bodyIdAndCadViewFileIdMap.get(plate.getBodyId());
            if(ObjectUtil.isNotNull(orderBodyDO)) {
                plateRespVO.setBodyName(orderBodyDO.getName());
                plateRespVO.setRoomName(orderBodyDO.getRoomName());
                plateRespVO.setCadViewFileId(orderBodyDO.getCadViewFileId());
            }

            records.add(plateRespVO);
        }
        return new PageResult<>(records, plateIdPage.getTotal());
    }

    @Override
    public PageResult<OrderViewPartPageRespVO> getBodyViewPartsPage(OrderCadViewPlatePageReqVO pageReqVO) {
        Set<Long> bodyIds = pageReqVO.getBodyIds();
        Set<Long> groupIds = pageReqVO.getGroupIds();
        if (CollUtil.isEmpty(bodyIds)) {
            return new PageResult<>(Collections.emptyList(), 0L);
        }
        List<OrderBodyDO> orderBodyDOList = orderBodyMapper.selectByIds(bodyIds);
        if (CollUtil.isEmpty(orderBodyDOList)) {
            throw new ServiceException(ORDER_BODY_NOT_EXISTS);
        }

        boolean deleted = Boolean.TRUE.equals(pageReqVO.getDeleted());
        boolean fromGroup = CollUtil.isNotEmpty(groupIds);

        List<OrdersViewPartsPageDO> rows = orderItemMapper.selectOrdersViewPartsList(
                List.of(pageReqVO.getOrderId()),
                bodyIds,
                groupIds,
                null,
                pageReqVO.getName(),
                deleted
        );

        if (CollUtil.isEmpty(rows)) {
            return new PageResult<>(Collections.emptyList(), 0L);
        }

        Collection<OrderViewPartPageRespVO> records = buildBodyViewPartsGroup(rows, fromGroup);
        return new PageResult<>(new ArrayList<>(records), (long) records.size());
    }

    /**
     * 组装配件的加工组和部件
     *
     * @param rows
     * @param fromGroup
     * @return
     */
    private Collection<OrderViewPartPageRespVO> buildBodyViewPartsGroup(List<OrdersViewPartsPageDO> rows,
                                                                        boolean fromGroup) {
        Map<String, OrderViewPartPageRespVO> records = new LinkedHashMap<>();
        Map<String, Set<String>> processGroupNameMap = new HashMap<>();
        Map<String, Set<String>> componentNameMap = new HashMap<>();

        for (OrdersViewPartsPageDO row : rows) {
            if (!isBodyViewPartNumRow(row, fromGroup)) {
                continue;
            }

            String key = buildBodyViewPartKey(row);
            records.computeIfAbsent(key, k -> {
                OrderViewPartPageRespVO vo = BeanUtil.copyProperties(row, OrderViewPartPageRespVO.class);
                vo.setNum(BigDecimal.ZERO);
                vo.setProcessGroupName("");
                vo.setComponentName("");
                return vo;
            });
        }

        if (records.isEmpty()) {
            return Collections.emptyList();
        }

        for (OrdersViewPartsPageDO row : rows) {
            String key = buildBodyViewPartKey(row);
            OrderViewPartPageRespVO vo = records.get(key);
            if (vo == null) {
                continue;
            }

            if (isBodyViewPartNumRow(row, fromGroup) && row.getNum() != null) {
                vo.setNum(vo.getNum().add(row.getNum()));
            }

            if (row.getProcessGroupName() != null && !row.getProcessGroupName().isBlank()) {
                processGroupNameMap.computeIfAbsent(key, k -> new LinkedHashSet<>()).add(row.getProcessGroupName());
            }

            if (row.getComponentName() != null && !row.getComponentName().isBlank()) {
                componentNameMap.computeIfAbsent(key, k -> new LinkedHashSet<>()).add(row.getComponentName());
            }
        }

        for (Map.Entry<String, OrderViewPartPageRespVO> entry : records.entrySet()) {
            String key = entry.getKey();
            OrderViewPartPageRespVO vo = entry.getValue();

            vo.setProcessGroupName(String.join(",", processGroupNameMap.getOrDefault(key, Collections.emptySet())));
            vo.setComponentName(String.join(",", componentNameMap.getOrDefault(key, Collections.emptySet())));
        }

        return records.values();
    }

    /**
     * 配件累计规则
     *
     * @param row
     * @param fromGroup
     * @return
     */
    private boolean isBodyViewPartNumRow(OrdersViewPartsPageDO row, boolean fromGroup) {
        if (fromGroup) {
            return ObjectUtil.isNotNull(row.getGroupId()) && ObjectUtil.notEqual(row.getGroupId(), 0L);
        }
        return ObjectUtil.equals(row.getGroupId(), 0L)
                || (ObjectUtil.isNull(row.getGroupId()) && ObjectUtil.isNull(row.getCompId()));
    }

    /**
     * 柜体id+配件id+cadviewid key
     *
     * @param row
     * @return
     */
    private String buildBodyViewPartKey(OrdersViewPartsPageDO row) {
        return row.getBodyId() + "_" + row.getId() + "_" + row.getCadViewId();
    }

    @Override
    public OrdersViewCadViewInfoRespVO getBodyViewCadInfo(OrderCadViewPlatePageReqVO reqVO) {
        OrdersViewCadViewInfoRespVO ordersViewCadViewInfoRespVO = new OrdersViewCadViewInfoRespVO();
        Long orderId = reqVO.getOrderId();
        OrderDO orderDO = orderMapper.selectById(orderId);
        AssertUtils.notEmpty(orderDO, ORDER_NOT_EXISTS);

        Set<Long> bodyIds = reqVO.getBodyIds();

        // 匹配柜体
        if(CollUtil.isEmpty(bodyIds)) {
            return ordersViewCadViewInfoRespVO;
        }
        List<OrderBodyDO> orderBodyDOList = orderBodyMapper.selectByIds(bodyIds);
        if (CollUtil.isEmpty(orderBodyDOList)) {
            throw new ServiceException(ORDER_BODY_NOT_EXISTS);
        }

        // 整理出body_id和cad图纸id的关系
        Map<Long, Long> bodyIdAndCadViewFileIdMap = orderBodyDOList.stream()
                .filter(item -> item.getCadViewFileId() != null)
                .collect(Collectors.toMap(OrderBodyDO::getId, OrderBodyDO::getCadViewFileId));

        Boolean deleted = reqVO.getDeleted();

        // 查询所有板件的视图所需信息
        PageDTO<OrdersViewPlatesPageDO> page1 = new PageDTO<>(1, PageParam.PAGE_SIZE_NONE);
        IPage<OrdersViewPlatesPageDO> viewPlatesPage = orderItemMapper.selectOrdersViewPlatesPage(page1, List.of(orderId), bodyIds, reqVO.getGroupIds(), null, true, deleted);

        List<OrdersViewPlatesPageDO> plateRecords = viewPlatesPage.getRecords();

        // cad图纸id赋到每块板上
        if(CollUtil.isNotEmpty(plateRecords)) {
            plateRecords.forEach(item -> item.setCadViewFileId(bodyIdAndCadViewFileIdMap.get(item.getBodyId())));
        }

        // 查询所有配件的视图所需信息
        PageDTO<OrdersViewPartsPageDO> page2 = new PageDTO<>(1, PageParam.PAGE_SIZE_NONE);
        IPage<OrdersViewPartsPageDO> viewPartsPage = orderItemMapper.selectOrdersViewPartsPage(page2, List.of(orderId), bodyIds, reqVO.getGroupIds(), null, null, true, deleted);

        List<OrdersViewPartsPageDO> partRecords = viewPartsPage.getRecords();

        // cad图纸id赋到每个配件上
        if (CollUtil.isNotEmpty(partRecords)) {
            partRecords.forEach(item -> item.setCadViewFileId(bodyIdAndCadViewFileIdMap.get(item.getBodyId())));
        }

        ordersViewCadViewInfoRespVO.setPlates(BeanUtil.copyToList(plateRecords, OrderViewPlatePageRespVO.class));
        ordersViewCadViewInfoRespVO.setParts(BeanUtil.copyToList(partRecords, OrderViewPartPageRespVO.class));
        return ordersViewCadViewInfoRespVO;
    }

    @Override
    public OrdersViewCadViewInfoRespVO getBodyViewPartCadInfo(OrderCadViewPlatePageReqVO reqVO) {
        OrdersViewCadViewInfoRespVO ordersViewCadViewInfoRespVO = new OrdersViewCadViewInfoRespVO();
        Long orderId = reqVO.getOrderId();
        OrderDO orderDO = orderMapper.selectById(orderId);
        AssertUtils.notEmpty(orderDO, ORDER_NOT_EXISTS);

        Set<Long> bodyIds = reqVO.getBodyIds();

        // 匹配柜体
        if(CollUtil.isEmpty(bodyIds)) {
            return ordersViewCadViewInfoRespVO;
        }
        List<OrderBodyDO> orderBodyDOList = orderBodyMapper.selectByIds(bodyIds);
        if (CollUtil.isEmpty(orderBodyDOList)) {
            throw new ServiceException(ORDER_BODY_NOT_EXISTS);
        }

        // 整理出body_id和cad图纸id的关系
        Map<Long, Long> bodyIdAndCadViewFileIdMap = orderBodyDOList.stream()
                .filter(item -> item.getCadViewFileId() != null)
                .collect(Collectors.toMap(OrderBodyDO::getId, OrderBodyDO::getCadViewFileId));

        Boolean deleted = reqVO.getDeleted();

        // 查询所有配件的视图所需信息
        PageDTO<OrdersViewPartsPageDO> page = new PageDTO<>(1, PageParam.PAGE_SIZE_NONE);
        IPage<OrdersViewPartsPageDO> viewPartsPage = orderItemMapper.selectOrdersViewPartsPage(page, List.of(orderId), bodyIds, reqVO.getGroupIds(), null, reqVO.getName(), true, deleted);

        List<OrdersViewPartsPageDO> partRecords = viewPartsPage.getRecords();

        // cad图纸id赋到每个配件上
        if (CollUtil.isNotEmpty(partRecords)) {
            partRecords.forEach(item -> item.setCadViewFileId(bodyIdAndCadViewFileIdMap.get(item.getBodyId())));
        }

        ordersViewCadViewInfoRespVO.setParts(BeanUtil.copyToList(partRecords, OrderViewPartPageRespVO.class));
        return ordersViewCadViewInfoRespVO;
    }

    @Override
    public OrderPlateWechatMiniProgramCadInfoRespVO getPlateInfoByPlateNo(String plateNo) {
        // 1、解析组织id，查询板件信息
        Integer organId = Integer.parseInt(plateNo.substring(0, 5));
        organApi.validOrgan(organId.longValue()).checkError();

        PlateDO plateDO = plateMapper.selectOne(new LambdaQueryWrapper<PlateDO>()
                .eq(PlateDO::getOrganId, organId)
                .eq(PlateDO::getPlateNo, plateNo));

        if (ObjectUtil.isNull(plateDO)) {
            throw new ServiceException(PLATE_NOT_EXISTS);
        }
        Long orderId = plateDO.getOrderId();

        // 2、根据板id查询明细
        List<OrderItemDO> plateItemDOS = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>()
                .eq(OrderItemDO::getPlateId, plateDO.getId())
                .eq(OrderItemDO::getOrganId, organId)
                .eq(OrderItemDO::getOrderId, orderId)
        );
        if (CollUtil.isEmpty(plateItemDOS)) {
            throw new ServiceException(PLATE_NOT_EXISTS);
        }

        // 3、查询柜体获取图纸id
        OrderItemDO plateItemDO = plateItemDOS.get(0);
        // 板件cad id
        Integer cadViewId = plateItemDO.getCadViewId();
        OrderBodyDO orderBodyDO = orderBodyMapper.selectOne(new LambdaQueryWrapper<OrderBodyDO>()
                .eq(OrderBodyDO::getOrderId, orderId)
                .eq(OrderBodyDO::getId, plateItemDO.getBodyId())
                .eq(OrderBodyDO::getOrganId, organId)
        );
        // 图纸id
        Long cadViewFileId = orderBodyDO.getCadViewFileId();

        // 4、查询材料内容
        GoodsDO goodsDO = goodsMapper.selectOne(new LambdaQueryWrapper<GoodsDO>()
                .eq(GoodsDO::getOrderId, orderId)
                .eq(GoodsDO::getId, plateDO.getGoodsId())
                .eq(GoodsDO::getOrganId, organId)
        );

        return OrderPlateWechatMiniProgramCadInfoRespVO
                .builder()
                .roomName(orderBodyDO.getRoomName())
                .bodyName(orderBodyDO.getName())
                .plateNo(plateDO.getPlateNo())
                .plateName(plateDO.getName())
                .width(plateDO.getWidth())
                .height(plateDO.getHeight())
                .thickness(plateDO.getThickness())
                .sealLeft(plateDO.getSealLeft())
                .sealRight(plateDO.getSealRight())
                .sealUp(plateDO.getSealUp())
                .sealDown(plateDO.getSealDown())
                .material(goodsDO.getMaterial())
                .color(goodsDO.getColor())
                .remark(plateDO.getRemark())
                .cadViewFileId(cadViewFileId)
                .cadViewId(cadViewId)
                .build();
    }

    @Override
    public OrderWechatMiniProgramCadInfoRespVO getOrderInfoByPlateNo(String plateNo) {
        OrderWechatMiniProgramCadInfoRespVO result = new OrderWechatMiniProgramCadInfoRespVO();
        // 1、解析组织id，查询板件信息
        Integer organId = Integer.parseInt(plateNo.substring(0, 5));
        Long organIdLong = organId.longValue();
        organApi.validOrgan(organId.longValue()).checkError();

        PlateDO plateDO = plateMapper.selectOne(new LambdaQueryWrapper<PlateDO>()
                .eq(PlateDO::getOrganId, organIdLong)
                .eq(PlateDO::getPlateNo, plateNo));

        if (ObjectUtil.isNull(plateDO)) {
            throw new ServiceException(PLATE_NOT_EXISTS);
        }
        Long orderId = plateDO.getOrderId();

        // 2、查询订单信息
        OrderDO order = orderService.getOrder(orderId, organIdLong);
        if (ObjectUtil.isNull(order)) {
            throw new ServiceException(ORDER_NOT_EXISTS);
        }
        result.setOrder(BeanUtil.copyProperties(order, OrderRespVO.class));

        // 3、查询柜体信息
        result.setOrderBodyList(orderBodyService.getOrderBodyList(orderId, organIdLong));

        // 4、查询部件信息
        result.setOrderComponentList(orderComponentService.getOrderComponentListOnOrders(List.of(orderId), organIdLong));
        return result;
    }

    @Override
    public OrdersViewCadViewInfoRespVO getOrderDetailsByPlateNo(String plateNo, OrderWechatMiniProgramDetailReqVO reqVO) {
        // 1、解析组织id，查询板件信息
        Integer organId = Integer.parseInt(plateNo.substring(0, 5));
        Long organIdLong = organId.longValue();
        organApi.validOrgan(organId.longValue()).checkError();

        OrganContextHolder.setIgnore(false);
        OrganContextHolder.setOrganId(organIdLong);

        PlateDO plateDO = plateMapper.selectOne(new LambdaQueryWrapper<PlateDO>()
                .eq(PlateDO::getOrganId, organIdLong)
                .eq(PlateDO::getPlateNo, plateNo));

        if (ObjectUtil.isNull(plateDO)) {
            throw new ServiceException(PLATE_NOT_EXISTS);
        }

        OrderDetailComponentPageReqVO detailReqVO = new OrderDetailComponentPageReqVO();
        detailReqVO.setOrderId(plateDO.getOrderId());
        detailReqVO.setComponentIds(reqVO.getComponentIds());

        // 入参的柜体缺省用板件本身的柜体id
        Set<Long> bodyIds = reqVO.getBodyIds();
        if (CollUtil.isNotEmpty(bodyIds)) {
            detailReqVO.setBodyIds(bodyIds);
        } else {
            List<OrderItemDO> plateItems = orderItemService.getPlateItemCompId(plateDO.getOrderId(), plateDO.getId());
            if (CollUtil.isEmpty(plateItems)) {
                throw new ServiceException(PLATE_NOT_EXISTS);
            }
            detailReqVO.setBodyIds(Set.of(plateItems.get(0).getBodyId()));
        }

        return orderComponentService.getOrderViewCadInfo(detailReqVO);
    }
}