package com.jwipc.order.logic.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.jwipc.aggregation.ModelAggregationService;
import com.jwipc.constant.DelFlag;
import com.jwipc.constant.DictCode;
import com.jwipc.constant.FlagConst;
import com.jwipc.exception.DaoException;
import com.jwipc.order.constant.DeliveryStatus;
import com.jwipc.order.constant.PoSapClient;
import com.jwipc.order.convert.PurchaseOrderDetailComponentConvert;
import com.jwipc.order.convert.PurchaseOrderDetailConvert;
import com.jwipc.order.convert.PurchaseOrderDevPlanConvert;
import com.jwipc.order.dto.*;
import com.jwipc.order.entity.*;
import com.jwipc.order.logic.PurchaseOrderCountLogic;
import com.jwipc.order.logic.PurchaseOrderDetailLogic;
import com.jwipc.order.model.po.PurchaseOrderDetailPO;
import com.jwipc.order.model.query.PurchaseOrderDetailQuery;
import com.jwipc.order.model.query.PurchaseOrderDetailsQuery;
import com.jwipc.order.service.*;
import com.jwipc.page.PageUtil;
import com.jwipc.page.PageView;
import com.jwipc.prop.SysProp;
import com.jwipc.security.LoginUtil;
import com.jwipc.supplier.clent.dto.SupplierDTO;
import com.jwipc.supplier.client.SupplierClient;
import com.jwipc.sys.client.ProductClient;
import com.jwipc.sys.client.ProductStockClient;
import com.jwipc.sys.client.UserPurchaseGroupClient;
import com.jwipc.sys.client.dto.ProductInfoDTO;
import com.jwipc.util.EasyExcelImportUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.baomidou.dynamic.datasource.support.DdConstants.SLAVE;


/**
 * <p> </p>
 *
 * @author BOGON
 * @version 1.0
 * @since JDK 1.8
 */
@Service
@RequiredArgsConstructor
@DS(SLAVE)
@Slf4j
public class PurchaseOrderDetailLogicImpl implements PurchaseOrderDetailLogic {
    private final IPurchaseOrderDetailService purchaseOrderDetailService;
    private final IPurchaseOrderService purchaseOrderService;
    private final PurchaseOrderDetailConvert purchaseOrderDetailConvert;
    private final ModelAggregationService modelAggregationService;
    private final IPurchaseOrderDevPlanService purchaseOrderDevPlanService;
    private final IPurchaseOrderDetailCostService purchaseOrderDetailCostService;
    private final PurchaseOrderDevPlanConvert purchaseOrderDevPlanConvert;
    private final PoSapClient sapClient;
    private final IPurchaseOrderDetailComponentService purchaseOrderDetailComponentService;
    private final PurchaseOrderDetailComponentConvert purchaseOrderDetailComponentConvert;
    private final PurchaseOrderCountLogic purchaseOrderCountLogic;
    private final SupplierClient supplierClient;
    private final IDeliveryOrderDetailService deliveryOrderDetailService;
    private final UserPurchaseGroupClient userPurchaseGroupClient;
    private final SysProp sysProp;
    private final ProductClient productClient;
    private final ProductStockClient productStockClient;
    private final IPurchaseOrderDetailUnlockLogService purchaseOrderDetailUnlockLogService;


    @Override
    public PageView getList(PurchaseOrderDetailQuery query) {
        final Page<PurchaseOrderDetailPO> page = PageUtil.toPage(query);
        if (LoginUtil.isSupplier()) {
            query.setLoginSupplierCode(LoginUtil.getSupplierCode());
            query.setSupplierVisible(FlagConst.Y.getCode());
        } else {
            final Set<String> userPurchaseGroupCode = userPurchaseGroupClient.getUserPurchaseGroupCode(
                    LoginUtil.getUserId());
            query.setUserPurchaseGroupCodes(userPurchaseGroupCode);
        }
        List<PurchaseOrderDetailPO> list = purchaseOrderDetailService.findList(page, query);
        List<PurchaseOrderDetailListDTO> listDTOS = purchaseOrderDetailConvert.pos2Dtos(list);
        Map<String, String> materiaNameMap = new HashMap<>();
        //设置最新的物料名称，如果物料名称有变化，则取最新的物料名称， 2024-08-07 邓京术
        for (PurchaseOrderDetailListDTO listDTO : listDTOS) {
            initMaterialName(listDTO, materiaNameMap);
        }
        Collections.sort(listDTOS, new PurchaseOrderDetailListDTOComparator());
        return PageUtil.getPV(listDTOS, Objects.isNull(page) ? listDTOS.size() : page.getTotal());
    }

