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

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.IOutPutStatisticsService;
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.bu.IBuQmsOqcManageService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.base.ShiftExtService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.base.SxWorkOrderExtService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.busi.OutPutStatisticsService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.busi.PackageExtService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.busi.ProduceSnExtService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.busi.ProduceSnRepairService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesOutPutStatistics;
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.model.bu.SxBuOqcDataModel;
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.i3plus.pojo.mes.bean.MesWorkOrder;
import cn.estsh.impp.framework.boot.exception.ImppExceptionBuilder;
import cn.estsh.impp.framework.boot.util.SpringContextsUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.util.Map;

/**
 * @Description 出货检验 成品 被代理产品
 * @author wangjie
 * @version 1.0
 * @date 2021/1/13 9:28
 **/
@Slf4j
public class BuQmsOqcBySnExecBusiService implements IBuQmsOqcManageService {

    private IProduceSnExtService produceSnExtService;

    private IPackageExtService packageExtService;

    private ISxWorkOrderExtService workOrderExtService;

    private IProduceSnRepairService produceSnRepairService;

    private IShiftExtService shiftExtService;

    private IOutPutStatisticsService outPutStatisticsService;

    public BuQmsOqcBySnExecBusiService() {

        produceSnExtService = SpringContextsUtil.getBean(ProduceSnExtService.class);

        packageExtService = SpringContextsUtil.getBean(PackageExtService.class);

        workOrderExtService = SpringContextsUtil.getBean(SxWorkOrderExtService.class);

        produceSnRepairService = SpringContextsUtil.getBean(ProduceSnRepairService.class);

        shiftExtService = SpringContextsUtil.getBean(ShiftExtService.class);

        outPutStatisticsService = SpringContextsUtil.getBean(OutPutStatisticsService.class);

    }

