package nc.bs.ic.m45.insert;

import nc.bs.ic.general.insert.IInsertBP;
import nc.bs.ic.general.insert.InsertBPTemplate;
import nc.bs.ic.general.insert.rule.before.CheckCliabilityValue;
import nc.bs.ic.general.rule.after.AtpAfterUpdate;
import nc.bs.ic.general.rule.before.CtplcustomeridCheck;
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.*;
import nc.bs.ic.pub.base.ICAroundProcesser;
import nc.bs.ic.pub.base.IInsertRuleProvider;
import nc.impl.pubapp.pattern.rule.processer.AroundProcesser;
import nc.vo.bd.payment.IPaymentUtil;
import nc.vo.ic.general.define.MetaNameConst;
import nc.vo.ic.m45.entity.PurchaseInBodyVO;
import nc.vo.ic.m45.entity.PurchaseInVO;
import nc.vo.ic.pub.util.StringUtil;
import nccloud.bs.ic.mobile.inbound.operation.rewrite.MobAfterPurchaseInSave;

/**
 * 采购入库单后台新增BP
 *
 * @author songhy
 */
public class InsertBP implements IInsertBP<PurchaseInVO>,
        IInsertRuleProvider<PurchaseInVO> {

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

        /**
         * 放在现存量更新规则（OnhandAfterUpdate）之后，因为现存量更新时会调用预留接口，预留接口会回写采购订单，
         * 如果入库数量=订单数量，订单会自动入库关闭，入库关闭会解除预留，导致后续操作错误
         */
        ((ICAroundProcesser<PurchaseInVO>) processor).addAfterRuleAt(
                new InsertRewritePORule(), AtpAfterUpdate.class);
        processor.addAfterRule(new InsReWritePIM());
        processor.addAfterRule(new InsertRewriteITRule());
        processor.addAfterRule(new MobAfterPurchaseInSave());
        processor.addAfterRule(new FeeDetailInsert());
        //红字采购入库单原单退回保存回写累计入库退回主数量，由于预留处理需要查询蓝字采购入库单，回写操作应放在现存量更新规则（OnhandAfterUpdate）之后
        ((ICAroundProcesser<PurchaseInVO>) processor).addAfterRuleAt(new InsertRedReturnInRewriteRule(), AtpAfterUpdate.class);
        ((ICAroundProcesser<PurchaseInVO>) processor).addAfterRuleAt(new InsertRedReturnInRewriteSORule(), InsertRedReturnInRewriteRule.class);
        // 回写付款计划
        processor.addAfterRule(new InsertRewritePayPlanConfirmDataRule());
        // 回写付款计划子孙开票数据 先票后入库 入库日期时点，
        processor.addAfterRule(new InsertOrSignRewritePayPlanInvoiceRule(IPaymentUtil.STORE_RECEIPT_DATE));
        // 入库单保存回写采购合同付款计划
        processor.addAfterRule(new M45SaveAndRewriteCTPayPlan());

        // processor.addAfterRule(new InsertRewritePORule());
    }

    @Override
    public void addBeforeRule(PurchaseInVO[] vos,
                              AroundProcesser<PurchaseInVO> processor) {
        // 检查是否可以生成入库单
        processor.addBeforeRule(new InsertCheckCanInRule());
        processor.addBeforeRule(new FillCostOrgRule());
//    processor.addBeforeRule(new SaveCheckFeeMnyRule());
        processor.addBeforeRule(new PurchaseBillCheckRule());
        processor.addBeforeRule(new PurchaseInAssetWarehouseCheck());
        // 当数量（主数量，数量，报价数量）与采购订单一致时，使采购入库单表体价格和单价与采购订单一致
        //下面的规则处理会使入库单的改价不生效 hujieh
//    processor.addBeforeRule(new AdjustPriceAndMnyWhenSameNumRule());
        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 InsertCheckMaterialUnit());
        // 利润中心校验规则
        processor.addBeforeRule(new CheckCliabilityValue<PurchaseInVO>(MetaNameConst.CLIABILITYOID,MetaNameConst.CIOLIABILITYOID));
        // 来源于进口模块--流向单，填充报价单位、报价换算率
        processor.addBeforeRule(new FillInVqtunitRule());

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

    @Override
    public PurchaseInVO[] insert(PurchaseInVO[] bills) {
        // 应该在“物理自由辅助属性检查”规则执行前补充供应商
        this.fillCvendorid(bills);
        InsertBPTemplate<PurchaseInVO> insertBP =
                new InsertBPTemplate<PurchaseInVO>(BPPlugInPoint.InsertBP, this);
        return insertBP.insert(bills);
    }

    /**
     * 补表体的供应商，供应商已经挪到表头，表体的供应商要跟表头供应商一样
     *
     * @param vos
     */
    private void fillCvendorid(PurchaseInVO[] vos) {
        String cvendor = null;
        String cvendorvid = null;
        for (PurchaseInVO vo : vos) {

            // 取表头供应商
            cvendor = vo.getHead().getCvendorid();
            cvendorvid = vo.getHead().getCvendorvid();
            if (StringUtil.isSEmptyOrNull(cvendor)) {
                continue;
            }

            // 为表体供应商赋值
            for (PurchaseInBodyVO body : vo.getBodys()) {
                body.setCvendorid(cvendor);
                body.setCvendorvid(cvendorvid);
            }
        }
    }

}
