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

import cn.estsh.i3plus.ext.mes.pcn.api.busi.IProduceSnTravelExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.jx.IJxProdBusiStrategyService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.jx.IJxProduceSnExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.jx.IJxProduceSnMcRecordService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.jx.JxProdBusiStrategyParamsBuilder;
import cn.estsh.i3plus.ext.mes.pcn.pojo.repository.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.ConvertBeanExt;
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.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.mes.model.StationRequestBean;
import cn.estsh.i3plus.pojo.mes.model.StepResult;
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.List;

/**
 * @Author: wangjie
 * @CreateDate: 2021/01/18 11:41 上午
 * @Description: 工单通用处理
 **/
@Slf4j
@Service
public class JxProdBusiStrategyCommonService implements IJxProdBusiStrategyService {

    @Autowired
    private IJxProduceSnMcRecordService produceSnMcRecordService;

    @Autowired
    private IJxProduceSnExtService produceSnExtService;

    @Autowired
    private MesProduceSnMcRecordRepository produceSnMcRecordRepository;

    @Autowired
    private MesProduceSnExtRepository produceSnExtRepository;

    @Autowired
    private IProduceSnTravelExtService produceSnTravelExtService;

    @Autowired
    private MesBadCellDetailRepository badCellDetailRepository;

    @Autowired
    private MesProdBindRecordExtRepository prodBindRecordExtRepository;

    @Autowired
    private MesRepairRecordExtRepository repairRecordExtRepository;

    @Autowired
    private MesRepairTaskRepository repairTaskRepository;

    @Override
    public StepResult checkLineOn(JxProdBusiStrategyParamsBuilder params) {
        if (MesPcnExtEnumUtil.WORK_ORDER_TYPE.REWORK_ORDER.getValue() != params.getOrderModel().getWorkOrderType()) queryBusiData4Mc(params.manageCode(params.getScanInfo()));
        else queryProduceSnInfo(params.productSn(params.getScanInfo())).scanName();
        return StepResult.getSuccessComplete();
    }

    @Override
    public JxProdBusiStrategyParamsBuilder queryBusiData4Mc(JxProdBusiStrategyParamsBuilder params) {

        queryManageCodeInfo(params.manageCode(params.getScanInfo()));

        if (null == params.getManageCodeDb()) params.productSn(params.getScanInfo());

        queryProduceSnInfo(params);

        return params.scanName();

    }

    @Override
    public JxProdBusiStrategyParamsBuilder queryBusiData4Ps(JxProdBusiStrategyParamsBuilder params) {

        queryProduceSnInfo(params.productSn(params.getScanInfo()));

        if (null == params.getProduceSnExtDb()) params.manageCode(params.getScanInfo());

        queryManageCodeInfo(params);

        return params.scanName();

    }

    @Override
    public JxProdBusiStrategyParamsBuilder queryManageCodeInfo(JxProdBusiStrategyParamsBuilder params) {

        if (StringUtils.isEmpty(params.getManageCode())) return params;

        MesManageCode manageCodeDb = produceSnMcRecordService.getManageCodeDb(params.getOrganizeCode(), params.getManageCode(), params.getWorkCenterCode());

        if (null == manageCodeDb) return params.manageCode();

        MesProduceSnMcRecord produceSnMcRecordDb = produceSnMcRecordService.getProduceSnMcRecordDb(params.getOrganizeCode(), params.getManageCode());

        if (null != produceSnMcRecordDb) params.produceSnMcRecordDb(produceSnMcRecordDb).sn(produceSnMcRecordDb.getSerialNumber(), produceSnMcRecordDb.getProductSn());

        return params.manageCodeDb(manageCodeDb);
    }

    @Override
    public JxProdBusiStrategyParamsBuilder queryProduceSnInfo(JxProdBusiStrategyParamsBuilder params) {

        if (StringUtils.isEmpty(params.getSerialNumber()) && StringUtils.isEmpty(params.getProductSn())) return params;

        MesProduceSnExt produceSnExtDb = produceSnExtService.getProduceSnExtDb(params.getOrganizeCode(), params.getSerialNumber(), params.getProductSn());

        if (null == produceSnExtDb) return params.sn();

        return params.produceSnExtDb(produceSnExtDb).sn(produceSnExtDb.getSerialNumber(), produceSnExtDb.getProductSn()).manageCode(produceSnExtDb.getTrayNo());

    }

