package nc.bs.ic.m45.update;

import nc.bs.ic.general.rule.after.AtpAfterUpdate;
import nc.bs.ic.general.rule.before.CtplcustomeridCheck;
import nc.bs.ic.general.update.IUpdateBP;
import nc.bs.ic.general.update.UpdateBPTemplate;
import nc.bs.ic.m45.base.BPPlugInPoint;
import nc.bs.ic.m45.base.rule.FillCostOrgRule;
import nc.bs.ic.m45.base.rule.PurchaseBillCheckRule;
import nc.bs.ic.m45.base.rule.PurchaseInAssetWarehouseCheck;
import nc.bs.ic.m45.base.rule.PurchaseInVOScaleCheckRule;
import nc.bs.ic.m45.base.rule.PurchaseinRetMarginProcess;
import nc.bs.ic.m45.base.rule.PurchaseinRetMarginProcessFor5805;
import nc.bs.ic.m45.base.rule.ReturnSnIsExistInEquipcardCheck;
import nc.bs.ic.m45.base.rule.VmiCheckRule;
import nc.bs.ic.m45.insert.rule.InsertCheckMaterialUnit;
import nc.bs.ic.m45.insert.rule.M45SaveAndRewriteCTPayPlan;
import nc.bs.ic.m45.insert.rule.PurchaseInProjectRule;
import nc.bs.ic.m45.update.rule.FeeDetailUpdate;
import nc.bs.ic.m45.update.rule.IsRedBookThroughUpdate;
import nc.bs.ic.m45.update.rule.UpdReWritePIM;
import nc.bs.ic.m45.update.rule.UpdateNumCheck;
import nc.bs.ic.m45.update.rule.UpdateRedReturnInRewriteRule;
import nc.bs.ic.m45.update.rule.UpdateRewriteITRule;
import nc.bs.ic.m45.update.rule.UpdateRewritePORule;
import nc.bs.ic.m45.update.rule.UpdateRewritePayPlanConfirmDataRule;
import nc.bs.ic.m45.update.rule.UpdateRewritePayPlanConfirmInvoicenumRule;
import nc.bs.ic.pub.base.ICCompareAroundProcesser;
import nc.bs.ic.pub.base.IUpdateRuleProvider;
import nc.bs.ic.pub.util.SagasUtils;
import nc.bs.scmpub.rule.VOSagaFrozenValidateRule;
import nc.impl.pubapp.pattern.rule.processer.CompareAroundProcesser;
import nc.itf.ic.m45.compensate.IPurchaseInSagasCompensate;
import nc.vo.ic.general.define.SagasConst;
import nc.vo.ic.m45.entity.PurchaseInBodyVO;
import nc.vo.ic.m45.entity.PurchaseInVO;
import nc.vo.ic.pub.util.StringUtil;
import nc.vo.pub.VOStatus;
import nc.vo.scmpub.res.billtype.ICBillType;
import nccloud.bs.ic.mobile.inbound.operation.rewrite.MobAfterPurchaseInUpdate;
import nccloud.bs.ic.mobile.inbound.operation.rewrite.MobBeforePurchaseInUpdate;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * 采购入库单后台更新BP
 *
 * @author songhy
 */
public class UpdateBP implements IUpdateBP<PurchaseInVO>, IUpdateRuleProvider<PurchaseInVO> {

    @Override
    public void addAfterRule(PurchaseInVO[] vos, PurchaseInVO[] originVOs,
                             CompareAroundProcesser<PurchaseInVO> processor) {
        //红字采购入库修改单保存的时候，增加判断逻辑，如果表头仓库是直运仓，不检查物料的现存量 放在前面设置session
        processor.addAfterRule(new IsRedBookThroughUpdate());

        /**
         * 放在现存量更新规则（OnhandAfterUpdate）之后，因为现存量更新时会调用预留接口，预留接口会回写采购订单，
         * 如果入库数量=订单数量，订单会自动入库关闭，入库关闭会解除预留，导致后续操作错误
         */
        ((ICCompareAroundProcesser<PurchaseInVO>) processor).addAfterRuleAt(new UpdateRewritePORule(),
                AtpAfterUpdate.class);
        processor.addAfterRule(new UpdReWritePIM());
        processor.addAfterRule(new FeeDetailUpdate());
        // processor.addAfterRule(new UpdateRewritePORule());
        processor.addAfterRule(new UpdateRewriteITRule());
        // 2020年3月19日 补充微协同，增加采购入库单修改后消息
        processor.addAfterRule(new MobAfterPurchaseInUpdate());
        //红字采购入库单原单退回保存回写累计入库退回主数量，由于预留处理需要查询蓝字采购入库单，回写操作应放在现存量更新规则（OnhandAfterUpdate）之后
        ((ICCompareAroundProcesser<PurchaseInVO>) processor).addAfterRuleAt(new UpdateRedReturnInRewriteRule(), AtpAfterUpdate.class);

        // 入库单保存回写采购合同付款计划
        processor.addAfterRule(new M45SaveAndRewriteCTPayPlan());
        // 入库修改保存回写采购订单付款计划 add by yinliangc 20220219
        processor.addAfterRule(new UpdateRewritePayPlanConfirmDataRule());
        // 入库修改保存回写付款计划开票信息
        processor.addAfterRule(new UpdateRewritePayPlanConfirmInvoicenumRule());

    }

