package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.print.sortshipping.strategy;

import cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.print.IPrintTemplateStrategyService;
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.enumutil.ResourceEnumUtil;
import cn.estsh.i3plus.pojo.base.util.StringUtil;
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.MesShippingOrderManagementDetailModelForLiJia;
import cn.estsh.i3plus.pojo.mes.model.MesShippingOrderManagementModelForLiJia;
import cn.estsh.i3plus.pojo.mes.repository.MesCimCheryOrderRepository;
import cn.estsh.impp.framework.boot.util.ResultBean;
import com.alibaba.fastjson.JSONObject;
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.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @Description : 重庆礼嘉发运单
 **/
@Service
@Slf4j
public class CqLjSortShippingPrintStrategyService extends SortShippingDispatchStrategyService implements IPrintTemplateStrategyService {

    @Autowired
    private MesCimCheryOrderRepository cimCheryOrderRepository;

    @Override
    public List<MesShippingOrderManagement> getShippingOrderManagementList(MesShippingOrderManagement bean) {
        return super.getShippingOrderManagementList(bean);
    }

    @Override
    public List<MesShippingOrderManagementDetail> getShippingOrderManagementDetailList(String organizeCode, List<Long> idList, Object[] obj, String[] str) {
        return super.getShippingOrderManagementDetailList(organizeCode, idList, obj, str);
    }

    @Override
    public void saveShippingOrderManagementList(List<MesShippingOrderManagement> shippingOrderManagementList) {
        super.saveShippingOrderManagementList(shippingOrderManagementList);
    }

    @Override
    public ResultBean execute(MesShippingOrderManagement bean, List<MesShippingOrderManagement> shippingOrderManagementList) {

        //维护了该参数，则执行礼嘉的新逻辑
        List<MesShippingOrderManagementModelForLiJia> mainDataList = new ArrayList<>();

        List<Long> pidList = shippingOrderManagementList.stream().map(MesShippingOrderManagement::getId).collect(Collectors.toList());
        List<MesShippingOrderManagementDetail> shippingOrderManagementDetailList = getShippingOrderManagementDetailList(bean.getOrganizeCode(), pidList, null, null);

        log.info("工厂{}排序发运打印 --- 查询发运单明细信息:{}条 --- {}", bean.getOrganizeCode(),
                CollectionUtils.isEmpty(shippingOrderManagementDetailList) ? MesPcnExtConstWords.ZERO : shippingOrderManagementDetailList.size(), Thread.currentThread().getName());

        Map<Long, List<MesShippingOrderManagementDetail>> detailByPidMap = CollectionUtils.isEmpty(shippingOrderManagementDetailList) ? null :
                shippingOrderManagementDetailList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getPid()))).collect(Collectors.groupingBy(MesShippingOrderManagementDetail::getPid));

        //遍历处理每个发运单主表
        for (MesShippingOrderManagement shippingOrderManagement : shippingOrderManagementList) {
            log.info("工厂{}排序发运打印 --- 遍历 发运单:{} --- {}", bean.getOrganizeCode(), shippingOrderManagement.getShippingCode(), Thread.currentThread().getName());
            //一张实体发运单包含三部分信息（顶部的通用数据、中部的第一份表格数据，底部的第二份表格数据）
            //取出当前发运单的明细信息
            List<MesShippingOrderManagementDetail> details = null == detailByPidMap ? null : detailByPidMap.get(shippingOrderManagement.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));
                }
                log.info("工厂{}排序发运打印 --- 遍历 发运单:{} --- assyCodeList:{} --- logicSeqAndAssyCodeMap:{} --- {}", bean.getOrganizeCode(), shippingOrderManagement.getShippingCode(), assyCodeList.toString(), JSONObject.toJSONString(logicSeqAndAssyCodeMap), Thread.currentThread().getName());
                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());
                if (!CollectionUtils.isEmpty(physicalOrderList)) {
                    log.info("工厂{}排序发运打印 --- 遍历 发运单:{} --- physicalOrderList:{} --- {}", bean.getOrganizeCode(), shippingOrderManagement.getShippingCode(), JSONObject.toJSONString(physicalOrderList), Thread.currentThread().getName());
                    for (List<String> list : physicalOrderList) {
                        //生成一张实体发运单
                        log.info("工厂{}排序发运打印 --- 生成一张实体发运单:{} --- {}", bean.getOrganizeCode(), list.toString(), Thread.currentThread().getName());
                        mainDataList.add(createPhysicalOrder(shippingOrderManagement, list, detailByAssyCodeMap, details));
                    }
                }
            }
            shippingOrderManagement.setPrintCount(StringUtil.isEmpty(shippingOrderManagement.getPrintCount())? 1 : shippingOrderManagement.getPrintCount()+1);
            shippingOrderManagement.setLastPrintTime(TimeTool.getNowTime(true));
            shippingOrderManagement.setLastPrintUser(bean.getUserInfo());
            ConvertBean.serviceModelUpdate(shippingOrderManagement, bean.getUserInfo());
        }

        saveShippingOrderManagementList(shippingOrderManagementList);

        return ResultBean.success("发运单打印成功").setCode(ResourceEnumUtil.MESSAGE.SUCCESS.getCode()).setResultList(mainDataList);

    }

    private MesShippingOrderManagementModelForLiJia createPhysicalOrder(MesShippingOrderManagement shippingOrderManagement,
                                                                        List<String> assyCodeList,
                                                                        Map<String, List<MesShippingOrderManagementDetail>> detailByAssyCodeMap,
                                                                        List<MesShippingOrderManagementDetail> details) {
        MesShippingOrderManagementModelForLiJia model = new MesShippingOrderManagementModelForLiJia();
        //顶部的通用数据赋值
        model.setShippingGroupName(shippingOrderManagement.getShippingGroupName());
        model.setPrintDateTime(TimeTool.getNowTime(true));
        model.setShippingCode(shippingOrderManagement.getShippingCode());
        model.setDocumentNumber("YFVCQ-MS06-02-01");
        //中部表结构赋值
        model.setDetailModelsOne(createDetailList(assyCodeList.get(0), detailByAssyCodeMap, details, shippingOrderManagement.getRackNo()));
        //底部表结构赋值
        if (assyCodeList.size() > 1) model.setDetailModelsTwo(createDetailList(assyCodeList.get(1), detailByAssyCodeMap, details, shippingOrderManagement.getRackNo()));
        else model.setDetailModelsTwo(new ArrayList<>());
        log.info("工厂{}排序发运打印 --- MesShippingOrderManagementModelForLiJia:{} --- {}", shippingOrderManagement.getOrganizeCode(), JSONObject.toJSONString(model), Thread.currentThread().getName());
        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);
        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 ++;
            }
        }
        return dataList;
    }
}