    @Override
    public Integer queryOrderBindedQty(JxProdBusiStrategyParamsBuilder params) {
        List<MesProduceSnMcRecord> produceSnMcRecordList = produceSnMcRecordService.getProduceSnMcRecordDbList(params.getOrganizeCode(), params.getOrderModel().getOrderNo());
        return CollectionUtils.isEmpty(produceSnMcRecordList) ? MesPcnExtConstWords.ZERO : produceSnMcRecordList.size();
    }

    @Override
    public void insertProduceSnMcRecord(JxProdBusiStrategyParamsBuilder params) {
        MesProduceSnMcRecord produceSnMcRecord = new MesProduceSnMcRecord();
        produceSnMcRecord.setManageCode(params.getManageCode());
        produceSnMcRecord.setSerialNumber(params.getSerialNumber());
        produceSnMcRecord.setPartNo(params.getOrderModel().getPartNo());
        produceSnMcRecord.setPartNameRdd(params.getOrderModel().getPartNameRdd());
        produceSnMcRecord.setWorkCenterCode(params.getWorkCenterCode());
        produceSnMcRecord.setWorkOrderNo(params.getOrderModel().getOrderNo());
        produceSnMcRecord.setSnStatus(MesPcnExtEnumUtil.MC_RECORD_SN_STATUS.LINE_ON.getValue());
        produceSnMcRecord.setLineOnStatus(MesPcnExtEnumUtil.MC_RECORD_LINE_ON_STATUS.FALSE.getValue());
        produceSnMcRecord.setQcStatus(MesPcnExtEnumUtil.MC_RECORD_QC_STATUS.TRUE.getValue());
        produceSnMcRecord.setOrganizeCode(params.getOrganizeCode());
        produceSnMcRecord.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        ConvertBean.serviceModelInitialize(produceSnMcRecord, params.getUserInfo());
        params.produceSnMcRecordDb(produceSnMcRecordRepository.insert(produceSnMcRecord));
    }

    @Override
    public StepResult execLineOnComplete(JxProdBusiStrategyParamsBuilder params) {

        StepResult stepResult = saveProduceSn4LineOn(params);

        if (!stepResult.isCompleted()) return stepResult;

        StepResult result = saveProduceSnMcRecord4LineOn(params);

        if (!result.isCompleted()) return result;

        insertProduceSnTravel(params);

        return stepResult;

    }

    private StepResult saveProduceSn4LineOn(JxProdBusiStrategyParamsBuilder params) {

        StepResult stepResult = StepResult.getSuccessComplete();

        if (StringUtils.isEmpty(params.getSerialNumber()) && StringUtils.isEmpty(params.getProductSn())) return stepResult;

        String serialNumber = params.getSerialNumber();
        String productSn = params.getProductSn();

        queryProduceSnInfo(params);

        MesProduceSnExt produceSnExtDb = params.getProduceSnExtDb();

        if (null == produceSnExtDb) return stepResult.isCompleted(false).msg(String.format("过程条码[%s]产品条码[%s]对应的信息不存在!", serialNumber, productSn));

        if (MesPcnExtEnumUtil.SN_OPERATE_TYPE.REPAIR.getValue() == produceSnExtDb.getOperateType()) return stepResult.isCompleted(false).msg(String.format("过程条码[%s]产品条码[%s]对应的信息当前业务状态[返修]!", params.getSerialNumber(), params.getProductSn()));

        if (MesPcnExtEnumUtil.PRODUCE_SN_STATUS.PROCESS.getValue() <= produceSnExtDb.getSnStatus()) return stepResult;

        produceSnExtDb.setSnStatus(MesPcnExtEnumUtil.PRODUCE_SN_STATUS.PROCESS.getValue());
        produceSnExtService.doPackSnExtProcess((StationRequestBean) params.getObj(), produceSnExtDb);
        ConvertBean.serviceModelUpdate(produceSnExtDb, params.getUserInfo());
        produceSnExtDb.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        new ConvertBeanExt(produceSnExtDb).convertBean(produceSnExtDb);

        params.produceSnExtDb(produceSnExtRepository.save(produceSnExtDb));

        return stepResult;

    }