    @Override
    public SxBuOqcDataModel exec(Map<String, Object> params) {

        String organizeCode = (String) params.get(MesPcnExtConstWords.ORGANIZE_CODE);

        String serialNumber = (String) params.get(MesPcnExtConstWords.VALUE);

        String dataType = (String) params.get(MesPcnExtConstWords.DATA_TYPE);

        log.info("BU-QMS出货检验公共方法 --- 成品出货检验 --- 获取条码关联信息 START --- --- 线程ID[{}]", Thread.currentThread().getName());

        //条码
        MesProduceSnExt produceSnExt = getProduceSn(organizeCode, serialNumber);

        //包装明细
        MesPackageDetail packageDetail = getPackageDetail(organizeCode, serialNumber);

        //工单
        MesWorkOrder workOrder = getWorkOrder(organizeCode, produceSnExt);

        //初始化
        SxBuOqcDataModel oqcDataModel = new SxBuOqcDataModel(organizeCode, serialNumber);

        //封装生产日期与班次
        packOrderAndWorkTimeAndShift(oqcDataModel, produceSnExt, workOrder);

        //产量
        MesOutPutStatistics outPutStatisticsDb = getOutPutStatistics(oqcDataModel);

        //数据组合
        packOqcManageData(oqcDataModel, packageDetail.getPackageNo(), outPutStatisticsDb);

        log.info("BU-QMS出货检验公共方法 --- 成品出货检验 --- 获取条码关联信息 SUCCESS --- result[{}] --- 线程ID[{}]", JSONObject.toJSONString(oqcDataModel), Thread.currentThread().getName());

        if (StringUtils.isEmpty(dataType) || CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValueStr() == dataType) return oqcDataModel;

        log.info("BU-QMS出货检验公共方法 --- 成品出货检验 --- 获取条码组信息 START --- 线程ID[{}]", Thread.currentThread().getName());

        //条码组信息必要参数
        params.put(MesPcnExtConstWords.MODEL, oqcDataModel);

        //条码组信息
        oqcDataModel = new BuQmsOqcBySnExecAmountService().exec(params);

        log.info("BU-QMS出货检验公共方法 --- 成品出货检验 --- 获取条码组信息 SUCCESS --- result[{}] --- 线程ID[{}]", JSONObject.toJSONString(oqcDataModel), Thread.currentThread().getName());

        return oqcDataModel;
    }

    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_DATA_NOT_EXIT.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();
        }
        if (MesPcnExtEnumUtil.PRODUCE_SN_STATUS.OFFLINE.getValue() != produceSnExt.getSnStatus()) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("出货检验:产品条码[%s]的状态为[%s]",
                            serialNumber, MesPcnExtEnumUtil.PRODUCE_SN_STATUS.valueOfDescription(produceSnExt.getSnStatus()))
                    .build();
        }
        return produceSnExt;
    }

    private MesPackageDetail getPackageDetail(String organizeCode, String serialNumber) {
        MesPackageDetail packageDetail = packageExtService.getPackageDetailBySn(organizeCode, serialNumber);
        if (null == packageDetail || StringUtils.isEmpty(packageDetail.getSerialNumber())) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("出货检验:产品条码[%s]未关联包装条码信息", serialNumber)
                    .build();
        }
        return packageDetail;
    }

    private MesWorkOrder getWorkOrder(String organizeCode, MesProduceSnExt produceSnExt) {
        MesWorkOrder workOrder = workOrderExtService.getWorkOrderByOrderNo(organizeCode, produceSnExt.getLastWorkOrderNo());
        if (null == workOrder) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("出货检验:产品条码[%s]对应的工单[%s]信息不存在", produceSnExt.getSerialNumber(), produceSnExt.getLastWorkOrderNo())
                    .build();
        }
        return workOrder;
    }

    private void packOrderAndWorkTimeAndShift(SxBuOqcDataModel oqcDataModel, MesProduceSnExt produceSnExt, MesWorkOrder workOrder) {
        if (produceSnExt.getLastWorkOrderNo().equals(produceSnExt.getWorkOrderNo())) {
            oqcDataModel.setWorkTime(produceSnExt.getWorkTime());
            oqcDataModel.setShiftCode(produceSnExt.getShiftCode());
        } else {
            MesProduceSnRepair produceSnRepair = produceSnRepairService.getProduceSnRepairBySnAndOrderNo(produceSnExt.getOrganizeCode(), produceSnExt.getSerialNumber(), workOrder.getOrderNo());
            if (null == produceSnRepair) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                        .setErrorDetail("出货检验:产品条码[%s]已绑定返工工单[%s],但未查询到返工条码关联关系", produceSnExt.getSerialNumber(), workOrder.getOrderNo())
                        .build();
            }
            oqcDataModel.setWorkTime(produceSnRepair.getWorkTime());
            oqcDataModel.setShiftCode(produceSnRepair.getShiftCode());
        }

        MesShift shiftDb = shiftExtService.getShiftByShiftCodeAndCenterCode(produceSnExt.getOrganizeCode(), workOrder.getWorkCenterCode(), oqcDataModel.getShiftCode());
        if (null == shiftDb) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("出货检验:产品条码[%s]对应的班次[%s]与生产线[%s]的关联信息不存在", produceSnExt.getSerialNumber(), oqcDataModel.getShiftCode(), workOrder.getWorkCenterCode())
                    .build();
        }
        oqcDataModel.setShiftName(shiftDb.getShiftName());

        oqcDataModel.setWorkOrderType(workOrder.getWorkOrderType());
        oqcDataModel.setWorkOrderTypeName(MesPcnExtEnumUtil.WORK_ORDER_TYPE.valueOfDescription(workOrder.getWorkOrderType()));
        oqcDataModel.setWorkOrderNo(workOrder.getOrderNo());
        oqcDataModel.setPartNo(workOrder.getPartNo());
        oqcDataModel.setPartNameRdd(workOrder.getPartNameRdd());
        oqcDataModel.setWorkCenterCode(workOrder.getWorkCenterCode());
        oqcDataModel.setPlanQty(workOrder.getQty());
    }

    private MesOutPutStatistics getOutPutStatistics(SxBuOqcDataModel oqcDataModel) {
        MesOutPutStatistics outPutStatisticsDb = outPutStatisticsService.getOutPutStatisticsByTimeAndOrderNo(
                oqcDataModel.getOrganizeCode(), oqcDataModel.getWorkOrderNo(), oqcDataModel.getWorkTime(), oqcDataModel.getShiftCode());
        if (null == outPutStatisticsDb) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("出货检验:产品条码[%s]作业时间[%s]班次代码[%s]关联的%s[%s]对应的产量统计信息不存在",
                            oqcDataModel.getSerialNumber(), oqcDataModel.getWorkTime(), oqcDataModel.getShiftCode(), oqcDataModel.getWorkOrderTypeName(), oqcDataModel.getWorkOrderNo())
                    .build();
        }
        return outPutStatisticsDb;
    }

    private void packOqcManageData(SxBuOqcDataModel oqcDataModel, String packageNo, MesOutPutStatistics outPutStatisticsDb) {
        oqcDataModel.setPackageNo(packageNo);
        oqcDataModel.setCompleteQty(outPutStatisticsDb.getQty());
        oqcDataModel.setIdStr(outPutStatisticsDb.getId().toString());
    }

}
