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

import cn.estsh.i3plus.ext.mes.pcn.api.base.IBomExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMissingPartService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IProduceSnExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IProduceSnRepairService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.jx.IJxProduceSnRepairService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesMissingPart;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesProduceSnExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesProduceSnRepair;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesWorkOrderExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.MissPartConfirmModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.MissingPartBomModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.MissingPartDataModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.repository.MesMissingPartRepository;
import cn.estsh.i3plus.ext.mes.pcn.pojo.repository.MesWorkOrderExtRepository;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtEnumUtil;
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.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.mes.bean.MesBom;
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.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author wangjie
 * @version 1.0
 * @date 2021/1/13 9:28
 **/
@Slf4j
@Service
public class MissingPartService implements IMissingPartService {

    @Autowired
    private MesWorkOrderExtRepository workOrderExtRepository;

    @Autowired
    private MesMissingPartRepository missingPartRepository;

    @Autowired
    private IProduceSnExtService produceSnExtService;

    @Autowired
    private IJxProduceSnRepairService produceSnRepairService;

    @Autowired
    private IBomExtService bomExtService;

    @Override
    public MissingPartDataModel queryMissingPartModelData(MissingPartDataModel model) {

        MissingPartDataModel result = packMissingPartDataModel(model);

        List<MesWorkOrderExt> workOrderExtList = getWorkOrderExtList(model);
        if (!CollectionUtils.isEmpty(workOrderExtList)) {
            packMissingPartDataModelByWorkOrder(result, workOrderExtList.get(0));

            packMissingPartDataModelByBomDbList(result);

            packMissingPartDataModelByMissingPartDbList(result);
        }
        return result;
    }

