package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.busi;

import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesPartShippingGroupService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.platform.common.tool.TimeTool;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.ResourceEnumUtil;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.base.util.StringUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesConfig;
import cn.estsh.i3plus.pojo.mes.bean.MesCustomerPart;
import cn.estsh.i3plus.pojo.mes.bean.MesPartShippingGroup;
import cn.estsh.i3plus.pojo.mes.bean.MesPartShippingGroupDetail;
import cn.estsh.i3plus.pojo.mes.bean.edi.wuhu.MesCimCheryOrder;
import cn.estsh.i3plus.pojo.mes.bean.shipping.MesShippingOrderManagement;
import cn.estsh.i3plus.pojo.mes.bean.shipping.MesShippingOrderManagementDetail;
import cn.estsh.i3plus.pojo.mes.model.MesShippingOrderManagementDetailModel;
import cn.estsh.i3plus.pojo.mes.model.MesShippingOrderManagementDetailModelForLiJia;
import cn.estsh.i3plus.pojo.mes.model.MesShippingOrderManagementModel;
import cn.estsh.i3plus.pojo.mes.model.MesShippingOrderManagementModelForLiJia;
import cn.estsh.i3plus.pojo.mes.repository.*;
import cn.estsh.impp.framework.boot.util.ResultBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.function.Function;
import java.util.logging.Handler;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Service
@Slf4j
public class MesPartShippingGroupService implements IMesPartShippingGroupService {


    @Autowired
    private MesPartShippingGroupRepository shippingGroupRepository;

    @Autowired
    private MesShippingOrderManagementRepository shippingOrderManagementRepository;

    @Autowired
    private MesShippingOrderManagementDetailRepository shippingOrderManagementDetailRepository;

    @Autowired
    private MesPartShippingGroupDetailRepository mesPartShippingGroupDetailRepository;

    @Autowired
    private MesCimCheryOrderRepository cheryOrderRao;

    @Autowired
    private MesConfigRepository mesConfigRao;

