package com.cf.imes.module.executor.service.manage.pack;


import cn.hutool.core.collection.CollUtil;
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.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.QueryWrapperX;
import com.cf.imes.module.executor.api.plan.OrderPlanApi;
import com.cf.imes.module.executor.controller.admin.manage.pack.prePack.PackPlateList;
import com.cf.imes.module.executor.controller.admin.manage.pack.prePack.PrePackOptimizeInfo;
import com.cf.imes.module.executor.controller.admin.manage.pack.prePack.PrePackReqVO;
import com.cf.imes.module.executor.controller.admin.manage.pack.vo.*;
import com.cf.imes.module.executor.controller.admin.manage.query.vo.pack.OrderPackageVO;
import com.cf.imes.module.executor.dal.dataobject.order.OrderDO;
import com.cf.imes.module.executor.dal.dataobject.orderItem.OrderItemDO;
import com.cf.imes.module.executor.dal.dataobject.orderParts.OrderPartsDO;
import com.cf.imes.module.executor.dal.dataobject.pack.OrderPackageDO;
import com.cf.imes.module.executor.dal.dataobject.pack.OrderPrepackagedDO;
import com.cf.imes.module.executor.dal.dataobject.plate.PlateDO;
import com.cf.imes.module.executor.dal.mysql.order.OrderMapper;
import com.cf.imes.module.executor.dal.mysql.orderItem.OrderItemMapper;
import com.cf.imes.module.executor.dal.mysql.orderParts.OrderPartsMapper;
import com.cf.imes.module.executor.dal.mysql.pack.OrderPackageMapper;
import com.cf.imes.module.executor.dal.mysql.pack.OrderPrepackagedMapper;
import com.cf.imes.module.executor.dal.mysql.plate.PlateMapper;
import com.cf.imes.module.system.api.setting.SettingApi;
import com.cf.imes.module.system.api.setting.dto.PackageConfigDTO;
import com.cf.imes.module.system.enums.ErrorCodeConstants;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.aop.framework.AopContext;
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.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.cf.imes.framework.common.util.string.SearchUtil.insertSeparator;
import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getUserOrganId;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.*;

@Service
@Validated
public class PackServiceImpl implements PackService {

    @Resource
    private OrderPackageMapper orderPackageMapper;


    @Resource
    private OrderItemMapper orderItemMapper;

    @Resource
    private OrderPartsMapper orderPartsMapper;

    @Resource
    private PlateMapper orderPlateMapper;

    @Resource
    private OrderMapper ordersMapper;

    @Resource
    private SnowflakeIdWorker3rd idWorker;

    @Resource
    private OrderPrepackagedMapper orderPrepackagedMapper;


    @Resource
    private SettingApi settingApi;

    @Resource
    private OrderPlanApi orderPlanApi;


    // 打包分页查询
    @Override
    public PageResult<PackRespVO> getPackPage(PackPageReqVO pageReqVO) {

        PageDTO<PackRespVO> page = new PageDTO<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());

        List<Long> orderIds = new ArrayList<>();


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