    private StepResult saveProduceSnMcRecord4LineOn(JxProdBusiStrategyParamsBuilder params) {

        StepResult stepResult = StepResult.getSuccessComplete();

        if (StringUtils.isEmpty(params.getManageCode()) || !params.getManageCode().contains(MesPcnExtConstWords.AND)) return stepResult;

        String[] manageCodeArr = params.getManageCode().split(MesPcnExtConstWords.AND);

        MesProduceSnMcRecord produceSnMcRecordDb = produceSnMcRecordRepository.getById(Long.parseLong(manageCodeArr[1]));

        if (null == produceSnMcRecordDb) return stepResult.isCompleted(false).msg(String.format("管理编码[%s]ID[%s]对应的管理编码与工单条码关系信息不存在!", manageCodeArr[0], manageCodeArr[1]));

        if (MesPcnExtEnumUtil.SN_OPERATE_TYPE.REPAIR.getValue() == produceSnMcRecordDb.getOperateType()) return stepResult.isCompleted(false).msg(String.format("管理编码[%s]ID[%s]对应的管理编码与工单条码关系信息当前业务状态[返修]!", manageCodeArr[0], manageCodeArr[1]));

        if (MesPcnExtEnumUtil.MC_RECORD_LINE_ON_STATUS.TRUE.getValue() == produceSnMcRecordDb.getLineOnStatus()) return stepResult;

        produceSnMcRecordDb.setLineOnStatus(MesPcnExtEnumUtil.MC_RECORD_LINE_ON_STATUS.TRUE.getValue());
        ConvertBean.serviceModelUpdate(produceSnMcRecordDb, params.getUserInfo());
        produceSnMcRecordDb.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        produceSnMcRecordRepository.save(produceSnMcRecordDb);

        return stepResult;
    }

    @Override
    public void insertProduceSnTravel(JxProdBusiStrategyParamsBuilder params) {
        if (null == params.getProduceSnExtDb()) return;
        produceSnTravelExtService.insertProduceSnTravelExt(params.getProduceSnExtDb());
    }

    @Override
    public StepResult execLineOnBindMc(JxProdBusiStrategyParamsBuilder params) { return StepResult.getSuccessComplete(); }

    @Override
    public StepResult checkFinalInspection(JxProdBusiStrategyParamsBuilder params) {
        if (MesPcnExtEnumUtil.WORK_ORDER_TYPE.REWORK_ORDER.getValue() != params.getOrderModel().getWorkOrderType()) queryBusiData4Mc(params.manageCode(params.getScanInfo()));
        else queryProduceSnInfo(params.productSn(params.getScanInfo())).scanName();
        return StepResult.getSuccessComplete();
    }

    @Override
    public StepResult checkThirdPartyPs(JxProdBusiStrategyParamsBuilder params) { return StepResult.getSuccessComplete(); }

    @Override
    public void execFinalInspectionBindPs(JxProdBusiStrategyParamsBuilder params) {

        saveProduceSnMcRecord4FinalInspection(params);

        saveProduceSn4FinalInspection(params);

        doRestoreBusiData(params);

        insertProduceSnTravel(params);

    }

    private void saveProduceSnMcRecord4FinalInspection(JxProdBusiStrategyParamsBuilder params) {

        if (StringUtils.isEmpty(params.getManageCode()) || !params.getManageCode().contains(MesPcnExtConstWords.AND)) return;

        String[] manageCodeArr = params.getManageCode().split(MesPcnExtConstWords.AND);

        MesProduceSnMcRecord produceSnMcRecordDb = produceSnMcRecordRepository.getById(Long.parseLong(manageCodeArr[1]));

        produceSnMcRecordDb.setSnStatus(MesPcnExtEnumUtil.MC_RECORD_SN_STATUS.LINE_OFF.getValue());
        if (StringUtils.isEmpty(produceSnMcRecordDb.getSerialNumber())) produceSnMcRecordDb.setSerialNumber(params.getProduceSnExtDb().getSerialNumber());
        if (StringUtils.isEmpty(produceSnMcRecordDb.getProductSn())) produceSnMcRecordDb.setProductSn(params.getScanInfo());
        ConvertBean.serviceModelUpdate(produceSnMcRecordDb, params.getUserInfo());
        produceSnMcRecordDb.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());

