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

import cn.estsh.i3plus.ext.mes.pcn.api.base.IShiftExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.base.ISxWorkOrderExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IPackageExtService;
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.ep.IEpQmsOqcManageService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.dao.ep.IEpProduceSnExtDao;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.dao.ep.IEpProduceSnRepairDao;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesPackageExt;
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.ep.EpProduceSnExtModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.ep.SxEpOqcManageModel;
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.exception.ImppExceptionEnum;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesPackageDetail;
import cn.estsh.i3plus.pojo.mes.bean.MesShift;
import cn.estsh.impp.framework.boot.exception.ImppExceptionBuilder;
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;

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

    @Autowired
    private IProduceSnExtService produceSnExtService;

    @Autowired
    private ISxWorkOrderExtService workOrderExtService;

    @Autowired
    private IProduceSnRepairService produceSnRepairService;

    @Autowired
    private IPackageExtService packageExtService;

    @Autowired
    private IShiftExtService shiftExtService;

    @Autowired
    private IEpProduceSnExtDao epProduceSnExtDao;

    @Autowired
    private IEpProduceSnRepairDao epProduceSnRepairDao;

    @Override
    public SxEpOqcManageModel queryEpQmsOqcManageData(Map<String, Object> params) {
        String organizeCode = (String) params.get(MesPcnExtConstWords.ORGANIZE_CODE);
        String sn = (String) params.get(MesPcnExtConstWords.SN);
        String dataType = (String) params.get(MesPcnExtConstWords.DATA_TYPE);
        return queryEpQmsOqcManageData(organizeCode, sn, dataType);
    }

    private SxEpOqcManageModel queryEpQmsOqcManageData(String organizeCode, String serialNumber, String dataType) {
        log.info("EP-QMS获取出货检验正常检验主数据,参数organizeCode[{}]serialNumber[{}]dataType[{}]", organizeCode, serialNumber, dataType);

        MesProduceSnExt produceSnExt = getProduceSn(organizeCode, serialNumber);

        SxEpOqcManageModel result = new SxEpOqcManageModel();

        packModelByProduceSn(result, produceSnExt, organizeCode);

        packModelBySerialNumber(result, organizeCode, serialNumber);

        MesWorkOrderExt workOrderExt = getWorkOrder(organizeCode, serialNumber, result);

        packModelByWorkOrder(result, workOrderExt);

        packModelByShiftCode(result, organizeCode);

        log.info("EP-QMS获取出货检验正常检验主数据,结果result[{}]", JSONObject.toJSONString(result));

        if (CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValueStr().equals(dataType)) return result;

        queryEpQmsOqcManageSn(result, organizeCode);

        return result;
    }

    private void packModelByProduceSn(SxEpOqcManageModel result, MesProduceSnExt produceSnExt, String organizeCode) {
        if (produceSnExt.getLastWorkOrderNo().equals(produceSnExt.getWorkOrderNo())) {
            result.setWorkOrderNo(produceSnExt.getWorkOrderNo());
            result.setWorkTime(produceSnExt.getWorkTime());
            result.setShiftCode(produceSnExt.getShiftCode());
        } else {
            result.setWorkOrderType(MesPcnExtEnumUtil.WORK_ORDER_TYPE.REWORK_ORDER.getValue());

            MesProduceSnRepair produceSnRepair = produceSnRepairService.getProduceSnRepairBySnAndOrderNo(organizeCode, produceSnExt.getSerialNumber(), produceSnExt.getLastWorkOrderNo());
            if (null == produceSnRepair) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                        .setErrorDetail("产品条码[%s]关联返工工单[%s]的记录不存在,请重新扫描", produceSnExt.getSerialNumber(), produceSnExt.getLastWorkOrderNo())
                        .build();
            }
            result.setWorkOrderNo(produceSnExt.getLastWorkOrderNo());
            result.setWorkTime(produceSnRepair.getWorkTime());
            result.setShiftCode(produceSnRepair.getShiftCode());
        }
    }

    private void packModelByWorkOrder(SxEpOqcManageModel result, MesWorkOrderExt workOrderExt) {
        result.setWorkOrderType(workOrderExt.getWorkOrderType());
        result.setWorkOrderTypeName(MesPcnExtEnumUtil.WORK_ORDER_TYPE.valueOfDescription(workOrderExt.getWorkOrderType()));
        result.setPartNo(workOrderExt.getPartNo());
        result.setPartNameRdd(workOrderExt.getPartNameRdd());
        result.setWorkCenterCode(workOrderExt.getWorkCenterCode());
        result.setQty(workOrderExt.getQty());
        result.setCompleteQty(workOrderExt.getCompleteQty());
    }

    private void packModelByShiftCode(SxEpOqcManageModel result, String organizeCode) {
        MesShift shiftDb = shiftExtService.getShiftByShiftCodeAndCenterCode(organizeCode, result.getWorkCenterCode(), result.getShiftCode());
        if (null != shiftDb) result.setShiftName(shiftDb.getShiftName());
    }

    private void packModelBySerialNumber(SxEpOqcManageModel result, String organizeCode, String serialNumber) {
        MesPackageDetail packageDetail = packageExtService.getPackageDetailBySn(organizeCode, serialNumber);
        if (null == packageDetail) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("产品条码[%s]未关联包装条码,请重新扫描", serialNumber)
                    .build();
        }
        MesPackageExt packageExt = packageExtService.getPackageByPackNo(organizeCode, packageDetail.getPackageNo());
        if (null == packageExt) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("产品条码[%s]关联的包装条码[%s]不存在,请重新扫描", serialNumber, packageDetail.getPackageNo())
                    .build();
        }
        if (!packageExt.getLastWorkOrderNo().equals(result.getWorkOrderNo())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("产品条码[%s]关联的包装条码[%s]未关联%s[%s],请重新扫描",
                            serialNumber, packageDetail.getPackageNo(), MesPcnExtEnumUtil.WORK_ORDER_TYPE.valueOfDescription(result.getWorkOrderType()), result.getWorkOrderNo())
                    .build();
        }
        result.setPackageNo(packageDetail.getPackageNo());
        result.setSerialNumber(serialNumber);
    }

    private MesProduceSnExt getProduceSn(String organizeCode, String serialNumber) {
        MesProduceSnExt produceSnExt = produceSnExtService.getProduceSnExtBySn(organizeCode, serialNumber);
        if (null == produceSnExt) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("产品条码[%s]不存在,请重新扫描", serialNumber)
                    .build();
        }
        if (MesPcnExtEnumUtil.PRODUCE_SN_STATUS.OFFLINE.getValue() != produceSnExt.getSnStatus() &&
                MesPcnExtEnumUtil.PRODUCE_SN_STATUS.ERR_OFFLINE.getValue() != produceSnExt.getSnStatus()) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("产品条码[%s]未打包下线,请重新扫描", serialNumber)
                    .build();
        }
        if (MesPcnExtEnumUtil.PRODUCE_SN_QC_STATUS.QUALIFIED.getValue() != produceSnExt.getQcStatus()) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("产品条码[%s]质量状态[%s],请重新扫描",
                            serialNumber, MesPcnExtEnumUtil.PRODUCE_SN_QC_STATUS.valueOfDescription(produceSnExt.getQcStatus()))
                    .build();
        }
        return produceSnExt;
    }

    private MesWorkOrderExt getWorkOrder(String organizeCode, String serialNumber, SxEpOqcManageModel result) {
        MesWorkOrderExt workOrderExt = workOrderExtService.getWorkOrderExtByOrderNo(organizeCode, result.getWorkOrderNo());
        if (null == workOrderExt) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("产品条码[%s]关联的%s[%s]不存在,请重新扫描",
                            serialNumber, StringUtils.isEmpty(result.getWorkOrderType()) ? "生产工单" : "返工工单", result.getWorkOrderNo())
                    .build();
        }
        return workOrderExt;
    }

    private SxEpOqcManageModel queryEpQmsOqcManageSn(SxEpOqcManageModel result, String organizeCode) {

        log.info("EP-QMS获取出货检验正常检验条码数据,参数organizeCode[{}]serialNumber[{}]", organizeCode, result.getSerialNumber());

        List<EpProduceSnExtModel> produceSnList;
        if (MesPcnExtEnumUtil.WORK_ORDER_TYPE.REWORK_ORDER.getValue() != result.getWorkOrderType()) {
            produceSnList = epProduceSnExtDao.querySnListByOrderNoAndWorkTime4Oqc(organizeCode, result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode());
            produceSnList = CollectionUtils.isEmpty(produceSnList) ? null :
                    produceSnList.stream().filter(o -> (null != o && o.getWorkOrderNo().equals(o.getLastWorkOrderNo()))).collect(Collectors.toList());
        } else {
            produceSnList = epProduceSnRepairDao.querySnRepairListByOrderNoAndWorkTime4Oqc(organizeCode, result.getWorkOrderNo(), result.getWorkTime(), result.getShiftCode());
        }

        packProdMapList(produceSnList, result);

        log.info("EP-QMS获取出货检验正常检验条码数据,结果result[{}]", JSONObject.toJSONString(result));

        return result;
    }

    private void packProdMapList(List<EpProduceSnExtModel> produceSnList, SxEpOqcManageModel result) {
        if (!CollectionUtils.isEmpty(produceSnList)) {

            produceSnList = produceSnList.stream().filter(o -> null != o).sorted(Comparator.comparing(EpProduceSnExtModel::getOutWorkCenterTime)).collect(Collectors.toList());

            List<Map<String, String>> prodMapList = new ArrayList<>();

            for (EpProduceSnExtModel produceSn : produceSnList) {
                if (null == produceSn) {
                    continue;
                }
                Map<String, String> prodMap = new HashMap<>();
                prodMap.put(MesPcnExtConstWords.SERIAL_NUMBER, produceSn.getSerialNumber());
                prodMap.put(MesPcnExtConstWords.PACKAGENO, produceSn.getPackageNo());
                prodMapList.add(prodMap);

                if (produceSn.getSerialNumber().equals(result.getSerialNumber())) break;

            }

            result.setProdMapList(prodMapList);
        }
    }
}