    @Override
    public PageView details(PurchaseOrderDetailsQuery query) {
        final Page<PurchaseOrderDetailPO> page = PageUtil.toPage(query);
        if (LoginUtil.isSupplier()) {
            query.setLoginSupplierCode(LoginUtil.getSupplierCode());
            query.setSupplierVisible(FlagConst.Y.getCode());
        } else {
            final Set<String> userPurchaseGroupCode = userPurchaseGroupClient.getUserPurchaseGroupCode(
                    LoginUtil.getUserId());
            query.setUserPurchaseGroupCodes(userPurchaseGroupCode);
        }
        List<PurchaseOrderDetailPO> list = purchaseOrderDetailService.findDetails(page, query);
        List<PurchaseOrderDetailListDTO> listDTOS = purchaseOrderDetailConvert.pos2Dtos(list);
        Map<String, String> materiaNameMap = new HashMap<>();
        //设置最新的物料名称，如果物料名称有变化，则取最新的物料名称， 2024-08-07 邓京术
        for (PurchaseOrderDetailListDTO listDTO : listDTOS) {
            initMaterialName(listDTO, materiaNameMap);
        }
        Collections.sort(listDTOS, new PurchaseOrderDetailListDTOComparator());
        return PageUtil.getPV(listDTOS, Objects.isNull(page) ? listDTOS.size() : page.getTotal());
    }

    private void initMaterialName(PurchaseOrderDetailListDTO listDTO, Map<String, String> materiaNameMap) {
        if (materiaNameMap.keySet().contains(listDTO.getMaterialCode())) {
            listDTO.setMaterialName(materiaNameMap.get(listDTO.getMaterialCode()));
        } else {
            ProductInfoDTO productInfoDTO = productClient.getByMaterialCodeAndFactoryCode(listDTO.getMaterialCode(),
                    listDTO.getFactoryCode());
            if (Objects.nonNull(productInfoDTO)) {
                materiaNameMap.put(listDTO.getMaterialCode(), productInfoDTO.getMaterialName());
                listDTO.setMaterialName(productInfoDTO.getMaterialName());
            }
        }
    }

    class PurchaseOrderDetailListDTOComparator implements Comparator<PurchaseOrderDetailListDTO> {
        @Override
        public int compare(PurchaseOrderDetailListDTO o1, PurchaseOrderDetailListDTO o2) {
            return Integer.parseInt(o1.getOrderRow()) - Integer.parseInt(o2.getOrderRow());
        }
    }

    @Override
    public List<PurchaseOrderDetailListDTO> listAll(PurchaseOrderDetailQuery query) {
        if (LoginUtil.isSupplier()) {
            query.setLoginSupplierCode(LoginUtil.getSupplierCode());
            query.setSupplierVisible(FlagConst.Y.getCode());
        } else {
            final Set<String> userPurchaseGroupCode = userPurchaseGroupClient.getUserPurchaseGroupCode(
                    LoginUtil.getUserId());
            query.setUserPurchaseGroupCodes(userPurchaseGroupCode);
        }
        //需要查询一下总数
        query.setRows(1);
        query.setPage(1);
        final Page<PurchaseOrderDetailPO> page = PageUtil.toPage(query);
        purchaseOrderDetailService.findList(page, query);
        final long total = page.getTotal();
        if (total > sysProp.getExportMaxCount()) {
            throw new DaoException(StrUtil.format("导出数据超过{}条", sysProp.getExportMaxCount()));
        }
        List<PurchaseOrderDetailPO> list = purchaseOrderDetailService.findList(query);
        return purchaseOrderDetailConvert.pos2Dtos(list);
    }