        params.produceSnMcRecordDb(produceSnMcRecordRepository.save(produceSnMcRecordDb)).manageCode(produceSnMcRecordDb.getManageCode());

    }

    private void saveProduceSn4FinalInspection(JxProdBusiStrategyParamsBuilder params) {

        MesProduceSnExt produceSnExtDb = null == params.getProduceSnExtDb() ? queryProduceSnInfo(params).getProduceSnExtDb() : params.getProduceSnExtDb();

        if (StringUtils.isEmpty(produceSnExtDb.getProductSn())) produceSnExtDb.setProductSn(params.getScanInfo());
        if (StringUtils.isEmpty(produceSnExtDb.getTrayNo())) produceSnExtDb.setTrayNo(params.getManageCode());
        if (MesPcnExtEnumUtil.PRODUCE_SN_QC_STATUS.QUALIFIED.getValue() != produceSnExtDb.getQcStatus()) produceSnExtDb.setQcStatus(MesPcnExtEnumUtil.PRODUCE_SN_QC_STATUS.QUALIFIED.getValue());

        produceSnExtService.doPackSnExtProcess((StationRequestBean) params.getObj(), produceSnExtDb);
        ConvertBean.serviceModelUpdate(produceSnExtDb, params.getUserInfo());
        produceSnExtDb.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        new ConvertBeanExt(produceSnExtDb).convertBean(produceSnExtDb);

        params.produceSnExtDb(produceSnExtRepository.save(produceSnExtDb));

    }

    private void doRestoreBusiData(JxProdBusiStrategyParamsBuilder params) {

        if (null == params.getProduceSnMcRecordDb()) return;

        doRestoreProdBindRecord(params);

        if (!doRestoreBadCellDetail(params)) return;

        doRestoreRepairRecord(params);

        doRestoreRepairTask(params);

    }

    private void doRestoreProdBindRecord(JxProdBusiStrategyParamsBuilder params) {

        if (null == params.getProduceSnMcRecordDb()) return;

        List<MesProdBindRecordExt> prodBindRecordExtList = prodBindRecordExtRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.THIRD_PARTY_PID},
                new Object[]{params.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), params.getProduceSnMcRecordDb().getId().toString()});

        if (CollectionUtils.isEmpty(prodBindRecordExtList)) return;

        for (MesProdBindRecordExt item : prodBindRecordExtList) {
            if (null == item) continue;

            if (!StringUtils.isEmpty(item.getSerialNumber()) && !StringUtils.isEmpty(item.getProductSn())) continue;
            item.setSerialNumber(params.getProduceSnMcRecordDb().getSerialNumber());
            item.setProductSn(params.getProduceSnMcRecordDb().getProductSn());
            ConvertBean.serviceModelUpdate(item, params.getUserInfo());
            new ConvertBeanExt(item).convertBean(item);
            prodBindRecordExtRepository.save(item);
        }

    }

    private Boolean doRestoreBadCellDetail(JxProdBusiStrategyParamsBuilder params) {

        if (null == params.getProduceSnMcRecordDb()) return false;

        List<MesBadCellDetail> badCellDetailList = badCellDetailRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.THIRD_PARTY_PID},
                new Object[]{params.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), params.getProduceSnMcRecordDb().getId().toString()});

        if (CollectionUtils.isEmpty(badCellDetailList)) return false;

        Boolean result = false;
        for (MesBadCellDetail item : badCellDetailList) {
            if (null == item) continue;

            if (!StringUtils.isEmpty(item.getSerialNumber()) && !StringUtils.isEmpty(item.getProductSn())) continue;
            item.setSerialNumber(params.getProduceSnMcRecordDb().getSerialNumber());
            item.setProductSn(params.getProduceSnMcRecordDb().getProductSn());
            ConvertBean.serviceModelUpdate(item, params.getUserInfo());
            badCellDetailRepository.save(item);

            result = true;
        }

        return result;
    }

    private void doRestoreRepairRecord(JxProdBusiStrategyParamsBuilder params) {

        if (null == params.getProduceSnMcRecordDb()) return;

        List<MesRepairRecordExt> repairRecordExtList = repairRecordExtRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.THIRD_PARTY_PID},
                new Object[]{params.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), params.getProduceSnMcRecordDb().getId().toString()});

        if (CollectionUtils.isEmpty(repairRecordExtList)) return;

        for (MesRepairRecordExt item : repairRecordExtList) {
            if (null == item) continue;

            if (!StringUtils.isEmpty(item.getSerialNumber()) && !StringUtils.isEmpty(item.getProductSn())) continue;
            item.setSerialNumber(params.getProduceSnMcRecordDb().getSerialNumber());
            item.setProductSn(params.getProduceSnMcRecordDb().getProductSn());
            ConvertBean.serviceModelUpdate(item, params.getUserInfo());
            repairRecordExtRepository.save(item);
        }

    }

    private void doRestoreRepairTask(JxProdBusiStrategyParamsBuilder params) {

        if (null == params.getProduceSnMcRecordDb()) return;

        List<MesRepairTask> repairTaskList = repairTaskRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.THIRD_PARTY_PID},
                new Object[]{params.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), params.getProduceSnMcRecordDb().getId().toString()});

        if (CollectionUtils.isEmpty(repairTaskList)) return;

        for (MesRepairTask item : repairTaskList) {
            if (null == item) continue;

            if (!StringUtils.isEmpty(item.getSerialNumber()) && !StringUtils.isEmpty(item.getProductSn())) continue;
            item.setSerialNumber(params.getProduceSnMcRecordDb().getSerialNumber());
            item.setProductSn(params.getProduceSnMcRecordDb().getProductSn());
            ConvertBean.serviceModelUpdate(item, params.getUserInfo());
            repairTaskRepository.save(item);
        }

    }

    @Override
    public void execFinalInspectionMarkRepair(JxProdBusiStrategyParamsBuilder params) {

        saveProduceSn4MarkRepair(params);

        saveProduceSnMcRecord4MarkRepair(params);

        insertProduceSnTravel(params);

    }

    private void saveProduceSn4MarkRepair(JxProdBusiStrategyParamsBuilder params) {

        if (StringUtils.isEmpty(params.getSerialNumber()) && StringUtils.isEmpty(params.getProductSn())) return;

        queryProduceSnInfo(params);

        MesProduceSnExt produceSnExtDb = params.getProduceSnExtDb();

        produceSnExtDb.setOperateType(MesPcnExtEnumUtil.SN_OPERATE_TYPE.REPAIR.getValue());
        produceSnExtService.clearProduceSnProcess(produceSnExtDb);
        ConvertBean.serviceModelUpdate(produceSnExtDb, params.getUserInfo());
        produceSnExtDb.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        new ConvertBeanExt(produceSnExtDb).convertBean(produceSnExtDb);

        params.produceSnExtDb(produceSnExtRepository.save(produceSnExtDb));

    }

    private void saveProduceSnMcRecord4MarkRepair(JxProdBusiStrategyParamsBuilder params) {

        if (StringUtils.isEmpty(params.getManageCode()) || !params.getManageCode().contains(MesPcnExtConstWords.AND)) return;

        String[] manageCodeArr = params.getManageCode().split(MesPcnExtConstWords.AND);

        MesProduceSnMcRecord produceSnMcRecordDb = produceSnMcRecordRepository.getById(Long.parseLong(manageCodeArr[1]));

        produceSnMcRecordDb.setOperateType(MesPcnExtEnumUtil.SN_OPERATE_TYPE.REPAIR.getValue());

        ConvertBean.serviceModelUpdate(produceSnMcRecordDb, params.getUserInfo());
        produceSnMcRecordDb.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        produceSnMcRecordRepository.save(produceSnMcRecordDb);

    }

}