    public List<MesPartShippingGroup> findAll(MesPartShippingGroup partShippingGroup) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(partShippingGroup.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(partShippingGroup.getShippingGroupCode(), MesPcnExtConstWords.SHIPPING_GROUP_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(partShippingGroup.getShippingGroupName(), MesPcnExtConstWords.SHIPPING_GROUP_NAME, packBean);
        return shippingGroupRepository.findByHqlWhere(packBean);
    }

    @Override
    public MesPartShippingGroup getMesPartShippingGroup(String organizeCode, String shippingGroupCode) {
        if(StringUtil.isEmpty(organizeCode) || StringUtil.isEmpty(shippingGroupCode)) return null;
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(shippingGroupCode, MesPcnExtConstWords.SHIPPING_GROUP_CODE, packBean);
        return shippingGroupRepository.getByProperty(packBean);
    }

    @Override
    public ResultBean doMesMesShippingOrderManagementPrint(MesShippingOrderManagement bean) {
        DdlPackBean configPackBean = DdlPackBean.getDdlPackBean(bean.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack("WU_HU_SUPPLIER","cfgKey", configPackBean);
        List<MesConfig> configList = mesConfigRao.findByHqlWhere(configPackBean);
        String supplierNo = "";
        if (configList != null && !configList.isEmpty()) {
            supplierNo = configList.get(0).getCfgValue();
        }
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(bean.getOrganizeCode());
        //多选
        if (!StringUtil.isEmpty(bean.getShippingGroupCode())) {
            DdlPreparedPack.getInPackList(Arrays.asList(bean.getShippingGroupCode().split(",")), "shippingGroupCode", packBean);
        }
        DdlPreparedPack.getStringEqualPack(bean.getShippingCode(), "shippingCode", packBean);
        DdlPreparedPack.getIsNull("lastPrintTime", packBean);
        DdlPreparedPack.getOrderByPack(new Object[]{CommonEnumUtil.ASC_OR_DESC.ASC.getValue()}, new String[]{"createDatetime"}, packBean);
        List<MesShippingOrderManagement> pullingOrderInfos = shippingOrderManagementRepository.findByHqlTopWhere(packBean,10);
        log.info("doMesMesShippingOrderManagementPrint-pullingOrderInfos" + pullingOrderInfos.size());
        if (!CollectionUtils.isEmpty(pullingOrderInfos)) {
            //45527 礼嘉福特发运单打印（通过系统参数信息判断是否采用新的查询取值逻辑-礼嘉福特）
            DdlPackBean configPackBeanTwo = DdlPackBean.getDdlPackBean(bean.getOrganizeCode());
            DdlPreparedPack.getStringEqualPack("SORT_SHIPMENT_PRINTS_FLAG_FOR_LI_JIA","cfgKey", configPackBeanTwo);
            MesConfig liJiaConfig = mesConfigRao.getByProperty(configPackBeanTwo);
            log.info("doMesMesShippingOrderManagementPrint-liJiaConfig" + liJiaConfig);
            if (Objects.isNull(liJiaConfig)) {
                log.info("doMesMesShippingOrderManagementPrint-老逻辑");
                //未维护该参数，则继续执行原有逻辑
                List<MesShippingOrderManagementModel> modelList = new ArrayList<>();
                //把查出来的发运单打印并修改打印状态为已打印-
                for (MesShippingOrderManagement shippingOrder : pullingOrderInfos) {
                    MesShippingOrderManagementModel model = new MesShippingOrderManagementModel();
                    String shippingCodePrefix = shippingOrder.getShippingCode().substring(0, shippingOrder.getShippingCode().length() - 3);
                    String shippingCodeSuffix = shippingOrder.getShippingCode().substring(shippingOrder.getShippingCode().length() - 3);
                    model.setShippingCode(shippingCodePrefix);
                    model.setShippingCodeAfter3(shippingCodeSuffix);
                    model.setShippingCodeWhole(shippingOrder.getShippingCode());

                    //查询原始报文
                    List<MesCimCheryOrder> cheryOrderList = getCheryOrder(shippingOrder.getOrganizeCode(), shippingOrder.getShippingCode());
                    Map<String, List<MesCimCheryOrder>> cheryOrderMap = new HashMap<>();
                    if (cheryOrderList != null && !cheryOrderList.isEmpty()) {
                        MesCimCheryOrder cheryOrder = cheryOrderList.get(0);
                        model.setPlantName(cheryOrder.getPlantName());
                        model.setPartkitName(cheryOrder.getPartkitName());
                        model.setDeliverySendSequence(cheryOrder.getDeliverySendSequence());
                        model.setReceiveDockName(cheryOrder.getReceiveDockNo()+"--"+cheryOrder.getReceiveDockName());
                        model.setLastRecRequireTime(cheryOrder.getLastRecRequireTime());
                        //根据cheryOrder的workshopNo获取对应的车间名称
                        String workshopName = getWorkshopName(cheryOrder.getOrganizeCode(), cheryOrder.getWorkshopNo());
                        model.setWorkShop(workshopName);
                        model.setCreateDateTime(cheryOrder.getCreateDatetime());
                        model.setPrintDateTime(TimeTool.getNowTime(true));
                        cheryOrderMap = cheryOrderList.stream().collect(Collectors.groupingBy(MesCimCheryOrder::getVin));
                    }

                    //查询发运单明细
                    DdlPackBean partPackBean = DdlPackBean.getDdlPackBean(shippingOrder.getOrganizeCode());
                    DdlPreparedPack.getNumEqualPack(shippingOrder.getId(), "pid", partPackBean);
                    DdlPreparedPack.getOrderBy("boxNum",CommonEnumUtil.ASC_OR_DESC.ASC.getValue(), partPackBean);
                    List<MesShippingOrderManagementDetail> shipOrderPartInfos = shippingOrderManagementDetailRepository.findByHqlWhere(partPackBean);
                    if (!CollectionUtils.isEmpty(shipOrderPartInfos)) {
                        List<MesShippingOrderManagementDetailModel> detailList = new ArrayList<>();
                        shipOrderPartInfos = shipOrderPartInfos.stream().sorted(Comparator.comparing(MesShippingOrderManagementDetail::getCustInfoSeq)).collect(Collectors.toList());
                        for (MesShippingOrderManagementDetail shipOrderPartInfo : shipOrderPartInfos) {
                            MesShippingOrderManagementDetailModel detailModel = new MesShippingOrderManagementDetailModel();
                            detailModel.setPartNo(shipOrderPartInfo.getPartNo());
                            detailModel.setPartName(shipOrderPartInfo.getPartName());
                            detailModel.setQty(shipOrderPartInfo.getPlanQty());
                            detailModel.setBoxNo(shipOrderPartInfo.getCustInfoSeq());
                            detailModel.setSupplierNo(supplierNo);
                            detailModel.setVin(shipOrderPartInfo.getVin().substring(shipOrderPartInfo.getVin().length()-8));
                            MesCimCheryOrder order = cheryOrderMap.get(shipOrderPartInfo.getVin()).get(0);
                            if (order != null) {
                                detailModel.setWholePartNo(order.getMaterialNo());
                            }
                            detailList.add(detailModel);
                        }
                        model.setShipOrderPartInfos(detailList);
                    }

                    //查询原有报文 根据shippingCode;
                    shippingOrder.setPrintCount(StringUtil.isEmpty(shippingOrder.getPrintCount())?1:shippingOrder.getPrintCount()+1);
                    shippingOrder.setLastPrintTime(TimeTool.getNowTime(true));
                    shippingOrder.setLastPrintUser(bean.getUserInfo());
                    ConvertBean.serviceModelUpdate(shippingOrder, bean.getUserInfo());
                    modelList.add(model);
                }
                shippingOrderManagementRepository.saveAll(pullingOrderInfos);
                return ResultBean.success("发运单打印成功")
                        .setCode(ResourceEnumUtil.MESSAGE.SUCCESS.getCode())
                        .setResultList(modelList);
            }else {
                log.info("doMesMesShippingOrderManagementPrint-新逻辑");
                //维护了该参数，则执行礼嘉的新逻辑
                List<MesShippingOrderManagementModelForLiJia> mainDataList = new ArrayList<>();
                /**
                 * 查询发运单明细信息
                 */
                List<Long> pidList = pullingOrderInfos.stream().map(MesShippingOrderManagement::getId).collect(Collectors.toList());
                DdlPackBean liJIaPackBean = DdlPackBean.getDdlPackBean(bean.getOrganizeCode());
                DdlPreparedPack.getInPackList(pidList, "pid", liJIaPackBean);
                List<MesShippingOrderManagementDetail> shippingOrderManagementDetailList =
                        shippingOrderManagementDetailRepository.findByHqlWhere(liJIaPackBean);
                log.info("doMesMesShippingOrderManagementPrint-查询发运单明细信息" + shippingOrderManagementDetailList.size());
                Map<Long, List<MesShippingOrderManagementDetail>> detailByPidMap = shippingOrderManagementDetailList
                        .stream().collect(Collectors.groupingBy(MesShippingOrderManagementDetail::getPid));
                log.info("doMesMesShippingOrderManagementPrint-查询发运单明细信息-detailByPidMap-" + detailByPidMap.size());
                //遍历处理每个发运单主表
                for (MesShippingOrderManagement pullingOrderInfo : pullingOrderInfos) {
                    //一张实体发运单包含三部分信息（顶部的通用数据、中部的第一份表格数据，底部的第二份表格数据）
                    //取出当前发运单的明细信息
                    List<MesShippingOrderManagementDetail> details = detailByPidMap.get(pullingOrderInfo.getId());
                    if (!CollectionUtils.isEmpty(details)) {
                        //将发运单明细按照 assyCode 分组
                        //assyCode 的个数 / 2 代表会生成实体发运单的份数（一个 assyCode 就是一个表格，一份实体表单上可以放两个表格）
                        Map<String, List<MesShippingOrderManagementDetail>> detailByAssyCodeMap =
                                details.stream().collect(Collectors.groupingBy(MesShippingOrderManagementDetail::getAssyCode));
                        //将assyCode按照logic_Seq进行排序（选取每个assyCode对应的那组数据中的logic_seq最小值，根据该值对assyCode进行排序）
                        List<String> assyCodeList = new ArrayList<>(detailByAssyCodeMap.keySet());
                        Map<Long, String> logicSeqAndAssyCodeMap = new HashMap<>();
                        for (String assyCode : assyCodeList) {
                            List<MesShippingOrderManagementDetail> detailList = detailByAssyCodeMap.get(assyCode);
                            Optional<MesShippingOrderManagementDetail> min =
                                    detailList.stream().min(Comparator.comparing(MesShippingOrderManagementDetail::getLogicSeq));
                            min.ifPresent(mesShippingOrderManagementDetail -> logicSeqAndAssyCodeMap.put(mesShippingOrderManagementDetail.getLogicSeq(), assyCode));
                        }
                        List<Long> collect = logicSeqAndAssyCodeMap.keySet().stream().sorted().collect(Collectors.toList());
                        List<String> newAssyCodeList = new ArrayList<>();
                        for (Long logicSeq : collect) {
                            newAssyCodeList.add(logicSeqAndAssyCodeMap.get(logicSeq));
                        }
                        //将 assyCode 两两分组
                        List<List<String>> physicalOrderList = IntStream.range(0, newAssyCodeList.size())
                                .filter(i -> i % 2 == 0)
                                .mapToObj(i -> newAssyCodeList.subList(i, Math.min(i + 2, newAssyCodeList.size())))
                                .collect(Collectors.toList());
                        for (List<String> list : physicalOrderList) {
                            //生成一张实体发运单
                            log.info("doMesMesShippingOrderManagementPrint-生成一张实体发运单-list-" + list);
                            mainDataList.add(createPhysicalOrder(pullingOrderInfo, list, detailByAssyCodeMap, details));
                        }
                    }
                    pullingOrderInfo.setPrintCount(StringUtil.isEmpty(pullingOrderInfo.getPrintCount())? 1 : pullingOrderInfo.getPrintCount()+1);
                    pullingOrderInfo.setLastPrintTime(TimeTool.getNowTime(true));
                    pullingOrderInfo.setLastPrintUser(bean.getUserInfo());
                    ConvertBean.serviceModelUpdate(pullingOrderInfo, bean.getUserInfo());
                    log.info("doMesMesShippingOrderManagementPrint-pullingOrderInfo更新");
                }
                shippingOrderManagementRepository.saveAll(pullingOrderInfos);
                log.info("doMesMesShippingOrderManagementPrint-结束");
                return ResultBean.success("发运单打印成功")
                        .setCode(ResourceEnumUtil.MESSAGE.SUCCESS.getCode())
                        .setResultList(mainDataList);
            }
        }
        return ResultBean.success("不存在需要打印的发运单")
                .setCode(ResourceEnumUtil.MESSAGE.SUCCESS.getCode());
    }

    private String getWorkshopName(String organizeCode, String workshopNo) {

        DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(workshopNo, "cfgKey", ddlPackBean);
        List<MesConfig> configList = mesConfigRao.findByHqlWhere(ddlPackBean);
        return configList.isEmpty() ? "" : configList.get(0).getCfgValue();

    }
    private List<MesCimCheryOrder> getCheryOrder(String organizeCode, String sheetNo) {
        DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(sheetNo, "sheetNo", ddlPackBean);
        return cheryOrderRao.findByHqlWhere(ddlPackBean);
    }
    @Override
    public MesPartShippingGroupDetail getMesPartShippingGroupDetail(String organizeCode, String shippingGroupCode, String partNo, String custPartNo) {
        if(StringUtil.isEmpty(organizeCode) || StringUtil.isEmpty(shippingGroupCode) || StringUtil.isEmpty(partNo) || StringUtil.isEmpty(custPartNo)) return null;
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(shippingGroupCode, "shippingGroupCode", packBean);
        DdlPreparedPack.getStringEqualPack(partNo, "partNo", packBean);
        DdlPreparedPack.getStringEqualPack(custPartNo, "custPartNo", packBean);
        return mesPartShippingGroupDetailRepository.getByProperty(packBean);
    }

    @Override
    public MesPartShippingGroupDetail getMesPartShippingGroupDetailByPartNo(String organizeCode, String shippingGroupCode, String partNo) {
        if(StringUtil.isEmpty(organizeCode) || StringUtil.isEmpty(shippingGroupCode) || StringUtil.isEmpty(partNo)) return null;
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(shippingGroupCode, "shippingGroupCode", packBean);
        DdlPreparedPack.getStringEqualPack(partNo, "partNo", packBean);
        return mesPartShippingGroupDetailRepository.getByProperty(packBean);
    }

    private MesShippingOrderManagementModelForLiJia createPhysicalOrder(MesShippingOrderManagement pullingOrderInfo,
                                                                        List<String> assyCodeList,
                                                                        Map<String, List<MesShippingOrderManagementDetail>> detailByAssyCodeMap,
                                                                        List<MesShippingOrderManagementDetail> details) {
        MesShippingOrderManagementModelForLiJia model = new MesShippingOrderManagementModelForLiJia();
        //顶部的通用数据赋值
        model.setShippingGroupName(pullingOrderInfo.getShippingGroupName());
        model.setPrintDateTime(TimeTool.getNowTime(true));
        model.setShippingCode(pullingOrderInfo.getShippingCode());
        model.setDocumentNumber("YFVCQ-MS06-02-01");
        log.info("doMesMesShippingOrderManagementPrint-顶部的通用数据赋值" + model);
        //中部表结构赋值
        model.setDetailModelsOne(createDetailList(assyCodeList.get(0), detailByAssyCodeMap, details, pullingOrderInfo.getRackNo()));
        log.info("doMesMesShippingOrderManagementPrint-中部表结构赋值" + model);
        //底部表结构赋值
        model.setDetailModelsTwo(createDetailList(assyCodeList.get(1), detailByAssyCodeMap, details, pullingOrderInfo.getRackNo()));
        log.info("doMesMesShippingOrderManagementPrint-底部表结构赋值" + model);
        return model;
    }

    private List<MesShippingOrderManagementDetailModelForLiJia> createDetailList(
            String assyCode, Map<String, List<MesShippingOrderManagementDetail>> detailByAssyCodeMap,
            List<MesShippingOrderManagementDetail> details, String rackNo) {
        List<MesShippingOrderManagementDetailModelForLiJia> dataList = new ArrayList<>();
        //取出符合条件的发运单明细数据
        List<MesShippingOrderManagementDetail> nowDetailList = detailByAssyCodeMap.get(assyCode);
        log.info("doMesMesShippingOrderManagementPrint-createDetailList-nowDetailList" + nowDetailList.size());
        if (!CollectionUtils.isEmpty(nowDetailList)) {
            //并按照 logic_seq 升序排列
            List<MesShippingOrderManagementDetail> collect = nowDetailList.stream().sorted(
                    Comparator.comparing(MesShippingOrderManagementDetail::getLogicSeq)).collect(Collectors.toList());
            Integer number = 1;
            for (MesShippingOrderManagementDetail mesShippingOrderManagementDetail : collect) {
                MesShippingOrderManagementDetailModelForLiJia detailModel = new MesShippingOrderManagementDetailModelForLiJia();
                detailModel.setNumber(number);
                detailModel.setCustInfoSeq(mesShippingOrderManagementDetail.getCustInfoSeq());
                if (!StringUtils.isEmpty(mesShippingOrderManagementDetail.getVin())) {
                    detailModel.setVin(mesShippingOrderManagementDetail.getVin().substring(
                            mesShippingOrderManagementDetail.getVin().length() - 6));
                }
                detailModel.setCarSerialCode(mesShippingOrderManagementDetail.getCarSerialCode());
                detailModel.setPartNo(mesShippingOrderManagementDetail.getPartNo());
                detailModel.setCustPartNo(mesShippingOrderManagementDetail.getCustPartNo());
                detailModel.setCustPartName(mesShippingOrderManagementDetail.getPartName());
                detailModel.setRackNo(rackNo);
                dataList.add(detailModel);
                number ++;
            }
        }
        log.info("doMesMesShippingOrderManagementPrint-createDetailList-dataList" + dataList.size());
        return dataList;
    }

}