    public Pair<List<PurchaseOrderDetailListDTO>, Long> getListForDeliveryCreate(PurchaseOrderDetailQuery query) {
        return this.getListForDeliveryCreate(query, false);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Pair<List<PurchaseOrderDetailListDTO>, Long> getListForDeliveryCreate(PurchaseOrderDetailQuery query,
                                                                                 boolean exportFlag)
    {
        Map<String, String> materiaNameMap = new HashMap<>();
        boolean isSupplier = LoginUtil.isSupplier();
        if (isSupplier) {
            query.setLoginSupplierCode(LoginUtil.getSupplierCode());
            //2025-06-26判断是否是物流供应商查询创建送货单订单明细
            List<String> LogisticSuplier = Stream.of("1001", "1001E", "5012","5012E").collect(Collectors.toList());
            if(LogisticSuplier.contains(LoginUtil.getSupplierCode())){
                query.setSupplierCode1(LoginUtil.getSupplierCode());
            }
            //判断当前的供应商是否有角色编码
            final List<String> roleCodes = LoginUtil.getRoleCodes();
            //判断是否存在特殊角色 special 如果存在并且没有输入查询条件就返回空数据
            if (roleCodes.contains(DictCode.SUPPLIER_SPECIAL_ROLE)) {
                final Map<String, Object> map = BeanUtil.beanToMap(query, false, false);
                Set<String> keySet = Sets.newHashSet();
//                keySet.add("orderCode");
//                keySet.add("orderTypeCode");
                keySet.add("material");
//                keySet.add("startCreateDate");
//                keySet.add("endCreateDate");
//                keySet.add("factoryCode");
//                keySet.add("devCount");
//                keySet.add("createName");
                boolean isOk = keySet.stream().allMatch(key -> {
                    if (Objects.nonNull(map.get(key))) {
                        if (Strings.isNullOrEmpty(map.get(key).toString())) {
                            return true;
                        } else {
                            return false;
                        }
                    } else {
                        return true;
                    }
                });
                if (isOk) {
                    return Pair.of(Collections.emptyList(), 0L);
                }
            }
            query.setSupplierVisible(FlagConst.Y.getCode());
        } else {
            final Set<String> userPurchaseGroupCode = userPurchaseGroupClient.getUserPurchaseGroupCode(
                    LoginUtil.getUserId());
            query.setUserPurchaseGroupCodes(userPurchaseGroupCode);
        }
        query.setForCreateDelivery(FlagConst.Y.getCode());
        //未清数量 不等于0的不查询出来， 2024-08-28 邓京术
        query.setNoClearNum("0");
        //获取条件如果是 query.devCount =1 或者0需要进行全量刷新
        if (Objects.equals(query.getDevCount(), "1") || Objects.equals(query.getDevCount(), "0")) {
            List<PurchaseOrderDetailPO> list = purchaseOrderDetailService.findList(query);
            List<AppointmentQuantitySapDTO.Item> result = Lists.newArrayList();
            Set<String> cache = Sets.newHashSet();
            for (PurchaseOrderDetailPO listDTO : list) {
                if (!cache.contains(listDTO.getMaterialCode() + listDTO.getFactoryCode())) {
                    cache.add(listDTO.getMaterialCode() + listDTO.getFactoryCode());
                    final AppointmentQuantitySapDTO.Item item = new AppointmentQuantitySapDTO.Item();
                    item.setMATNR(listDTO.getMaterialCode());
                    item.setWERKS(listDTO.getFactoryCode());
                    result.add(item);
                }
            }
            // 分批处理项目，每批100个
            int batchSize = 100;
            for (int i = 0; i < result.size(); i += batchSize) {
                int end = Math.min(i + batchSize, result.size());
                List<AppointmentQuantitySapDTO.Item> batch = result.subList(i, end);
                // 处理当前批次
                purchaseOrderCountLogic.allocateOrderQuantity(batch);
            }
            final Page<PurchaseOrderDetailPO> page = PageUtil.toPage(query);
            query.setDevCount1(Integer.parseInt(query.getDevCount()));
            if (exportFlag) {
                Long total = purchaseOrderDetailService.findCountForPage(query);
                if (exportFlag && total > sysProp.getExportMaxCount()) {
                    throw new DaoException(StrUtil.format("导出数据超过{}条", sysProp.getExportMaxCount()));
                }
            }
            List<PurchaseOrderDetailPO> pageLists;
            if (Objects.nonNull(page)) {
                page.setSearchCount(false);
                long total = purchaseOrderDetailService.findCountForPage(query);
                pageLists = purchaseOrderDetailService.findList(page, query);
                //需要单独查询分页总数
                page.setTotal(total);
            } else {
                pageLists = purchaseOrderDetailService.findList(query);
            }
            List<PurchaseOrderDetailListDTO> listDTOS = purchaseOrderDetailConvert.pos2Dtos(pageLists);
            for (PurchaseOrderDetailListDTO listDTO : listDTOS) {
                //送货数量设置，如果有解锁，unlockFlag = 1,则送货数量=解锁数量
                if (Objects.nonNull(listDTO.getUnlockFlag()) &&
                        listDTO.getUnlockFlag().equals(FlagConst.Y.getCode())) {
                    listDTO.setDeliveryNum(listDTO.getUnlockNum());
                //A-订单交货 B-计划交货 对于订单交货的订单，送货数量=未清数量-在途送货数量
                } else if (listDTO.getMarkFlag().equals("A")) {
                    listDTO.setDeliveryNum(
                            listDTO.getNoClearNum().subtract(listDTO.getOnlineNum()));
                } else {//否则送货数量=可送数量
                    listDTO.setDeliveryNum(listDTO.getEnableNum());
                }

                //设置最新的物料名称，如果物料名称有变化，则取最新的物料名称， 2024-08-07 邓京术
                initMaterialName(listDTO, materiaNameMap);

                //如果是供应商登录需要清除解锁备注的内容
                if (isSupplier) {
                    listDTO.setUnlockRemark(StrUtil.EMPTY);
                }
            }

            return Pair.of(listDTOS, Objects.isNull(page) ? listDTOS.size() : page.getTotal());
        } else {
            final Page<PurchaseOrderDetailPO> page = PageUtil.toPage(query);
            List<PurchaseOrderDetailListDTO> listDTOS;
            //需要单独查询分页总数
            Long count = purchaseOrderDetailService.findCountForPage(query);
            if (exportFlag && count > sysProp.getExportMaxCount()) {
                throw new DaoException(StrUtil.format("导出数据超过{}条", sysProp.getExportMaxCount()));
            }
            if (Objects.nonNull(page)) {
                page.setSearchCount(false);
                List<PurchaseOrderDetailPO> list = purchaseOrderDetailService.findList(page, query);
                listDTOS = purchaseOrderDetailConvert.pos2Dtos(list);
                page.setTotal(count);
            } else {
                List<PurchaseOrderDetailPO> list = purchaseOrderDetailService.findList(query);
                listDTOS = purchaseOrderDetailConvert.pos2Dtos(list);
            }
            //这个地方需要取sap的送货数量
            List<AppointmentQuantitySapDTO.Item> result = Lists.newArrayList();
            Set<String> cache = Sets.newHashSet();
            for (PurchaseOrderDetailListDTO listDTO : listDTOS) {
                if (!cache.contains(listDTO.getMaterialCode() + listDTO.getFactoryCode())) {
                    cache.add(listDTO.getMaterialCode() + listDTO.getFactoryCode());
                    final AppointmentQuantitySapDTO.Item item = new AppointmentQuantitySapDTO.Item();
                    item.setMATNR(listDTO.getMaterialCode());
                    item.setWERKS(listDTO.getFactoryCode());
                    result.add(item);
                }
            }
            final Map<Long, BigDecimal> longBigDecimalMap = purchaseOrderCountLogic.allocateOrderQuantity(result);
            for (PurchaseOrderDetailListDTO listDTO : listDTOS) {
                final BigDecimal s = longBigDecimalMap.get(listDTO.getId());
                if (Objects.nonNull(s)) {
                    listDTO.setEnableNum(s);
                }
                //送货数量设置 如果已经解锁 unlockFlag = 1 则送货数量=解锁数量，
                if (Objects.nonNull(listDTO.getUnlockFlag()) &&
                        listDTO.getUnlockFlag().equals(FlagConst.Y.getCode())) {
                    listDTO.setDeliveryNum(listDTO.getUnlockNum());
                //如果是//A-订单交货 则送货数量=未清数量-在途送货单  //B-计划交货
                } else if (listDTO.getMarkFlag().equals("A")) {
//                    listDTO.setEnableNum(
//                            listDTO.getNoClearNum().subtract(listDTO.getOnlineNum()));
                    listDTO.setDeliveryNum(
                            listDTO.getNoClearNum().subtract(listDTO.getOnlineNum()));
                } else {
                    listDTO.setDeliveryNum(listDTO.getEnableNum());
                }

                //如果是供应商登录需要清除解锁备注的内容
                if (isSupplier) {
                    listDTO.setUnlockRemark(StrUtil.EMPTY);
                }
                //设置最新的物料名称，如果物料名称有变化，则取最新的物料名称， 2024-08-07 邓京术
                initMaterialName(listDTO, materiaNameMap);
            }

            return Pair.of(listDTOS, Objects.isNull(page) ? listDTOS.size() : page.getTotal());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<PurchaseOrderDetailListDTO> getListUnlockForDeliveryCreate(List<String> idList)
    {
        List<PurchaseOrderDetailPO> list = purchaseOrderDetailService.findListUnlockForDeliveryCreate(idList);
        List<PurchaseOrderDetailListDTO> listDTOS = purchaseOrderDetailConvert.pos2Dtos(list);
        //这个地方需要取sap的送货数量
        List<AppointmentQuantitySapDTO.Item> result = Lists.newArrayList();
        Set<String> cache = Sets.newHashSet();
        for (PurchaseOrderDetailListDTO listDTO : listDTOS) {
            if (!cache.contains(listDTO.getMaterialCode() + listDTO.getFactoryCode())) {
                cache.add(listDTO.getMaterialCode() + listDTO.getFactoryCode());
                final AppointmentQuantitySapDTO.Item item = new AppointmentQuantitySapDTO.Item();
                item.setMATNR(listDTO.getMaterialCode());
                item.setWERKS(listDTO.getFactoryCode());
                result.add(item);
            }
        }
        final Map<Long, BigDecimal> longBigDecimalMap = purchaseOrderCountLogic.allocateOrderQuantity(result);
        for (PurchaseOrderDetailListDTO listDTO : listDTOS) {
            final BigDecimal s = longBigDecimalMap.get(listDTO.getId());
            if (Objects.nonNull(s)) {
                listDTO.setEnableNum(s);
            }
        }
        //如果是供应商登录需要清除解锁备注的内容
        if (LoginUtil.isSupplier()) {
            for (PurchaseOrderDetailListDTO listDTO : listDTOS) {
                listDTO.setUnlockRemark(StrUtil.EMPTY);
            }
        }
        return listDTOS;
    }

    @Override
    public PurchaseOrderDetailLabelPrintDTO getInfoForLabelPrint(String orderCode, String materialCode) {
        final LambdaQueryWrapper<PurchaseOrder> eq = new LambdaQueryWrapper<PurchaseOrder>().eq(
                PurchaseOrder::getOrderCode, orderCode);
        if (LoginUtil.isSupplier()) {
            eq.eq(PurchaseOrder::getSupplierErpCode, LoginUtil.getSupplierCode());
        }
        final PurchaseOrder purchaseOrder = purchaseOrderService.getOne(eq);
        //特殊判断
        //KG5515-1000或者YP4415-1000

        if (orderCode.startsWith("KG") || orderCode.startsWith("YP")) {
            //KG5515-1000或者YP4415-1000我现在需要获取供应商编码和工厂编码
            final String[] split = orderCode.split("-");
            if (split.length == 2) {
                String supplierCode = split[0];
                //需要截取掉KG 或者YP
                supplierCode = supplierCode.substring(2);
                final String factory = split[1];
                final SupplierDTO supplierByCode = supplierClient.getSupplierByCode(supplierCode);
                if (Objects.isNull(supplierByCode)) {
                    throw new DaoException("供应商不存在");
                }
                final PurchaseOrderDetailLabelPrintDTO labelPrintDTO = new PurchaseOrderDetailLabelPrintDTO();
                labelPrintDTO.setSupplierId(supplierByCode.getId());
                labelPrintDTO.setSupplierCode(supplierByCode.getSupplierCode());
                labelPrintDTO.setFactoryCode(factory);
                modelAggregationService.processRelationAggregation(labelPrintDTO);
                if (StrUtil.isNotEmpty(materialCode)) {
                    final ProductInfoDTO byMaterialCodeAndFactoryCode = productClient.getByMaterialCodeAndFactoryCode(
                            materialCode, factory);
                    if (Objects.isNull(byMaterialCodeAndFactoryCode)) {
                        throw new DaoException("物料不存在");
                    }
                    labelPrintDTO.setUnit(byMaterialCodeAndFactoryCode.getOrderUnit());
                    labelPrintDTO.setDefaultStock(productStockClient.getStockLocation(materialCode));
                    return labelPrintDTO;
                }
                return labelPrintDTO;
            } else {
                throw new DaoException("采购订单不存在");
            }
        }
        //特殊判断
        if (Objects.isNull(purchaseOrder)) {
            throw new DaoException("采购订单不存在");
        }
        if (Strings.isNullOrEmpty(materialCode)) {
            final PurchaseOrderDetailLabelPrintDTO labelPrintDTO = new PurchaseOrderDetailLabelPrintDTO();
            labelPrintDTO.setSupplierId(purchaseOrder.getSupplierId());
            modelAggregationService.processRelationAggregation(labelPrintDTO);
            return labelPrintDTO;
        }
        final List<PurchaseOrderDetail> list = purchaseOrderDetailService.list(
                new LambdaUpdateWrapper<PurchaseOrderDetail>().eq(PurchaseOrderDetail::getOrderCode, orderCode)
                        .eq(PurchaseOrderDetail::getMaterialCode, materialCode));
        if (CollUtil.isEmpty(list)) {
            throw new DaoException("采购订单明细不存在");
        }
        final PurchaseOrderDetail one = list.get(0);
        final PurchaseOrderDetailLabelPrintDTO labelPrintDTO = purchaseOrderDetailConvert.entity2Dto1(one);
        labelPrintDTO.setSupplierId(purchaseOrder.getSupplierId());
        labelPrintDTO.setDefaultStock(productStockClient.getStockLocation(materialCode));
        modelAggregationService.processRelationAggregation(labelPrintDTO);
        return labelPrintDTO;
    }

    @Override
    public PageView getPlanList(String orderCode, String row) {
        List<PurchaseOrderDevPlan> devPlans = purchaseOrderDevPlanService.list(
                new LambdaQueryWrapper<PurchaseOrderDevPlan>().eq(PurchaseOrderDevPlan::getPurchaseOrder, orderCode)
                        .eq(PurchaseOrderDevPlan::getLineItem, row));
        List<PurchaseOrderDevPlanBaseDTO> list = purchaseOrderDevPlanConvert.entities2Dtos(devPlans);
        return PageUtil.getPV(list, list.size());
    }

    @Override
    @DS(SLAVE)
    public PageView getComponentList(String orderCode, String row, String planLine) {
        final PurchaseOrder purchaseOrder = purchaseOrderService.getOne(
                new LambdaQueryWrapper<PurchaseOrder>().eq(PurchaseOrder::getOrderCode, orderCode), false);
        //需要查询订单工厂
        final PurchaseOrderDetail orderDetail = purchaseOrderDetailService.getOne(
                new LambdaQueryWrapper<PurchaseOrderDetail>().eq(PurchaseOrderDetail::getOrderCode, orderCode)
                        .eq(PurchaseOrderDetail::getOrderRow, row), false);
        final String factoryCode = orderDetail.getFactoryCode();
        final List<PurchaseOrderDetailComponent> detailComponents = purchaseOrderDetailComponentService.list(
                new LambdaQueryWrapper<PurchaseOrderDetailComponent>().eq(
                                PurchaseOrderDetailComponent::getPurchaseOrder, orderCode)
                        .eq(PurchaseOrderDetailComponent::getLineItem, row)
                        .eq(PurchaseOrderDetailComponent::getPlanLine, planLine));
        List<PurchaseOrderDetailComponentListDTO> result = purchaseOrderDetailComponentConvert.entities2Dtos(
                detailComponents);
        final ComponentCountSapDTO.Item1 item1 = new ComponentCountSapDTO.Item1();
        item1.item = Lists.newArrayList();
        for (PurchaseOrderDetailComponentListDTO it : result) {
            final ComponentCountSapDTO.Item item = new ComponentCountSapDTO.Item();
            item.WERKS = factoryCode;
            item.MATNR = it.getComponentMaterialCode();
            item.LIFNR = purchaseOrder.getSupplierErpCode();
            item1.item.add(item);
        }
        ComponentCountSapDTO componentCountSapDTO = new ComponentCountSapDTO();
        componentCountSapDTO.setIT_HEAD(item1);
        Map<String, ComponentCountResposeDTO.Item2> cache = Maps.newHashMap();
        if (CollUtil.isNotEmpty(result)) {
            final ComponentCountResposeDTO componentCount = sapClient.getComponentCount(componentCountSapDTO);
            final ComponentCountResposeDTO.Item1 itItem = componentCount.getIT_ITEM();
            final List<ComponentCountResposeDTO.Item2> item = Objects.nonNull(
                    itItem) ? itItem.item : Lists.newArrayList();
            cache = item.stream()
                    .collect(Collectors.toMap(a -> a.MATNR, b -> b, (existing, replacement) -> existing));
        }


        for (PurchaseOrderDetailComponentListDTO dto : result) {
            final String componentMaterialCode = dto.getComponentMaterialCode();
            final ComponentCountResposeDTO.Item2 item2 = cache.get(componentMaterialCode);
            if (Objects.nonNull(item2)) {
                dto.setCount(item2.SLLAB);
                dto.setUnit(item2.MEINS);
            }
            //设置最新的物料名称，如果物料名称有变化，则取最新的物料名称， 2024-08-14 邓京术
            ProductInfoDTO productInfoDTO = productClient.getByMaterialCodeAndFactoryCode(componentMaterialCode,
                    factoryCode);
            if (Objects.nonNull(productInfoDTO)) {
                dto.setComponentMaterialName(productInfoDTO.getMaterialName());
            }

        }
        return PageUtil.getPV(result, result.size());
    }

    @Override
    public PageView getCostList(String orderCode, String row) {
        List<PurchaseOrderDetailCost> costList = purchaseOrderDetailCostService.list(
                new LambdaQueryWrapper<PurchaseOrderDetailCost>().eq(PurchaseOrderDetailCost::getPurchaseOrder,
                        orderCode).eq(PurchaseOrderDetailCost::getLineItem, row));
        return PageUtil.getPV(costList, costList.size());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void unlock(List<PurchaseOrderDetailUnlockDTO> unlockDTO) {
        final Set<Long> collect = unlockDTO.stream().map(PurchaseOrderDetailUnlockDTO::getId)
                .collect(Collectors.toSet());
        if (CollUtil.isEmpty(collect)) {
            return;
        }
        final List<PurchaseOrderDetail> purchaseOrderDetails1 = purchaseOrderDetailService.listByIds(collect);
        final Map<Long, BigDecimal> numCache = unlockDTO.stream().collect(
                Collectors.toMap(PurchaseOrderDetailUnlockDTO::getId, PurchaseOrderDetailUnlockDTO::getUnlockNum));
        final Map<Long, String> remarkache = unlockDTO.stream().filter(a -> StrUtil.isNotEmpty(a.getUnlockRemark()))
                .collect(
                        Collectors.toMap(PurchaseOrderDetailUnlockDTO::getId,
                                PurchaseOrderDetailUnlockDTO::getUnlockRemark));
        Set<String> msg = Sets.newHashSet();
        List<PurchaseOrderDetail> updateLists = Lists.newArrayList();
        final LocalDate now = LocalDate.now();
        Set<Long> restUnlockIds = Sets.newHashSet();
        List<PurchaseOrderDetailUnlockLog> logList = new ArrayList<>();
        for (PurchaseOrderDetail purchaseOrderDetail : purchaseOrderDetails1) {
            final BigDecimal noClearNum = purchaseOrderDetail.getNoClearNum();
            //查询在途
            final String orderCode = purchaseOrderDetail.getOrderCode();
            final String orderRow = purchaseOrderDetail.getOrderRow();
            final BigDecimal onLineNum = deliveryOrderDetailService.findCountByPurchaseDetail(orderCode, orderRow,
                    DeliveryStatus.SHIPPED.getStatus(), DelFlag.NORMAL.getStatus());
            final BigDecimal enableNum = noClearNum.subtract(onLineNum);
            final BigDecimal unlockNum = numCache.get(purchaseOrderDetail.getId());
            if (unlockNum.compareTo(enableNum) > 0) {
                msg.add(StrUtil.format("{}-{}", orderCode, orderRow));
                continue;
            }
            final String unlockRemark = remarkache.get(purchaseOrderDetail.getId());
            final PurchaseOrderDetail tmp = new PurchaseOrderDetail();
            tmp.setId(purchaseOrderDetail.getId());
            //判断解锁数量是否为0
            if (unlockNum.compareTo(BigDecimal.ZERO) == 0) {
                restUnlockIds.add(purchaseOrderDetail.getId());
            } else {
                tmp.setUnlockNum(unlockNum);
                tmp.setUnlockRemark(StrUtil.isNotEmpty(unlockRemark) ? unlockRemark : StrUtil.EMPTY);
                tmp.setUnlockDate(now);
                tmp.setUnlockFlag(FlagConst.Y.getCode());
                updateLists.add(tmp);
                //20240925 增加每次保存解锁数据日志逻辑
                PurchaseOrderDetailUnlockLog log = new PurchaseOrderDetailUnlockLog();
                log.setUnlockNum(unlockNum);
                log.setUnlockRemark(StrUtil.isNotEmpty(unlockRemark) ? unlockRemark : StrUtil.EMPTY);
                log.setUnlockDate(now);
                log.setUnlockFlag(true);
                log.setOnlineNum(onLineNum.doubleValue());
                setPurchaseOrderDetailUnlockLogValue(purchaseOrderDetail,log);
                //unlockLog.setPurchaseGroupCode();
                //unlockLog.setSupplierName();
                logList.add(log);
            }
        }
        if (CollUtil.isNotEmpty(msg)) {
            throw new DaoException(msg.stream().collect(Collectors.joining("</br>")) + "数量不够无法解锁");
        }
        if (CollUtil.isNotEmpty(updateLists)) {
            purchaseOrderDetailService.updateBatchById(updateLists);
        }
        if (CollUtil.isNotEmpty(logList)) {
            //新增加一张解锁日志表
            purchaseOrderDetailUnlockLogService.saveBatch(logList);

        }
        if (CollUtil.isNotEmpty(restUnlockIds)) {
            final LambdaUpdateWrapper<PurchaseOrderDetail> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.in(PurchaseOrderDetail::getId, restUnlockIds).
                    set(PurchaseOrderDetail::getUnlockNum, null)
                    .set(PurchaseOrderDetail::getUnlockFlag, null)
                    .set(PurchaseOrderDetail::getUnlockDate, null)
                    .set(PurchaseOrderDetail::getUnlockRemark, null);
            purchaseOrderDetailService.update(updateWrapper);
        }
    }

    private void setPurchaseOrderDetailUnlockLogValue(PurchaseOrderDetail purchaseOrderDetail,PurchaseOrderDetailUnlockLog unlockLog){
        unlockLog.setOrderId(purchaseOrderDetail.getOrderId());
        unlockLog.setOrderCode(purchaseOrderDetail.getOrderCode());
        unlockLog.setOrderRow(purchaseOrderDetail.getOrderRow());
        unlockLog.setMaterialCode(purchaseOrderDetail.getMaterialCode());
        unlockLog.setMaterialName(purchaseOrderDetail.getMaterialName());
        unlockLog.setUnitCode(purchaseOrderDetail.getUnitCode());
        unlockLog.setUnitName(purchaseOrderDetail.getUnitName());
        unlockLog.setNum(purchaseOrderDetail.getNum());
        unlockLog.setFactoryName(purchaseOrderDetail.getFactoryName());
        unlockLog.setDelFlag(purchaseOrderDetail.getDelFlag());
        unlockLog.setCreateName(purchaseOrderDetail.getCreateName());
        unlockLog.setCreateTime(purchaseOrderDetail.getCreateTime());
        unlockLog.setRemark(purchaseOrderDetail.getRemark());
        unlockLog.setSupplierErpCode(purchaseOrderDetail.getSupplierErpCode());
        unlockLog.setNoClearNum(purchaseOrderDetail.getNoClearNum().doubleValue());
        unlockLog.setOperator(LoginUtil.getUserId().toString());
        unlockLog.setOperationTime(LocalDateTime.now());
        unlockLog.setRowTypeCode(purchaseOrderDetail.getRowTypeCode());
        unlockLog.setReceivedNum(purchaseOrderDetail.getReceivedNum());
    }


    @Override
    public void importUnlock(MultipartFile file) throws IOException {
        List<Map<String, String>> dataList = EasyExcelImportUtils.parseExcelToData(file.getInputStream(), 2);
        List<PurchaseOrderDetailUnlockDTO> purchaseOrderDetailUnlockDTOS = Lists.newArrayList();
        for (Map<String, String> stringStringMap : dataList) {
            final String id = stringStringMap.get("id");
            final String orderCode = stringStringMap.get("orderCode");
            final String orderRow = stringStringMap.get("orderRow");
            final String unlockNum = stringStringMap.get("unlockNum");
            final String unlockRemark = stringStringMap.get("unlockRemark");
            if(StringUtils.isEmpty(unlockNum) || "0".equals(unlockNum)){
                throw new DaoException("订单号："+orderCode +"，行号："+orderRow+"的解锁数量为空或者等于0，如不需要解锁请将该行删除");
            }
            if (StringUtils.isEmpty(unlockRemark)) {
                throw new DaoException("订单号："+orderCode +"，行号："+orderRow+"的解锁备注没有填写!");
            }
            //需要解锁数据
            log.info("id:{},orderCode:{},orderRow:{}:{},unlockNum:{}", id, orderCode, orderRow,
                    unlockNum);
            PurchaseOrderDetailUnlockDTO purchaseOrderDetailUnlockDTO = new PurchaseOrderDetailUnlockDTO();
            purchaseOrderDetailUnlockDTO.setId(Long.valueOf(id));
            purchaseOrderDetailUnlockDTO.setUnlockNum(new BigDecimal(unlockNum));
            purchaseOrderDetailUnlockDTO.setUnlockRemark(
                    StrUtil.isNotEmpty(unlockRemark) ? unlockRemark : StrUtil.EMPTY);
            purchaseOrderDetailUnlockDTOS.add(purchaseOrderDetailUnlockDTO);
        }
        if (CollUtil.isEmpty(purchaseOrderDetailUnlockDTOS)) {
            throw new DaoException("没有需要解锁的数据");
        }
        this.unlock(purchaseOrderDetailUnlockDTOS);
    }
}