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

import cn.estsh.i3plus.ext.mes.api.busi.bu.IBuPatchPartConfirmService;
import cn.estsh.i3plus.ext.mes.pojo.bean.MesErrorLineOff;
import cn.estsh.i3plus.ext.mes.pojo.bean.MesErrorLineOffDetail;
import cn.estsh.i3plus.ext.mes.pojo.bean.MesProcessBom;
import cn.estsh.i3plus.ext.mes.pojo.model.bu.MesPatchPartConfirmModel;
import cn.estsh.i3plus.ext.mes.pojo.repository.MesErrorLineOffDetailRepository;
import cn.estsh.i3plus.ext.mes.pojo.repository.MesErrorLineOffRepository;
import cn.estsh.i3plus.ext.mes.pojo.repository.MesProcessBomRepository;
import cn.estsh.i3plus.ext.mes.pojo.util.MesExtConstWords;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.platform.common.exception.ImppExceptionEnum;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.bean.ListPager;
import cn.estsh.i3plus.pojo.base.common.Pager;
import cn.estsh.i3plus.pojo.base.common.PagerHelper;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.impp.framework.boot.auth.AuthUtil;
import cn.estsh.impp.framework.boot.exception.ImppExceptionBuilder;
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;

@Slf4j
@Service
public class BuPatchPartConfirmService implements IBuPatchPartConfirmService {

    @Autowired
    private MesErrorLineOffRepository errorLineOffRepository;

    @Autowired
    private MesErrorLineOffDetailRepository errorLineOffDetailRepository;

    @Autowired
    private MesProcessBomRepository processBomRepository;

    /**
     * 查询异常下线数据
     * @param orderNo
     * @param userName
     * @param organizeCode
     * @return
     */
    @Override
    public ListPager getExOffline(String orderNo, String userName, String organizeCode, Pager pager) {
        if (null == orderNo) {
            pager = PagerHelper.getPager(pager, errorLineOffRepository.listCount());
            return (new ListPager(errorLineOffRepository.listPager(pager), pager));
        } else {
            DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
            DdlPreparedPack.getStringEqualPack(orderNo, MesExtConstWords.WORK_ORDER_NO, packBean);

            int count = errorLineOffRepository.findByHqlWhereCount(packBean);
            pager = PagerHelper.getPager(pager, count);
            DdlPreparedPack.getOrderByPack(new Object[]{CommonEnumUtil.ASC_OR_DESC.DESC.getValue()}, new String[]{MesExtConstWords.MODIFY_DATE_TIME}, packBean);
            List<MesErrorLineOff> errorLineOffList = errorLineOffRepository.findByHqlWherePage(packBean, pager);

            return new ListPager(errorLineOffList, pager);

        }
    }

    /**
     * 查询原始子物料
     * @return
     */
    @Override
    public List getBeforeOartBom(MesPatchPartConfirmModel patchPartConfirmModel) {

        List<String> snList = patchPartConfirmModel.getSnList();
        String orderNo = patchPartConfirmModel.getOrderNo();
        String userName = AuthUtil.getSessionUser().getUserName();
        String organizeCode = AuthUtil.getOrganize().getOrganizeCode();

        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(orderNo, MesExtConstWords.WORK_ORDER_NO, packBean);
        List<MesErrorLineOffDetail> errorLineOffDetailList = errorLineOffDetailRepository.findByHqlWhere(packBean);

        Map<String,List<MesErrorLineOffDetail>> errorLineListBySn = new HashMap<>();

        Integer sizeMin = 0;
        String snMin = null;

        for (String sn : snList) {
            List<MesErrorLineOffDetail> collect = errorLineOffDetailList.stream().filter(e -> e.getSerialNumber().equals(sn)).collect(Collectors.toList());
            errorLineListBySn.put(sn,collect);
            if (sizeMin == 0){
                sizeMin = collect.size();
                snMin = sn;
            }else if (collect.size() < sizeMin){
                sizeMin = collect.size();
                snMin = sn;
            }

        }

        List<MesErrorLineOffDetail> resultList = new ArrayList<>();

        List<MesErrorLineOffDetail> errorLineOffDetailListMin = errorLineListBySn.get(snMin);

        Integer count = 0;
        for (MesErrorLineOffDetail min : errorLineOffDetailListMin) {
            count = 0;
            for (List<MesErrorLineOffDetail> value : errorLineListBySn.values()) {
                List<MesErrorLineOffDetail> collect = value.stream().filter(e -> e.getItemPartNo().equals(min.getItemPartNo())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(collect)){
                    count += 1;
                }
            }
            if (count == snList.size()){
                resultList.add(min);
            }
        }

        if (!StringUtils.isEmpty(patchPartConfirmModel.getItemPartNo())){
            resultList = resultList.stream().filter(r -> r.getItemPartNo().equals(patchPartConfirmModel.getItemPartNo())).collect(Collectors.toList());
        }

        if (!StringUtils.isEmpty(patchPartConfirmModel.getItemPartName())){
            resultList = resultList.stream().filter(r -> r.getItemPartName().contains(patchPartConfirmModel.getItemPartName())).collect(Collectors.toList());
        }

        return resultList;
    }