            return handleIsUpCase(pageReqVO, orderIds,pageReqVO.getIsUp());

        } else {

            return handleNormalCase(pageReqVO, orderIds, page);

        }


    }



    // 查看生产订单对应的板材信息
    @Override
    public List<PlateDetailsRespVO> getOrderPlateList(Long orderId) {

        // 查询订单对应的板件信息
        List<PlateDetailsRespVO> plateDetailsRespVOS = orderPlateMapper.selectOrderNoPackPlateList(orderId, getUserOrganId());

        if(plateDetailsRespVOS.isEmpty()){
            return new ArrayList<>();
        }

        for (PlateDetailsRespVO plateDetailsRespVO : plateDetailsRespVOS) {
            StringBuilder name = new StringBuilder();
            if (!plateDetailsRespVO.getProcessGroupNameList().isEmpty()) {
                for (GroupNameList groupNameList : plateDetailsRespVO.getProcessGroupNameList()) {
                    // 去除最后的逗号
                    name.append(groupNameList.getName()).append(",");

                }
                name = new StringBuilder(name.substring(0, name.length() - 1));
            }
            plateDetailsRespVO.setProcessGroup(name.toString());
        }

        return plateDetailsRespVOS;


    }


    // 查询多个生产单对应的板材信息
    @Override
    public List<PlateDetailsRespVO> getOrdersPlateList(List<Long> orderIds) {

        List<PlateDetailsRespVO> plateDetailsRespVOS = orderPlateMapper.selectOrderPackPlateList(orderIds,getUserOrganId());

        if (plateDetailsRespVOS.isEmpty()) {

            return new ArrayList<>();
        }

        List<Long> packageIds = plateDetailsRespVOS.stream().map(PlateDetailsRespVO::getPackageId).distinct().toList();
        List<OrderPackageDO> orderPackageDOS = new ArrayList<>();
        if (!packageIds.isEmpty()) {
            orderPackageDOS = orderPackageMapper.selectBatchIds(packageIds);
        }


        for (PlateDetailsRespVO plateDetailsRespVO : plateDetailsRespVOS) {
            StringBuilder name = new StringBuilder();
            if (!plateDetailsRespVO.getProcessGroupNameList().isEmpty()) {
                for (GroupNameList groupNameList : plateDetailsRespVO.getProcessGroupNameList()) {
                    // 去除最后的逗号
                    name.append(groupNameList.getName()).append(",");
                }
                name = new StringBuilder(name.substring(0, name.length() - 1));
            }
            plateDetailsRespVO.setProcessGroup(name.toString());

            plateDetailsRespVO.setPackageNo(orderPackageDOS.stream()
                    .filter(m -> m.getId().equals(plateDetailsRespVO.getPackageId()))
                    .map(OrderPackageDO::getPackageNo).findFirst().orElse(""));

        }

        return plateDetailsRespVOS;


    }


    // 查看生产订单对应的包裹信息
    @Override
    public List<OrderPackageVO> getOrderPack(PackageDetailsReqVO reqVO) {


        List<OrderPackageVO> orderPackageVOS = orderPackageMapper.selectPackListByOrderId(Long.valueOf(reqVO.getOrderId()), getUserOrganId());

        if(orderPackageVOS.isEmpty()){
            return new ArrayList<>();
        }

        OrderDO orderDO = ordersMapper.selectById(reqVO.getOrderId());

        AssertUtils.notEmpty(orderDO,ORDER_DATE_ERROR);

        orderPackageVOS.forEach(m -> {
                    m.setCustomOrderNo(orderDO.getCustomOrderNo());
                    m.setCustomer(orderDO.getCustomer());
                    m.setAddress(orderDO.getAddress());
                    m.setDealer(orderDO.getDealer());
                    m.setOrderRemark(orderDO.getRemark());
                }
        );

        return orderPackageVOS;

    }


    @Override
    public PageResult<OrderPackageVO> getPageOrderPack(PackageDetailsReqVO reqVO) {

        PageDTO<OrderPackageVO> page = new PageDTO<>(reqVO.getPageNo(), reqVO.getPageSize());

        List<Long> packId = null;

        Long orderId = Long.valueOf(reqVO.getOrderId());

        if (reqVO.getPlateNo() != null) {

            List<Long> plateId = orderPlateMapper.selectplateByPlateNoList(reqVO.getPlateNo(), orderId, getUserOrganId())
                    .stream().map(PlateDO::getId).toList();

            if (plateId.isEmpty()) {
                return null;
            }

            packId = orderItemMapper.selectPackByPlateId(plateId,orderId ,getUserOrganId()).stream().map(OrderItemDO::getPackageId).distinct().toList();

        }


        QueryWrapperX<OrderPackageDO> queryWrapperX = new QueryWrapperX<>();
        queryWrapperX
                .eq("o.organ_id", getUserOrganId())
                .eq("o.deleted", false)
                .eq("o.id", reqVO.getOrderId())
                .eq("op.deleted", false)
                .likeIfPresent("op.package_no", reqVO.getPackageNo())
                .inIfPresent("op.id", packId)
                .eqIfPresent("op.status", reqVO.getPackStatus())
                .orderByDesc("op.create_time");


        IPage<OrderPackageVO> orderPackageDOIPage = orderPackageMapper.selectByOrderNo(page, queryWrapperX);


        if (CollUtil.isEmpty(orderPackageDOIPage.getRecords())) {
            return new PageResult<>();
        }


        return new PageResult<>(orderPackageDOIPage.getRecords(), orderPackageDOIPage.getTotal());

    }


    // 查看配件列表分页
    @Override
    public List<OrderPartsRespVO> getPartsList(OrderPartsReqVO reqVO) {

        List<OrderPartsRespVO> orderPartsRespVOS = orderPartsMapper.selectPartsList(reqVO.getOrderId(), getUserOrganId());

        orderPartsRespVOS.forEach(f->{
            f.setNum(f.getCount().stream().reduce(BigDecimal.ZERO, BigDecimal::add));

            f.setCount(null);
            f.setBodyId(null);
            f.setRoomId(null);
            f.setGroupId(null);
        });

        return orderPartsRespVOS;

    }


    // 更新配件
    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderPackRespVO updateParts(OrderPartsReqVO reqVO) {

        validateOrdersExists(reqVO.getOrderId(),null);

        // 判断包裹ID是否为空，为空，走新增，不为空，走更新
        if (reqVO.getPackId() == null) {

            OrderPackageDO orderPackageDO = new OrderPackageDO();
            orderPackageDO.setOrderId(reqVO.getOrderId());
            orderPackageDO.setType(OrderPackageTypeEnum.PARTS.getType());
            orderPackageDO.setPackageNo(generatePackageNo());
            orderPackageDO.setStatus((OrderPackageStatusEnum.PACKAGED.getStatus()));
            orderPackageMapper.insert(orderPackageDO);
            // 生产单明细表新增包裹 ID
            if (reqVO.getAddPartsIdList() != null) {
                orderItemMapper.insertPartsId(orderPackageDO.getId(), reqVO.getAddPartsIdList(), reqVO.getOrderId(), getUserOrganId());
            }

            // 判断当前生产单的板材和配件是否已全部打包且当前生产单的包裹已全部封包
            if (validateOrderPack(reqVO.getOrderId())) {

                PackServiceImpl p = (PackServiceImpl)AopContext.currentProxy();
                p.updateOrderStatus(reqVO.getOrderId());

            }

            return typeConversion(orderPackageDO);

        }


        if(reqVO.getAddPartsIdList().isEmpty() && reqVO.getAddPlateIdList().isEmpty() && reqVO.getDeletePartsIdList().isEmpty()){
            throw exception(PART_PACK_DATA_ERROR);
        }


        OrderPackageDO orderPackageDO = orderPackageMapper.selectByPackId(reqVO.getPackId(),reqVO.getOrderId(), getUserOrganId());

        AssertUtils.notEmpty(orderPackageDO,ORDER_PACK_DATA_ERROR);
        List<OrderItemDO> orderItemDOS = orderItemMapper.selectPackList(reqVO.getPackId(), reqVO.getOrderId(), getUserOrganId());
        List<Long> partsList = orderItemDOS.stream().map(OrderItemDO::getPartsId).distinct().toList();


        // 如果此时删除的包裹配件数量等于查询出来的配件数量，且新增的板材数量不为0，更改包裹的类型
        if (reqVO.getDeletePartsIdList().size() == partsList.size() && !reqVO.getAddPlateIdList().isEmpty()) {


            // 删除生产单明细表配件对应的包裹ID
            orderItemMapper.deletePartsList(reqVO.getDeletePartsIdList(), reqVO.getPackId(), reqVO.getOrderId(), getUserOrganId());


            // 生产单明细表板材新增对应的包裹ID
            orderItemMapper.insertPackId(reqVO.getAddPlateIdList(), reqVO.getPackId(), reqVO.getOrderId(), getUserOrganId());


            // 更新包裹类型和包裹的状态
            orderPackageDO.setType(OrderPackageTypeEnum.PLATE.getType());
            orderPackageDO.setStatus(OrderPackageStatusEnum.PACKAGED.getStatus());
            orderPackageMapper.updateById(orderPackageDO);
            return typeConversion(orderPackageDO);

        }


        // 生产明细表新增的配件ID
        if (!reqVO.getAddPartsIdList().isEmpty()) {
            orderItemMapper.insertParts(reqVO.getAddPartsIdList(), reqVO.getPackId(), reqVO.getOrderId(), getUserOrganId());
        }
        // 生产明细表删除的配件ID
        if (!reqVO.getDeletePartsIdList().isEmpty()) {
            orderItemMapper.deletePartsList(reqVO.getDeletePartsIdList(), reqVO.getPackId(), reqVO.getOrderId(), getUserOrganId());
        }
        orderPackageDO.setStatus(OrderPackageStatusEnum.PACKAGED.getStatus());

        orderPackageMapper.updateById(orderPackageDO);


        // 判断当前生产单的板材和配件是否已全部打包且当前生产单的包裹已全部封包
        if (validateOrderPack(reqVO.getOrderId())) {

            PackServiceImpl p = (PackServiceImpl)AopContext.currentProxy();
            p.updateOrderStatus(reqVO.getOrderId());

        }

        return typeConversion(orderPackageDO);
    }


    // 拆包
    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderPackRespVO unpacking(Long packageID) {

        OrderPackageDO packageDO = orderPackageMapper.selectById(packageID);

        AssertUtils.notEmpty(packageDO,ORDER_PACK_DATA_NULL_ERROR );

        Long orderId = packageDO.getOrderId();

        OrderDO orderDO = ordersMapper.selectById(orderId);

        AssertUtils.notEmpty(orderDO,ORDER_NO_DATA_ERROR);

        orderDO.setPackaged(OrderPackageStatusEnum.UNPACKED.getStatus());

        if(orderDO.getStatus().equals(OrderStatusEnum.FINISH_PRODUCTION.getStatus())){
            orderDO.setStatus(OrderStatusEnum.IN_PRODUCTION.getStatus());
            orderDO.setFinishTime(null);
        }

        ordersMapper.updateById(orderDO);

        packageDO.setStatus(OrderPackageStatusEnum.UNPACKED.getStatus());
        orderPackageMapper.updateById(packageDO);
        return typeConversion(packageDO);


    }


    // 更新包裹
    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderPackRespVO updatePack(OrderPackReqVO packageVO) {

        validateOrdersExists(packageVO.getOrderId(),null);

        // 判断包裹ID是否为空，为空，走新增，不为空，走更新
        if (packageVO.getPackId() == null) {

            OrderPackageDO orderPackageDO = new OrderPackageDO();
            orderPackageDO.setOrderId(packageVO.getOrderId());
            orderPackageDO.setType(OrderPackageTypeEnum.PLATE.getType());
            orderPackageDO.setPackageNo(generatePackageNo());
            orderPackageDO.setStatus((OrderPackageStatusEnum.PACKAGED.getStatus()));
            orderPackageDO.setRemark(packageVO.getRemark());
            orderPackageMapper.insert(orderPackageDO);
            // 生产单明细表新增包裹 ID
            if (packageVO.getAddPlateIdList() != null) {
                orderItemMapper.insertPackId(packageVO.getAddPlateIdList(), orderPackageDO.getId(), packageVO.getOrderId(), getUserOrganId());
            }

            if (validateOrderPack(packageVO.getOrderId())) {

                PackServiceImpl p = (PackServiceImpl)AopContext.currentProxy();
                p.updateOrderStatus(packageVO.getOrderId());
            }

            return typeConversion(orderPackageDO);
        }


        if(packageVO.getAddPlateIdList().isEmpty() && packageVO.getAddPartsIdList().isEmpty() && packageVO.getDeletePlateIdList().isEmpty()){
            throw exception(PART_PACK_DATA_ERROR);
        }


        OrderPackageDO orderPackageDO = orderPackageMapper.selectByPackId(packageVO.getPackId(),packageVO.getOrderId(), getUserOrganId());

        AssertUtils.notEmpty(orderPackageDO,ORDER_PACK_DATA_ERROR);

        List<OrderItemDO> orderItemDOS = orderItemMapper.selectPackList(packageVO.getPackId(), packageVO.getOrderId(), getUserOrganId());
        List<Long> plateList = orderItemDOS.stream().map(OrderItemDO::getPlateId).distinct().toList();


        // 如果此时删除的包裹板材数量等于查询出来的板材数量，且新增的配件数量不为0，更改包裹的类型
        if (packageVO.getDeletePlateIdList().size() == plateList.size() && !packageVO.getAddPartsIdList().isEmpty()) {


            // 删除生产单明细表板件对应的包裹ID
            orderItemMapper.deletePackId(packageVO.getDeletePlateIdList(), packageVO.getPackId(), packageVO.getOrderId(), getUserOrganId());


            // 生产单明细表配件新增对应的包裹ID
            orderItemMapper.insertParts(packageVO.getAddPartsIdList(), packageVO.getPackId(), packageVO.getOrderId(), getUserOrganId());


            // 更新包裹类型和包裹的状态
            orderPackageDO.setType(OrderPackageTypeEnum.PARTS.getType());
            orderPackageDO.setStatus(OrderPackageStatusEnum.PACKAGED.getStatus());
            orderPackageMapper.updateById(orderPackageDO);
            return typeConversion(orderPackageDO);

        }


        // 生产明细表新增包裹ID
        if (!packageVO.getAddPlateIdList().isEmpty()) {
            orderItemMapper.insertPackId(packageVO.getAddPlateIdList(), packageVO.getPackId(), packageVO.getOrderId(), getUserOrganId());
        }

        // 移除生产明细表中板件对应的包裹ID
        if (!packageVO.getDeletePlateIdList().isEmpty()) {
            orderItemMapper.deletePackId(packageVO.getDeletePlateIdList(), packageVO.getPackId(), packageVO.getOrderId(), getUserOrganId());
        }
        orderPackageDO.setStatus(OrderPackageStatusEnum.PACKAGED.getStatus());

        orderPackageMapper.updateById(orderPackageDO);


        // 判断当前生产单的板材和配件是否已全部打包且当前生产单的包裹已全部封包
        if (validateOrderPack(packageVO.getOrderId())) {

            // 修改生产单的打包状态
            PackServiceImpl p = (PackServiceImpl)AopContext.currentProxy();
            p.updateOrderStatus(packageVO.getOrderId());

        }

        return typeConversion(orderPackageDO);

    }


    // 判断当前生产单的板材和配件是否已全部打包且当前生产单的包裹已全部封包
    public Boolean validateOrderPack(Long orderId) {

        List<OrderPackageDO> orderPackageDOS = orderPackageMapper.selectPackList(orderId, getUserOrganId());

        if (!orderPackageDOS.isEmpty()) {
            return false;
        }

        List<PlateAndPartIdList> partsIds = orderItemMapper.selectOrderPackPartsIds(orderId, getUserOrganId());

        List<PlateAndPartIdList> plateIds = orderItemMapper.selectOrderPackPlateIds(orderId, getUserOrganId());

        return partsIds.isEmpty() && plateIds.isEmpty();

    }


    // 修改当前生产单的工序状态和生产单的状态
    @Transactional(rollbackFor = Exception.class)
    public void updateOrderStatus(Long orderId) {

        OrderDO orderDO = ordersMapper.selectById(orderId);


        // 修改生产单的打包状态为已打包
        orderDO.setPackaged(OrderPackageStatusEnum.PACKAGED.getStatus());


        if(orderPlanApi.getOrder(orderId).getData()){
            orderDO.setStatus(OrderStatusEnum.FINISH_PRODUCTION.getStatus());
            orderDO.setFinishTime(LocalDateTime.now());
        }


        ordersMapper.updateById(orderDO);



    }


    // 查询包裹
    @Override
    public List<OrderPackRespVO> selectPack(Long orderId) {

        List<OrderPackageDO> orderPackageDOS = orderPackageMapper.selectPackStatus(orderId, getUserOrganId());

        return orderPackageDOS.stream().map(this::typeConversion).toList();

    }




    // 删除包裹及其关联的包裹信息(删除全部)
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteOrderPack(PackReqVO reqVO) {



        // 判断包裹的类型是否为其他类型，如果是，则删除其包裹信息
        if (reqVO.getIsOther()) {

            List<Long> partsIds = orderItemMapper.selectPackList(reqVO.getPackageId(), reqVO.getOrderId(), getUserOrganId())
                    .stream().map(OrderItemDO::getPartsId)
                    .distinct()
                    .toList();
            if(partsIds.isEmpty()){
                return;
            }

            orderPartsMapper.deleteOrderParts(partsIds, reqVO.getOrderId(), getUserOrganId());

            orderPackageMapper.updateParts(reqVO.getPackageId(), reqVO.getOrderId(), getUserOrganId());

            orderItemMapper.deleteParts(reqVO.getPackageId(), reqVO.getOrderId(), partsIds, getUserOrganId());

            List<OrderPackageDO> orderPackageDOS = orderPackageMapper.selectPackStatusList(reqVO.getOrderId(), getUserOrganId());

            if(orderPackageDOS.isEmpty()){

                OrderDO orderDO = ordersMapper.selectById(reqVO.getOrderId());

                orderDO.setPackaged(OrderPackageStatusEnum.UNPACKED.getStatus());

                ordersMapper.updateById(orderDO);

            }

            return;
        }



        orderPackageMapper.updateParts(reqVO.getPackageId(), reqVO.getOrderId(), getUserOrganId());

        orderItemMapper.deleteOrderPack(reqVO.getPackageId(), reqVO.getOrderId(), getUserOrganId());

        orderPrepackagedMapper.deletePacked(reqVO.getOrderId(),getUserOrganId());


        List<OrderPackageDO> orderPackageDOS = orderPackageMapper.selectPackStatusList(reqVO.getOrderId(), getUserOrganId());

        if(orderPackageDOS.isEmpty()){

            OrderDO orderDO = ordersMapper.selectById(reqVO.getOrderId());

            orderDO.setPackaged(OrderPackageStatusEnum.UNPACKED.getStatus());

            ordersMapper.updateById(orderDO);

        }

    }


    // 新增外部配件包裹表
    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderPackRespVO addNewOtherPack(OtherPackReqVO reqVO) {


        // 配件表新增数据
        OrderPartsDO orderParts = BeanUtils.toBean(reqVO, OrderPartsDO.class);
        // 因为是外部配件，所以配件类型的名称固定为 “ 外部配件”
        orderParts.setType("外部配件");
        orderParts.setUnit(reqVO.getUnit());
        orderPartsMapper.insert(orderParts);


        // 在包裹表中添加包裹编号和生产单号，修改包裹类型未其他配件类型
        OrderPackageDO orderPackageDO = new OrderPackageDO();
        orderPackageDO.setPackageNo(generatePackageNo());
        orderPackageDO.setOrderId(reqVO.getOrderId());
        orderPackageDO.setType(OrderPackageTypeEnum.OTHER_ACCESSORIES.getType());

        // 新增包裹
        orderPackageMapper.insert(orderPackageDO);


        // 在生产单明细表中添加数据（生产单号，配件ID，包裹ID，部件数量）
        OrderItemDO orderItemDO = new OrderItemDO();
        orderItemDO.setOrderId(reqVO.getOrderId());
        orderItemDO.setType(OrderItemTypeEnum.QUOTATIONACCESSORIES.getType());
        orderItemDO.setPartsId(orderParts.getId());
        orderItemDO.setPackageId(orderPackageDO.getId());
        orderItemDO.setNum(reqVO.getNum());


        // 在生产单明细表中新增数据
        orderItemMapper.insert(orderItemDO);

        // 查看新增的包裹信息
        return typeConversion(orderPackageDO);


    }


    // 新增外部配件
    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderPartsRespVO addNewOtherParts(OtherPackReqVO reqVO) {

        OrderPackageDO orderPackageDO = orderPackageMapper.selectByPackNo(reqVO.getPackNo(), getUserOrganId());
        if (orderPackageDO.getType() != OrderPackageTypeEnum.OTHER_ACCESSORIES.getType().longValue()) {
            throw exception(THE_CURRENT_PACKAGE_TYPE_IS_INCORRECT);
        }


        // 配件表新增数据
        OrderPartsDO orderParts = BeanUtils.toBean(reqVO, OrderPartsDO.class);
        // 因为是外部配件，所以配件类型的名称固定为 “ 外部配件”
        orderParts.setType("外部配件");
        orderParts.setUnit(reqVO.getUnit());
        orderPartsMapper.insert(orderParts);

        // 在生产单明细表中添加数据（生产单号，配件ID，包裹ID，部件数量）
        OrderItemDO orderItemDO = new OrderItemDO();
        orderItemDO.setOrderId(reqVO.getOrderId());
        orderItemDO.setPartsId(orderParts.getId());
        orderItemDO.setPackageId(orderPackageDO.getId());
        orderItemDO.setNum(reqVO.getNum());

        // 在生产单明细表中新增数据
        orderItemMapper.insert(orderItemDO);

        return BeanUtils.toBean(orderParts, OrderPartsRespVO.class);

    }


    // 删除包裹中的外部配件
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteOtherParts(DeleteOtherPartsReqVO reqVO) {


        if (reqVO.getIsOtherParts()) {
            // 更新配件表中配件为逻辑删除
            orderPartsMapper.updateParts(reqVO.getPartsId(), reqVO.getOrderId(), getUserOrganId());
            orderItemMapper.deleteOtherParts(reqVO.getPartsId(), reqVO.getOrderId(), getUserOrganId());
        }

        orderItemMapper.updateParts(reqVO.getPartsId(), reqVO.getPackageId(), reqVO.getOrderId(), getUserOrganId());

    }


    // 查询预打包优化信息
    @Override
    public String getPrePackInfo(Long orderId) {


        OrderPrepackagedDO orderPrepackagedDO = orderPrepackagedMapper.selectOrder(orderId, getUserOrganId());


        if (orderPrepackagedDO == null) {
            return null;
        }


        return JsonUtils.unzipString(orderPrepackagedDO.getResult());

    }


    // 保存优化后的预打包信息
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOptimizeInfo(PrePackReqVO reqVO) {


        PackageConfigDTO userSetting = settingApi.getUserSetting(UserSettingTypeEnum.PREPACKAGED.getType());

        String setting = userSetting.getSetting();

        if (setting == null) {

            throw exception(CURRENTLY_NO_CONFIGURATION_AVAILABLE, UserSettingTypeEnum.PREPACKAGED.getName());
        }

        JsonNode settingParse = JsonUtils.parseTree(JsonUtils.unzipString(setting));

        boolean autoPack = settingParse.get("autoPack").asBoolean();


        String optimizeInfo = reqVO.getOptimizeInfo();

        // 自动打包，包裹表新增
        if (autoPack) {

            ArrayList<OrderPackageDO> orderPackageDOS = new ArrayList<>();

            List<PackPlateList> packPlateNoLists = new ArrayList<>();

            ObjectMapper objectMapper = new ObjectMapper();

            JsonNode jsonNode = JsonUtils.parseTree(reqVO.getOptimizeInfo());

            List<PrePackOptimizeInfo> asJsonObject = objectMapper.convertValue(jsonNode, new TypeReference<>() {
            });


            asJsonObject.forEach(value -> {

                value.getList().forEach(prePackOptimizeInfo -> {

                    String packageNo = generatePackageNo();
                    prePackOptimizeInfo.setName(packageNo);
                    orderPackageDOS.add(OrderPackageDO.builder()
                            .packageNo(packageNo)
                            .type(OrderPackageTypeEnum.PLATE.getType())
                            .orderId(reqVO.getOrderId())
                            .status(OrderPackageStatusEnum.PACKAGED.getStatus())
                            .build());
                    prePackOptimizeInfo.getList().forEach(plate -> {
                        List<String> list = plate.getList().stream().map(PrePackOptimizeInfo.PrerPlateData::getPlateId).toList();
                        list.forEach(a -> packPlateNoLists.add(PackPlateList.builder()
                                .packNo(packageNo)
                                .plateId(Long.valueOf(a))
                                .build()));
                    });

                });

            });


            optimizeInfo = JsonUtils.toJsonString(asJsonObject);

            List<OrderPackageDO> packageDOS = orderPackageMapper.selectPackStatus(reqVO.getOrderId(), getUserOrganId());

            if (!packageDOS.isEmpty()) {
                // 删除除配件和其他配件外的所有包裹
                orderPackageMapper.updateDelete(reqVO.getOrderId(), getUserOrganId());
            }

            // 包裹表新增包裹
            orderPackageMapper.insertBatch(orderPackageDOS);

            // 根据包裹编号查找包裹ID
            orderPackageDOS.forEach(a ->
                    packPlateNoLists.stream().filter(f -> Objects.equals(f.getPackNo(), a.getPackageNo()))
                            .forEach(f -> f.setPackId(a.getId())));

            List<OrderItemDO> orderItemDOS = orderItemMapper.selectPackPlateList(reqVO.getOrderId(), getUserOrganId());


            packPlateNoLists.forEach(a ->
                    orderItemDOS.stream().filter(f -> Objects.equals(f.getPlateId(), a.getPlateId()))
                            .forEach(f -> f.setPackageId(a.getPackId())));

            orderItemMapper.updateBatch(orderItemDOS);

            // 查询配件是否为空，为空，修改生产单的状态为已打包
            List<PlateAndPartIdList> partsIds = orderItemMapper.selectOrderPackPartsIds(reqVO.getOrderId(), getUserOrganId());

            if (partsIds.isEmpty()) {
                OrderDO orderDO = ordersMapper.selectById(reqVO.getOrderId());
                orderDO.setPackaged(OrderPackageStatusEnum.PACKAGED.getStatus());
                if(Boolean.TRUE.equals(orderPlanApi.getOrder(reqVO.getOrderId()).getData())){
                    orderDO.setStatus(OrderStatusEnum.FINISH_PRODUCTION.getStatus());
                    orderDO.setFinishTime(LocalDateTime.now());
                }
                ordersMapper.updateById(orderDO);
            }

        }


        OrderPrepackagedDO orderPackOptimizeDO = orderPrepackagedMapper.selectOrder(reqVO.getOrderId(), getUserOrganId());

        if (orderPackOptimizeDO == null) {

            OrderPrepackagedDO prepackagedDO = new OrderPrepackagedDO();
            prepackagedDO.setOrderId(reqVO.getOrderId());
            prepackagedDO.setResult(JsonUtils.zipString(optimizeInfo));
            orderPrepackagedMapper.insert(prepackagedDO);
            return;
        }

        orderPackOptimizeDO.setResult(JsonUtils.zipString(optimizeInfo));
        orderPrepackagedMapper.updateById(orderPackOptimizeDO);


    }


    // 日期格式转换
    public static String convertTime(String input) {

        SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        try {
            Date date = inputFormat.parse(input);
            date.setTime(date.getTime() + 8 * 60 * 60 * 1000); // 将时间转换为东夏令时
            return outputFormat.format(date);
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }


    // 生成包裹编号
    private String generatePackageNo() {

        long packNo = idWorker.nextId();
        long obtainingTime = SnowflakeIdWorker3rd.obtainingTime();

        return (obtainingTime) + Long.toString(packNo).substring(2);

    }


    private void validateOrdersExists(Long orderId, Long packId) {

        OrderDO orderDO = ordersMapper.selectById(orderId);
        AssertUtils.notEmpty(orderDO,ORDER_PACK_ERROR);

        if(packId != null){
            OrderPackageDO orderPackageDO = orderPackageMapper.selectById(packId);
            AssertUtils.notEmpty(orderPackageDO,ORDER_PACK_DATA_ERROR);
        }

    }

    // 类型转换
    private OrderPackRespVO typeConversion(OrderPackageDO orderPackageDO) {
        return OrderPackRespVO.builder()
                .id(orderPackageDO.getId())
                .orderId(orderPackageDO.getOrderId())
                .organId(orderPackageDO.getOrganId())
                .packageNo(orderPackageDO.getPackageNo())
                .packageType(orderPackageDO.getType())
                .name(orderPackageDO.getName())
                .status(orderPackageDO.getStatus())
                .remark(orderPackageDO.getRemark())
                .build();

    }



    // 打包翻页查询
    private PageResult<PackRespVO> handleIsUpCase(PackPageReqVO pageReqVO, List<Long> orderIds,Boolean isUp) {

        IPage<PackRespVO> packRespVOS = new PageDTO<>();

        OrderDO order = ordersMapper.selectById(pageReqVO.getOrderId());
        AssertUtils.notEmpty(order, ORDER_DATE_ERROR);

        List<PackRespVO> packRespVOList = Boolean.TRUE.equals(isUp) ?
                ordersMapper.selectOrderIdsTrue(order.getCreateTime().toString(), getUserOrganId(), order.getId()) :
                ordersMapper.selectOrderIdsFalse(order.getCreateTime().toString(), getUserOrganId(), order.getId());

        if (packRespVOList.isEmpty()) {
            throw exception(NO_PRODUCTION_ORDER_INFORMATION_AVAILABLE, Boolean.TRUE.equals(isUp) ? "第" : "最后");
        }
        packRespVOS.setRecords(packRespVOList);

        packRespVOS.setTotal(1);

        orderIds.addAll(packRespVOS.getRecords().stream().map(PackRespVO::getId).toList());

        return buildPageResult(orderIds,packRespVOS);
    }



    // 打包分页查询
    private PageResult<PackRespVO> handleNormalCase(PackPageReqVO pageReqVO, List<Long> orderIds, PageDTO<PackRespVO> page) {

        pageReqVO.setCustomer(insertSeparator(pageReqVO.getCustomer()));
        pageReqVO.setCustomOrderNo(insertSeparator(pageReqVO.getCustomOrderNo()));
        pageReqVO.setAddress(insertSeparator(pageReqVO.getAddress()));


        // 查询查询分页
        IPage<PackRespVO> packRespVOS = ordersMapper.selectOrderIdList(page, pageReqVO, getUserOrganId());

        if (CollUtil.isEmpty(packRespVOS.getRecords())) {
            return new PageResult<>();
        }

        orderIds.addAll(packRespVOS.getRecords().stream().map(PackRespVO::getId).toList());

        return buildPageResult(orderIds, packRespVOS);

    }



    // 打包分页页面显示数据查询
    private PageResult<PackRespVO> buildPageResult(List<Long> orderIds,IPage<PackRespVO> packRespVOS){

        if(orderIds.isEmpty()){
            return new PageResult<>();
        }


        // 查询板材的总量
        List<PackRespVO> packRespVOList = orderPlateMapper.selectPackPlateNum(orderIds, getUserOrganId());

        AssertUtils.notEmpty(packRespVOList, ErrorCodeConstants.ORDER_PLATE_ERROR);

        for (PackRespVO packRespVO : packRespVOList) {
            packRespVO.setTotalPieceCount((long) packRespVO.getPlateIdList().size());
            packRespVO.setPlateIdList(null);
        }


        // 查询当前生产的包裹数量
        List<PackRespVO> respVOS = orderPackageMapper.selectPackPage(orderIds, getUserOrganId());


        for (PackRespVO packRespVO : respVOS) {
            packRespVO.setPackCount((long) packRespVO.getPackIdList().size());
            packRespVO.setPackIdList(null);
        }


        // 查询当前生产单已经打包的板材数量
        List<PackRespVO> plateNum = orderPackageMapper.selectPackPieceCount(orderIds, getUserOrganId());

        for (PackRespVO packRespVO : plateNum) {
            packRespVO.setPackPieceCount((long) packRespVO.getPlateIdList().size());
            packRespVO.setPlateIdList(null);
        }


        for (PackRespVO vosRecords : packRespVOS.getRecords()) {

            // 板材总数
            vosRecords.setTotalPieceCount(packRespVOList.stream().filter(f -> Objects.equals(f.getId(), vosRecords.getId())).mapToLong(PackRespVO::getTotalPieceCount).sum());
            // 已打包数
            vosRecords.setPackCount(respVOS.stream().filter(f -> Objects.equals(f.getId(), vosRecords.getId())).mapToLong(PackRespVO::getPackCount).sum());
            // 已打包片数
            vosRecords.setPackPieceCount(plateNum.stream().filter(f -> Objects.equals(f.getId(), vosRecords.getId())).mapToLong(PackRespVO::getPackPieceCount).sum());
            // 待处理量
            vosRecords.setPendingNum(vosRecords.getTotalPieceCount() - vosRecords.getPackPieceCount());

        }


        return new PageResult<>(packRespVOS.getRecords(), packRespVOS.getTotal());

    }


}