    @Override
    public List<MesMissingPart> getMissingPartByWorkOrderNo(String organizeCode, String workOrderNo) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(workOrderNo)) {
            return null;
        }
        return missingPartRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.WORK_ORDER_NO},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), workOrderNo},
                " order by createDatetime asc ");
    }

    @Override
    public MissPartConfirmModel getMissingPartAndWorkOrderBySn(String serialNumber, String organizeCode) {
        String workOrderNo;
        String workTime;
        MesProduceSnExt produceSnExt = produceSnExtService.getProduceSnExtByProductSn(organizeCode, serialNumber);
        if (null == produceSnExt) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("产品条码[%s]无效", serialNumber)
                    .build();
        }

        if (!StringUtils.isEmpty(produceSnExt.getLastWorkOrderNo()) && !produceSnExt.getLastWorkOrderNo().equals(produceSnExt.getWorkOrderNo())) {
            MesProduceSnRepair produceSnRepair = produceSnRepairService.getProduceSnRepairByProductSn(organizeCode, serialNumber);
            if (null == produceSnRepair) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                        .setErrorDetail("产品条码[%s]与返工工单[%s]的关联关系不存在", serialNumber, produceSnExt.getLastWorkOrderNo())
                        .build();
            }
            workOrderNo = produceSnRepair.getWorkOrderNo();
            workTime = produceSnRepair.getWorkTime();
        } else {
            workOrderNo = produceSnExt.getWorkOrderNo();
            workTime = produceSnExt.getWorkTime();
        }

        MissPartConfirmModel missPartConfirm = new MissPartConfirmModel();
        missPartConfirm.setOrderNo(workOrderNo);
        missPartConfirm.setPartNo(produceSnExt.getPartNo());
        missPartConfirm.setPartName(produceSnExt.getPartNameRdd());
        missPartConfirm.setWorkTime(workTime);
        return missPartConfirm;
    }

    private List<MesWorkOrderExt> getWorkOrderExtList(MissingPartDataModel model) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(model.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(model.getWorkCenterCode(), MesPcnExtConstWords.WORK_CENTER_CODE, packBean);
        DdlPreparedPack.getNumEqualPack(MesPcnExtEnumUtil.WORK_ORDER_STATUS.OPEN.getValue(), MesPcnExtConstWords.WORK_ORDER_STATUS, packBean);
        DdlPreparedPack.getStringEqualPack(model.getWorkOrderNo(), MesPcnExtConstWords.ORDER_NO, packBean);
        DdlPreparedPack.getOrderByPack(new Object[]{CommonEnumUtil.ASC_OR_DESC.ASC.getValue()}, new String[]{MesPcnExtConstWords.SEQ}, packBean);
        return workOrderExtRepository.findByHqlWhere(packBean);
    }

    @Override
    public MissingPartDataModel insertMissingPart(MissingPartDataModel model) {

        checkBomList(model.getBomList());

        MissingPartDataModel result = packMissingPartDataModel(model);

        MesWorkOrderExt workOrderExt = getWorkOrderExtComm(model);

        packMissingPartDataModelByWorkOrder(result, workOrderExt);

        packMissingPartDataModelByMissingPartDbList(result);

        checkIsExistMissingBomForInsert(result, model);

        packMissingPartDataModelByBomDbList(result);

        insertAndPackMissingPart(result, model, workOrderExt);

        return result;
    }

    private void checkIsExistMissingBomForInsert(MissingPartDataModel result, MissingPartDataModel model) {
        if (!CollectionUtils.isEmpty(result.getMissingPartList())) {
            List<String> itemPartNoList = model.getBomList().stream().filter(o -> null != o).map(MissingPartBomModel::getItemPartNo).collect(Collectors.toList());
            List<MissingPartBomModel> existList = result.getMissingPartList().stream().filter(o -> (null != o && itemPartNoList.contains(o.getItemPartNo()))).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(existList)) {
                List<String> existPartList = existList.stream().filter(o -> null != o).map(MissingPartBomModel::getItemPartNo).collect(Collectors.toList());
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                        .setErrorDetail("缺件BOM%s已存在", existPartList.toString())
                        .build();
            }
        }
    }

    private void insertAndPackMissingPart(MissingPartDataModel result, MissingPartDataModel model, MesWorkOrderExt workOrderExt) {
        List<MissingPartBomModel> missingPartList = result.getMissingPartList();
        for (MissingPartBomModel bomModel : model.getBomList()) {
            if (null == bomModel) {
                continue;
            }

            insertMissingPartByBom(model, bomModel, workOrderExt);

            if (CollectionUtils.isEmpty(missingPartList)) {
                missingPartList = new ArrayList<>();
            }
            missingPartList.add(new MissingPartBomModel(bomModel.getItemPartNo(), bomModel.getItemPartName()));
        }
        result.setMissingPartList(missingPartList);
    }

    private void insertMissingPartByBom(MissingPartDataModel model, MissingPartBomModel bomModel, MesWorkOrderExt workOrderExt) {
        MesMissingPart missingPart = new MesMissingPart();
        missingPart.setWorkOrderNo(model.getWorkOrderNo());
        missingPart.setWorkCenterCode(model.getWorkCenterCode());
        missingPart.setPartNo(workOrderExt.getPartNo());
        missingPart.setPartName(workOrderExt.getPartNameRdd());
        missingPart.setItemPartNo(bomModel.getItemPartNo());
        missingPart.setItemPartName(bomModel.getItemPartName());
        missingPart.setOrganizeCode(model.getOrganizeCode());
        ConvertBean.serviceModelInitialize(missingPart, model.getUserInfo());
        missingPartRepository.insert(missingPart);
    }

    @Override
    public MissingPartDataModel deleteMissingPart(MissingPartDataModel model) {

        checkBomList(model.getBomList());

        MissingPartDataModel result = packMissingPartDataModel(model);

        MesWorkOrderExt workOrderExt = getWorkOrderExtComm(model);

        packMissingPartDataModelByWorkOrder(result, workOrderExt);

        List<MesMissingPart> missingPartDbList = getMissingPartByWorkOrderNo(result.getOrganizeCode(), result.getWorkOrderNo());

        packMissingPartDataModelByMissingPartDbList(result, missingPartDbList);

        checkIsExistMissingBomForDelete(result, model);

        packMissingPartDataModelByBomDbList(result);

        deleteAndPackMissingPart(result, model, missingPartDbList);

        return result;
    }

    private void checkIsExistMissingBomForDelete(MissingPartDataModel result, MissingPartDataModel model) {
        if (CollectionUtils.isEmpty(result.getMissingPartList())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("不存在缺件BOM记录,删除失败")
                    .build();
        }
        List<String> itemPartNoList = result.getMissingPartList().stream().filter(o -> null != o).map(MissingPartBomModel::getItemPartNo).collect(Collectors.toList());

        List<MissingPartBomModel> unExistList = model.getBomList().stream().filter(o -> (null != o && !itemPartNoList.contains(o.getItemPartNo()))).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(unExistList)) {
            List<String> unExistPartList = unExistList.stream().filter(o -> null != o).map(MissingPartBomModel::getItemPartNo).collect(Collectors.toList());
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("缺件BOM记录%s不存在,删除失败", unExistPartList.toString())
                    .build();
        }
    }

    private void deleteAndPackMissingPart(MissingPartDataModel result, MissingPartDataModel model, List<MesMissingPart> missingPartDbList) {
        List<String> itemPartNoList = model.getBomList().stream().filter(o -> null != o).map(MissingPartBomModel::getItemPartNo).collect(Collectors.toList());
        for (MesMissingPart missingPart : missingPartDbList) {
            if (null == missingPart) {
                continue;
            }
            if (!itemPartNoList.contains(missingPart.getItemPartNo())) {
                continue;
            }
            missingPart.setIsDeleted(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());
            ConvertBean.serviceModelUpdate(missingPart, model.getUserInfo());
            missingPartRepository.save(missingPart);
        }

        List<MissingPartBomModel> missingPartList = null;
        for (MissingPartBomModel bomModel : result.getMissingPartList()) {
            if (null == bomModel) {
                continue;
            }
            if (itemPartNoList.contains(bomModel.getItemPartNo())) {
                continue;
            }
            if (CollectionUtils.isEmpty(missingPartList)) {
                missingPartList = new ArrayList<>();
            }
            missingPartList.add(bomModel);
        }
        result.setMissingPartList(missingPartList);
    }


    private void checkBomList(List<MissingPartBomModel> bomList) {
        if (CollectionUtils.isEmpty(bomList)) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("请选择缺件BOM")
                    .build();
        }
    }

    private MesWorkOrderExt getWorkOrderExtComm(MissingPartDataModel model) {
        List<MesWorkOrderExt> workOrderExtList = getWorkOrderExtList(model);
        if (CollectionUtils.isEmpty(workOrderExtList)) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("工单[%s]不能操作", model.getWorkOrderNo())
                    .build();
        }
        return workOrderExtList.get(0);
    }

    private MissingPartDataModel packMissingPartDataModel(MissingPartDataModel model) {
        MissingPartDataModel result = new MissingPartDataModel();
        result.setOrganizeCode(model.getOrganizeCode());
        result.setWorkCenterCode(model.getWorkCenterCode());
        result.setWorkOrderNo(model.getWorkOrderNo());
        return result;
    }

    private void packMissingPartDataModelByWorkOrder(MissingPartDataModel result, MesWorkOrderExt workOrderExt) {
        result.setWorkOrderNo(workOrderExt.getOrderNo());
        result.setPartNo(workOrderExt.getPartNo());
        result.setPartName(workOrderExt.getPartNameRdd());
        result.setQty(workOrderExt.getQty());
        result.setCompleteQty(workOrderExt.getCompleteQty());
    }

    private void packMissingPartDataModelByBomDbList(MissingPartDataModel result) {
        List<MesBom> bomDbList = bomExtService.getBomListByPartNo(result.getOrganizeCode(), result.getPartNo());
        if (!CollectionUtils.isEmpty(bomDbList)) {
            List<MissingPartBomModel> bomList = new ArrayList<>();
            for (MesBom bom : bomDbList) {
                if (null == bom) {
                    continue;
                }
                bomList.add(new MissingPartBomModel(bom.getItemPartNo(), bom.getItemPartName()));
            }
            result.setBomList(bomList);
        }
    }

    private void packMissingPartDataModelByMissingPartDbList(MissingPartDataModel result) {
        List<MesMissingPart> missingPartDbList = getMissingPartByWorkOrderNo(result.getOrganizeCode(), result.getWorkOrderNo());
        packMissingPartDataModelByMissingPartDbList(result, missingPartDbList);
    }

    private void packMissingPartDataModelByMissingPartDbList(MissingPartDataModel result, List<MesMissingPart> missingPartDbList) {
        if (!CollectionUtils.isEmpty(missingPartDbList)) {
            List<MissingPartBomModel> missingPartList = new ArrayList<>();
            for (MesMissingPart missingPart : missingPartDbList) {
                if (null == missingPart) {
                    continue;
                }
                missingPartList.add(new MissingPartBomModel(missingPart.getItemPartNo(), missingPart.getItemPartName()));
            }
            result.setMissingPartList(missingPartList);
        }
    }
}