    /**
     * 查询新子物料
     * @param userName
     * @param organizeCode
     * @return
     */
    @Override
    public List getAfterOartBom(String partNo, String userName, String organizeCode, String itemPartNo, String itemPartName ,Integer isBindKey) {

        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(partNo, MesExtConstWords.PART_NO, packBean);
//        DdlPreparedPack.getNumEqualPack(MesExtEnumUtil.IS_BIND_KEY.YES.getValue(), "isBindKey", packBean);
        List<MesProcessBom> processBomList = processBomRepository.findByHqlWhere(packBean);

        if (!CollectionUtils.isEmpty(processBomList)){

            //通过子物料去重
            processBomList = processBomList.stream() .collect(Collectors.collectingAndThen(
                    Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o-> new StringJoiner(MesExtConstWords.AND).add(o.getItemPartNo()).add(o.getIsBindKey().toString()).toString()))), ArrayList::new));

        }

        if (!StringUtils.isEmpty(itemPartNo)){
            processBomList = processBomList.stream().filter(r -> r.getItemPartNo().equals(itemPartNo)).collect(Collectors.toList());
        }

        if (!StringUtils.isEmpty(itemPartName)){
            processBomList = processBomList.stream().filter(r -> r.getItemPartName().contains(itemPartName)).collect(Collectors.toList());
        }

        if (null != isBindKey){
            processBomList = processBomList.stream().filter(r -> r.getIsBindKey() == isBindKey).collect(Collectors.toList());
        }

        return processBomList;
    }

    /**
     * 替换原有子物料号
     * @return
     */
    @Override
    public void insertUpdateReplacePartBom(MesPatchPartConfirmModel patchPartConfirmModel) {
        List<String> snList = patchPartConfirmModel.getSnList();
        String orderNo = patchPartConfirmModel.getOrderNo();
        String beforePartNo = patchPartConfirmModel.getBeforePartNo();
        String afterPartNo = patchPartConfirmModel.getAfterPartNo();
        String afterPartName = patchPartConfirmModel.getAfterPartName();
        String organizeCode = patchPartConfirmModel.getOrganizeCode();

        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(orderNo, MesExtConstWords.WORK_ORDER_NO, packBean);
        List<MesErrorLineOffDetail> errorLineOffDetailList = errorLineOffDetailRepository.findByHqlWhere(packBean);

        List<MesErrorLineOffDetail> mesErrorLineOffDetailList = new ArrayList<>();

        for (String sn : snList) {
            List<MesErrorLineOffDetail> collect = errorLineOffDetailList.stream().filter(e -> e.getSerialNumber().equals(sn)).collect(Collectors.toList());
            mesErrorLineOffDetailList.addAll(collect);

        }

        List<MesErrorLineOffDetail> afterList = mesErrorLineOffDetailList.stream().filter(e -> e.getItemPartNo().equals(afterPartNo)).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(afterList)){
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES.getCode())
                    .setErrorCode(ImppExceptionEnum.BUSINESS_EXCEPTION.getCode())
                    .setErrorDetail("物料【%s】已存在bom【%s】无法替换",orderNo,afterPartNo)
                    .build();
        }

        List<MesErrorLineOffDetail> beforeList = mesErrorLineOffDetailList.stream().filter(e -> e.getItemPartNo().equals(beforePartNo)).collect(Collectors.toList());

        beforeList.forEach(b -> {
            b.setItemPartNo(afterPartNo);
            b.setItemPartName(afterPartName);
            ConvertBean.modelUpdate(b, AuthUtil.getSessionUser());
            errorLineOffDetailRepository.update(b);
        });

    }
}