    @Override
    public void addBeforeRule(PurchaseInVO[] vos, PurchaseInVO[] originVOs,
                              CompareAroundProcesser<PurchaseInVO> processor) {
        // sagas冻结校验
        processor.addBeforeRule(new VOSagaFrozenValidateRule<PurchaseInVO>(true));
        processor.addBeforeRule(new FillCostOrgRule());
        processor.addBeforeRule(new PurchaseBillCheckRule());
        processor.addBeforeRule(new PurchaseInAssetWarehouseCheck());
        processor.addBeforeRule(new CtplcustomeridCheck<PurchaseInVO>());
        processor.addBeforeRule(new VmiCheckRule());
        processor.addBeforeRule(new ReturnSnIsExistInEquipcardCheck());
        processor.addBeforeRule(new PurchaseinRetMarginProcess());
        processor.addBeforeRule(new PurchaseinRetMarginProcessFor5805());
        processor.addBeforeRule(new PurchaseInVOScaleCheckRule());
        // 利润中心校验规则
//		processor.addBeforeRule(
//				new CheckCliabilityValue<PurchaseInVO>(MetaNameConst.CLIABILITYOID, MetaNameConst.CIOLIABILITYOID));
        processor.addBeforeRule(new InsertCheckMaterialUnit());
        processor.addBeforeRule(new MobBeforePurchaseInUpdate());
        //新加校验  出库跟踪入库场景  将采购入库单入库数量改小校验
        processor.addBeforeRule(new UpdateNumCheck());

        //2025年6月13日09点38分 -- 物料档案基本页签启用项目辅助属性+库存组织未启用项目，采购入库单保存时（包含接口导入）清除行项目，材料出库单保存时（包含接口导入）清除行项目
        processor.addBeforeRule(new PurchaseInProjectRule());

    }

    /**
     * 父类方法重写
     *
     */
    @Override
    public PurchaseInVO[] update(PurchaseInVO[] vos, PurchaseInVO[] originVOs) {
        SagasUtils.frozenAndAddSaga(vos, ICBillType.PurchaseIn.getCode(), SagasConst.COMPENSABLE, null);
        Map<String, Serializable> paramMap = new HashMap<String, Serializable>();
        paramMap.put(SagasConst.KEY_ACTIONNAME, SagasConst.UPDATE_45);
        paramMap.put(SagasConst.KEY_VOS, SagasUtils.produceLightVO(vos, originVOs));
        SagasUtils.compensate(paramMap, IPurchaseInSagasCompensate.class);
        this.fillCvendorid(vos);
        UpdateBPTemplate<PurchaseInVO> updateBP = new UpdateBPTemplate<PurchaseInVO>(BPPlugInPoint.UpdateBP, this);
        PurchaseInVO[] retVOs = updateBP.update(vos, originVOs);
        return retVOs;
    }

    private void fillCvendorid(PurchaseInVO[] vos) {
        String cvendor = null;
        String cvendorvid = null;
        for (PurchaseInVO vo : vos) {
            // 取表头供应商
            cvendor = vo.getHead().getCvendorid();
            //取表头供应商vid
            cvendorvid = vo.getHead().getCvendorvid();

            // 为表体供应商赋值
            for (PurchaseInBodyVO body : vo.getBodys()) {
                if (StringUtil.isStringEqual(cvendor, body.getCvendorid())) {
                    continue;
                }
                body.setCvendorid(cvendor);
                body.setCvendorvid(cvendorvid);
                if (VOStatus.UNCHANGED == body.getStatus()) {
                    // 此处必须判断状态，不能全部设为UPDATED，否则删行后，再新增行，保存会报错
                    body.setStatus(VOStatus.UPDATED);
                }

            }
        }
    }

}
