package com.foreverwin.mesnac.production.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.foreverwin.mesnac.common.constant.Constants;
import com.foreverwin.mesnac.common.dto.SfcDispatchDto;
import com.foreverwin.mesnac.common.enums.HandleEnum;
import com.foreverwin.mesnac.common.service.CommonService;
import com.foreverwin.mesnac.common.service.InspectionTaskService;
import com.foreverwin.mesnac.common.service.SfcDispatchCommonService;
import com.foreverwin.mesnac.common.util.ExceptionUtil;
import com.foreverwin.mesnac.common.util.StringUtil;
import com.foreverwin.mesnac.meapi.dto.RouterStepDto;
import com.foreverwin.mesnac.meapi.dto.SfcDto;
import com.foreverwin.mesnac.meapi.model.Router;
import com.foreverwin.mesnac.meapi.model.Sfc;
import com.foreverwin.mesnac.meapi.service.OperationService;
import com.foreverwin.mesnac.meapi.service.RouterService;
import com.foreverwin.mesnac.meapi.service.RouterStepService;
import com.foreverwin.mesnac.meapi.service.SfcService;
import com.foreverwin.mesnac.production.dto.SplitSfcDto;
import com.foreverwin.mesnac.production.mapper.SfcCrossMapper;
import com.foreverwin.mesnac.production.mapper.SplitSfcMapper;
import com.foreverwin.mesnac.production.model.SplitSfc;
import com.foreverwin.mesnac.production.model.StepOperation;
import com.foreverwin.mesnac.production.service.SfcCrossService;
import com.foreverwin.mesnac.production.service.SplitSfcService;
import com.foreverwin.modular.core.exception.BaseException;
import com.foreverwin.modular.core.meext.MEServices;
import com.foreverwin.modular.core.util.CommonMethods;
import com.foreverwin.modular.core.util.FrontPage;
import com.sap.me.nonconformance.*;
import com.sap.me.production.*;
import com.sap.me.status.StatusBOHandle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 产品条码拆分表 服务实现类
 * </p>
 *
 * @author Philip
 * @since 2021-07-20
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class SplitSfcServiceImpl extends ServiceImpl<SplitSfcMapper, SplitSfc> implements SplitSfcService {


    @Autowired
    private SplitSfcMapper splitSfcMapper;
    @Autowired
    private SfcDispatchCommonService sfcDispatchCommonService;
    @Autowired
    private InspectionTaskService inspectionTaskService;
    @Autowired
    private OperationService operationService;
    @Autowired
    private SfcCrossMapper sfcCrossMapper;
    @Autowired
    private RouterService routerService;
    @Autowired
    private SfcService sfcService;
    @Autowired
    private SfcCrossService sfcCrossService;
    @Autowired
    private RouterStepService routerStepService;
    @Autowired
    private CommonService commonService;
    @Override
    public IPage<SplitSfc> selectPage(FrontPage<SplitSfc> frontPage, SplitSfc splitSfc) {
        QueryWrapper<SplitSfc> queryWrapper = new QueryWrapper<>();
        queryWrapper.setEntity(splitSfc);
        return super.page(frontPage.getPagePlus(), queryWrapper);
    }

    @Override
    public List<SplitSfc> selectList(SplitSfc splitSfc) {
        QueryWrapper<SplitSfc> queryWrapper = new QueryWrapper<>();
        queryWrapper.setEntity(splitSfc);
        return super.list(queryWrapper);
    }

    @Override
    public SfcDto getSfcData(SfcDto dto) {
        String site = CommonMethods.getSite();
        String handle = HandleEnum.SFC.getHandle(site, dto.getSfc());
        if (StringUtil.isBlank(dto.getSfc())){
            throw new BaseException("产品条码不能为空");
        }
        if (StringUtil.isBlank(dto.getAbnormalNo())){
            throw new BaseException("异常单号不能为空");
        }
        //根据sfc找工单等信息
        SfcDto sfcData = splitSfcMapper.getSfcData(handle);
        if (sfcData==null){
            Sfc sfcServiceById = sfcService.getById(handle);
            if (!sfcServiceById.getStatusBo().equals(HandleEnum.STATUS.getHandle(site,"405"))){
                throw new BaseException("未找到产品条码信息");
            }
            sfcData= splitSfcMapper.getCompleteSfcData(handle).get(0);
        }
        String stepId = sfcData.getStepId();
        //查询质量异常记录数量
        SplitSfcDto sfcDto=splitSfcMapper.getAbnormalQty(site,dto.getSfc(),dto.getAbnormalNo());
        if (sfcDto==null){
            throw new BaseException("未找到闭环关闭的质量异常");
        }
        if(StringUtil.isBlank(sfcDto.getNcQty())){
            throw new BaseException("质量异常提报不良品数量为空，不能拆分");
        }
        sfcData.setQty(Double.valueOf(sfcDto.getNcQty()));
        sfcData.setAbnormalNo(sfcDto.getAbnormalNo());
        return sfcData;
    }
    @Override
    public SfcDto getGoodSfcData(String sfc) {
        String site = CommonMethods.getSite();
        String handle = HandleEnum.SFC.getHandle(site, sfc);
        //根据sfc找工单等信息
        SfcDto sfcData = splitSfcMapper.getSfcData(handle);
        if (sfcData==null){
            throw new BaseException("未找到产品条码信息");
        }
        if (!sfcData.getStatus().equals("401")&&!sfcData.getStatus().equals("402")){
            throw new BaseException("产品状态不可拆分");
        }
        if (sfcData.getQty()==1){
            throw new BaseException("数量为1不可拆分");
        }
        return sfcData;
    }
    @Override
    public SplitSfc goodSfcSplit(SfcDto sfcDto){
        String site = CommonMethods.getSite();
        String sfc = sfcDto.getSfc();
        BigDecimal splitQty = new BigDecimal(sfcDto.getQty());

        //根据sfc找工单等信息
        SfcDto sfcData =getGoodSfcData(sfc);
        if (sfcData==null){
            throw new BaseException("未找到产品条码信息");
        }
        String operation = sfcData.getOperation();
        SplitSfcRequest splitSfcRequest=new SplitSfcRequest();
        try {
            SplitSerializeServiceInterface splitService =  MEServices.create("com.sap.me.production", "SplitSerializeService",site);
            //拆sfc
            List<SplitSfcDetail> newList=new ArrayList<>();
            SplitSfcDetail splitDetail=new SplitSfcDetail();
            splitDetail.setQuantity(splitQty);
            newList.add(splitDetail);
            splitSfcRequest.setNewSfcList(newList);
            splitSfcRequest.setSfcRef(HandleEnum.SFC.getHandle(site,sfc));
            Collection<SplitSfcResponse> splitSfcResponses = splitService.splitSfc(splitSfcRequest);
            SplitSfcResponse splitSfcResponse = splitSfcResponses.iterator().next();
            String newSfcRef = splitSfcResponse.getNewSfcRef();

            SplitSfc splitSfc=new SplitSfc();
            String newSfc = StringUtil.trimHandle(newSfcRef);
            splitSfc.setHandle(HandleEnum.SPLIT_SFC.getHandle(site,newSfc));
            splitSfc.setSite(site);
            splitSfc.setSfc(sfc);
            splitSfc.setSplitSfc(newSfc);
            splitSfc.setSplitQty(splitQty);
            splitSfc.setCreateUser(CommonMethods.getUser());
            splitSfc.setCreatedDateTime(LocalDateTime.now());
            save(splitSfc);
            Router routerBySfcBo = routerService.getRouterBySfcBo(HandleEnum.SFC.getHandle(site, sfc));
            sfcDispatchCommonService.saveSplitSfcDispatch(site, CommonMethods.getUser(), "N", sfcData.getShopOrder(), sfc, operation, sfcData.getStepId(),newSfc, routerBySfcBo.getHandle(),sfcData.getStepSequence());
            return splitSfc;
        } catch (Exception e) {
            ExceptionUtil.throwException(e);
        }
        return null;
    }
    @Override
    public SplitSfc splitSfc(SfcDto sfcDto){
        String site = CommonMethods.getSite();
        String sfc = sfcDto.getSfc();
        String abnormalNo = sfcDto.getAbnormalNo();
        if (StringUtil.isBlank(abnormalNo)){
            throw new BaseException("异常单号不能为空");
        }
        String handle = HandleEnum.SFC.getHandle(site, sfc);
        BigDecimal splitQty = new BigDecimal(sfcDto.getQty());

        //根据sfc找工单等信息
        SfcDto sfcData = splitSfcMapper.getSfcData(handle);
        String operation ;
        BigDecimal qty ;
        String shopOrder;
        String stepId;
        String stepSequence;
        String resrce = null;
        boolean isComplete=false;
        String routerBoBySfc = null;
        String sfcRouterRef = null;
        if (sfcData==null){
            Sfc sfcServiceById = sfcService.getById(handle);
            if (!sfcServiceById.getStatusBo().equals(new StatusBOHandle(site,"405").getValue())){
                throw new BaseException("未找到产品条码信息");
            }
            StepOperation lastStep = sfcCrossMapper.findRouterLastOperationByRouterBo(handle).get(0);
            qty=new BigDecimal(sfcServiceById.getQty().toString());
            operation = StringUtil.trimHandle(lastStep.getOperationBo());
            shopOrder=StringUtil.trimHandle(sfcServiceById.getShopOrderBo());
            stepId=lastStep.getStepId();
            stepSequence= String.valueOf(lastStep.getSequence());
            routerBoBySfc=lastStep.getRouterBo();
            sfcRouterRef=lastStep.getHandle();
            resrce= lastStep.getResrce();
            isComplete=true;
        }else {
            qty= BigDecimal.valueOf(sfcData.getQty());
            operation = sfcData.getOperation();
            shopOrder=sfcData.getShopOrder();
            stepId=sfcData.getStepId();
            stepSequence=sfcData.getStepSequence();
        }

        //查询质量异常记录数量 处置工艺路线及不良代码
        SplitSfcDto splitSfcDto=splitSfcMapper.getAbnormalQty(site,sfc, abnormalNo);
        SfcDispatchDto sfcDispatchDto = new SfcDispatchDto();
        sfcDispatchDto.setSite(site);
        sfcDispatchDto.setSfc(sfc);
        sfcDispatchDto.setStepId(splitSfcDto.getStepId());
        SfcDispatchDto sfcDispatchBySfc = sfcDispatchCommonService.findSfcDispatchBySfc(sfcDispatchDto);
        if (sfcDispatchBySfc==null){
            throw new BaseException("未找到派工任务");
        }
        String routerBo = splitSfcDto.getRouterBo();
        String ncCode = splitSfcDto.getNcCode();
        String abnormalMethod = splitSfcDto.getAbnormalMethod();
        if (StringUtil.isBlank(ncCode)){
            throw new BaseException("异常处置未选择不良代码");
        }
        BigDecimal sfcQty = qty;
        if (new BigDecimal(splitSfcDto.getNcQty()).compareTo(sfcQty)>=0){
            throw new BaseException("质量异常数量大于等于于产品条码的数量，不能拆分");
        }
        if (splitQty.compareTo(new BigDecimal(splitSfcDto.getNcQty()))>0){
            throw new BaseException("拆分数量大于质量异常数量的数量，不能拆分");
        }
        String[] splitNcCode = ncCode.split(",");

        SplitSfcRequest splitSfcRequest=new SplitSfcRequest();
        try {
            SplitSerializeServiceInterface splitService =  MEServices.create("com.sap.me.production", "SplitSerializeService",site);
            if (isComplete){
                //修改状态
                updateStatus(site,handle,HandleEnum.STATUS.getHandle(site,"402"));
               //调整步骤
                splitSfcMapper.updateSfcRouterInUse(sfcRouterRef,"true","false");
                placeInQueueAtStep(site, handle, routerBoBySfc, HandleEnum.OPERATION.getHandle(site,operation), sfcRouterRef, qty, stepId);

            }
            //拆sfc
            List<SplitSfcDetail> newList=new ArrayList<>();
            SplitSfcDetail splitDetail=new SplitSfcDetail();
            splitDetail.setQuantity(splitQty);
            newList.add(splitDetail);
            splitSfcRequest.setNewSfcList(newList);
            splitSfcRequest.setSfcRef(HandleEnum.SFC.getHandle(site,sfc));
            Collection<SplitSfcResponse> splitSfcResponses = splitService.splitSfc(splitSfcRequest);
            SplitSfcResponse splitSfcResponse = splitSfcResponses.iterator().next();
            String newSfcRef = splitSfcResponse.getNewSfcRef();
            String newSfc = StringUtil.trimHandle(newSfcRef);
            if (isComplete){
                //修改状态
                updateStatus(site,handle,HandleEnum.STATUS.getHandle(site,"405"));
                 splitSfcMapper.updateSfcRouterInUse(sfcRouterRef,"false","true");
                //Operation currentRevisionRef = operationService.getCurrentRevisionRef(site, operation);
                //sfcCrossService.passAction(site,currentRevisionRef.getHandle(),resrce,handle,null);
                //修改库存数量
                commonService.updateInventory(site,sfc,qty.subtract(splitQty));
            }
            if(abnormalMethod.equals("F")&&StringUtil.notBlank(routerBo)){
                //记录不合格和处置
                recordNc(site, shopOrder, sfc, operation, stepId, newSfc, stepSequence, splitQty, newSfcRef, splitNcCode, routerBo);
             }
            //创建专检任务
            Map<String, Object> paramMap=new HashMap<>();
            paramMap.put("CATEGORY", Constants.INSPECTION_TYPE_P);
            paramMap.put("SFC",sfc );
            paramMap.put("SHOP_ORDER",sfcDispatchBySfc.getShopOrder());
            paramMap.put("OPERATION",sfcDispatchBySfc.getOperation());
            paramMap.put("STEP_ID",sfcDispatchBySfc.getStepId());
            paramMap.put("WORK_CENTER",sfcDispatchBySfc.getWorkCenter());
            paramMap.put("RESRCE",sfcDispatchBySfc.getResrce());
            paramMap.put("SFC_DISPATCH_DETAIL_BO",sfcDispatchBySfc.getHandle());
            inspectionTaskService.createNewTask(paramMap);
            SplitSfc splitSfc=new SplitSfc();
            splitSfc.setHandle(HandleEnum.SPLIT_SFC.getHandle(site,newSfc));
            splitSfc.setSite(site);
            splitSfc.setSfc(sfc);
            splitSfc.setSplitSfc(newSfc);
            splitSfc.setSplitQty(splitQty);
            splitSfc.setRouter(StringUtil.trimHandle(routerBo));
            splitSfc.setCreateUser(CommonMethods.getUser());
            splitSfc.setCreatedDateTime(LocalDateTime.now());
            save(splitSfc);
            return splitSfc;
        } catch (Exception e) {
            ExceptionUtil.throwException(e);
        }
        return null;
    }

    private void updateStatus(String site,String sfcBo,String statusBo) throws Exception {
        SfcStateServiceInterface sfcStateServiceInterface = MEServices.create("com.sap.me.production", "SfcStateService", site);
        UpdateSfcStatusRequest updateSfcStatusRequest = new UpdateSfcStatusRequest();
        updateSfcStatusRequest.setSfcRef(sfcBo);
        updateSfcStatusRequest.setStatusRef(statusBo);
        sfcStateServiceInterface.updateSfcStatus(updateSfcStatusRequest);
    }

    private void placeInQueueAtStep(String site, String sfcRef, String routerRef, String operationRef, String sfcRouterRef, BigDecimal qty, String stepId) throws Exception {
        SfcRoutingServiceInterface sfcRoutingService =  MEServices.create("com.sap.me.production", "SfcRoutingService",site);
        PlaceInQueueAtStepRequest request=new PlaceInQueueAtStepRequest();
        request.setSfcRef(sfcRef);
        request.setPlacementRouterRef(routerRef);
        request.setPlacementOperationRef(operationRef);
        request.setOperationSelectionType(OperationSelectionType.CURRENT_OPERATION);
        request.setPlacementSfcRouterRef(sfcRouterRef);
        request.setQuantity(qty);
        request.setPlacementStepId(stepId);
        sfcRoutingService.placeInQueueAtStep(request);
    }

    private void recordNc(String site, String shopOrder, String sfc, String operation, String stepId, String newSfc, String stepSequence, BigDecimal splitQty, String newSfcRef, String[] splitNcCode, String routerBo) throws Exception {
        NCProductionServiceInterface ncProductionService =  MEServices.create("com.sap.me.nonconformance", "NCProductionService",site);

        //记录不合格
        CreateNCRequest createNCRequest=new CreateNCRequest();
        createNCRequest.setQty(splitQty);
        createNCRequest.setSfcRef(newSfcRef);
        ProductionContext productionContext=new ProductionContext();
        StepIdentifier stepIdentifier=new StepIdentifier();
        stepIdentifier.setStepId(stepId);
        stepIdentifier.setOperationId(operation);
        productionContext.setStepIdentifier(stepIdentifier);
        String resrceBo = commonService.getResrceByOperation(operation);
        productionContext.setResourceRef(resrceBo);
        createNCRequest.setProdCtx(productionContext);
        createNCRequest.setNcCodeRef(HandleEnum.NC_CODE.getHandle(site,splitNcCode[0]));
        ncProductionService.createNC(createNCRequest);
        //不合格处置特殊工艺路线
        DispositionMultipleSfcsRequest dispositionSfcsRequest=new DispositionMultipleSfcsRequest();
        List<String> sfcs=new ArrayList<>();
        sfcs.add(newSfcRef);
        dispositionSfcsRequest.setSfcs(sfcs);
        dispositionSfcsRequest.setBypassStepValidation(true);
        DispositionSelection dispositionSelection=new DispositionSelection();
        Router maxRevisionRouter = routerService.getMaxRevisionRouter(site, StringUtil.trimHandle(routerBo));
        dispositionSelection.setRouterRef(maxRevisionRouter.getHandle());
        dispositionSfcsRequest.setDispositionSelection(dispositionSelection);
        dispositionSfcsRequest.setProdCtx(new ProductionContext());
        ncProductionService.dispositionMultipleSfcs(dispositionSfcsRequest);
        List<RouterStepDto> routerOperationByRouterBo = routerStepService.findRouterOperationByRouterBo(site, maxRevisionRouter.getHandle());
        if (routerOperationByRouterBo.isEmpty()){
            throw new BaseException("处置工艺路线没有步骤");
        }
        sfcDispatchCommonService.saveSplitSfcDispatch(site, CommonMethods.getUser(),"R", shopOrder, sfc, operation, stepId, newSfc, maxRevisionRouter.getHandle(), stepSequence);
    }

}