package nc.impl.pu.m21.action;

import nc.bs.pu.m21.action.rule.approve.AfterApprovingSynchronizeRuleRZ;
import nc.bs.pu.m21.maintain.rule.SupplierFrozeChkRule;
import nc.bs.pu.m21.plugin.OrderPluginPoint;
import nc.bs.pub.compiler.AbstractCompiler2;
import nc.bs.scmpub.pf.PfParameterUtil;
import nc.bs.scmpub.rule.VOSagaFrozenValidateRule;
import nc.impl.pu.m21.action.OrderReviseApproveAction;
import nc.impl.pu.m21.action.rule.approve.*;
import nc.impl.pu.m21.action.rule.pm.OrderApprovePMSupplyRule;
import nc.impl.pu.m21.action.rule.pm.OrderRewritePMStartDateRule;
import nc.impl.pu.m21.action.rule.revise.CheckBfinalcloseRule;
import nc.impl.pubapp.pattern.data.bill.BillUpdate;
import nc.impl.pubapp.pattern.rule.processer.AroundProcesser;
import nc.itf.pu.m21.compensate.IOrderSagasCompensate;
import nc.itf.pu.reference.ic.ATPServices;
import nc.vo.pu.m21.context.OrderContext;
import nc.vo.pu.m21.entity.OrderVO;
import nc.vo.pu.pub.enumeration.POEnumBillStatus;
import nc.vo.pu.pub.rule.pf.UpdatePflowVORule;
import nc.vo.pu.pub.sagas.PUSagasOperationEnum;
import nc.vo.pub.BusinessException;
import nc.vo.pub.compiler.PfParameterVO;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nc.vo.scmpub.msg.rule.UpdateMsgStatusRule;
import nc.vo.scmpub.res.billtype.POBillType;
import nc.vo.scmpub.util.AppInfoContext;
import nccloud.commons.lang.ArrayUtils;
import nccloud.pubimpl.pu.mobile.service.order.MobAfterApproveForPoOrderImpl;
import nccloud.pubitf.pu.pub.util.PuSagasUtil;

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

public class OrderApproveAction {
    public OrderApproveAction() {
    }

    public OrderVO[] approve(OrderVO[] vos, AbstractCompiler2 script, OrderContext[] ctxs) {
        Integer reviseStatus = vos[0].getHVO().getRevisionStatus();
        PfParameterUtil<OrderVO> util = new PfParameterUtil(script == null ? null : script.getPfParameterVO(), vos);
        OrderVO[] originBills = (OrderVO[]) util.getClientOrignBills();
        OrderVO[] clientBills = (OrderVO[]) util.getClientFullInfoBill();
        AroundProcesser<OrderVO> processer = new AroundProcesser(OrderPluginPoint.APPROVE);
        this.addBeforeRule(processer);
        this.addAfterRule(processer, null != script ? script.getPfParameterVO() : null);
        OrderVO[] customProperty = (OrderVO[]) script.getPfParameterVO().getCustomProperty("nc.bs.scmpub.pf.ORIGIN_VO_PARAMETER");
        if (customProperty == null || customProperty.length == 0) {
            clientBills = vos;
        }

        processer.before(clientBills);
        if (null != script) {
            try {
                script.procFlowBacth(script.getPfParameterVO());
            } catch (Exception e) {
                ExceptionUtils.wrappException(e);
            }
        }

        OrderVO[] returnVos;
        if (reviseStatus != null && reviseStatus == 0 && vos[0].getHVO().getForderstatus() == POEnumBillStatus.APPROVE.toIntValue()) {
            OrderContext ctx = ArrayUtils.isEmpty(ctxs) ? new OrderContext() : ctxs[0];
            returnVos = (new OrderReviseApproveAction()).approve(clientBills, ctx);
        } else {
            this.atpBeforeUpdate(clientBills);
            BillUpdate<OrderVO> update = new BillUpdate();
            returnVos = (OrderVO[]) update.update(clientBills, originBills);

            try {
                AppInfoContext.setProductCode(PUSagasOperationEnum.OREDERAPPROVE.getResCommon());
                AppInfoContext.setResId(PUSagasOperationEnum.OREDERAPPROVE.getResId());
                PuSagasUtil.frozenAndAddSaga(originBills, POBillType.Order.getCode());
                Map<String, Serializable> map = new HashMap();
                map.put("opertaion", "approve");
                map.put("pk_order", originBills[0].getHVO().getPk_order());
                map.put("po_order_isrevise", UFBoolean.FALSE);
                map.put("po_orderapprover", originBills[0].getHVO().getApprover());
                map.put("po_ordertaudittime", originBills[0].getHVO().getTaudittime());
                map.put("po_orderforderstatus", originBills[0].getHVO().getForderstatus());
                PuSagasUtil.compensate(IOrderSagasCompensate.class, map);
            } catch (BusinessException e) {
                ExceptionUtils.wrappException(e);
            }

            if (vos[0].getHVO().getForderstatus() == POEnumBillStatus.APPROVE.toIntValue()) {
                this.atpUpdate(returnVos);
                processer.after(returnVos);
            }
        }

        return returnVos;
    }

    private void addAfterRule(AroundProcesser<OrderVO> processer, PfParameterVO pfParameterVO) {
        processer.addAfterRule(new ApproveBudgetCtrlRule());
        processer.addAfterRule(new FilterOrderByStatusRule(POEnumBillStatus.APPROVE.toInt()));
        processer.addAfterRule(new ApproveSupplyRule());
        processer.addAfterRule(new InsertStatusOnWayRule());
        processer.addAfterRule(new InsertPayPlanBillVORule());
        processer.addAfterRule(new ApproveRewritePayPlanConfirmData4CTRule());
        processer.addAfterRule(new ApproveRewritePayPlanConfirmDataRule());
        processer.addAfterRule(new FillNcaninnumRule());
        processer.addAfterRule(new ApproveAfterEventRule());
        processer.addAfterRule(new MobAfterApproveForPoOrderImpl());
        processer.addAfterFinalRule(new UpdatePflowVORule(pfParameterVO));
        processer.addAfterFinalRule(new ApproveM21AndRewriteCTPayPlan());
        processer.addAfterRule(new OrderRewritePMStartDateRule(true));
        processer.addAfterRule(new OrderApprovePMSupplyRule());

        // 采购订单审批后同步到锐制MES系统
        processer.addAfterRule(new AfterApprovingSynchronizeRuleRZ());
    }

    private void addBeforeRule(AroundProcesser<OrderVO> processer) {
        processer.addBeforeRule(new VOSagaFrozenValidateRule(true));
        processer.addBeforeRule(new CheckBfinalcloseRule());
        processer.addBeforeRule(new ApproveVOValidateRule());
        processer.addBeforeRule(new SupplierFrozeChkRule());
        processer.addBeforeRule(new ApproveBeforeEventRule());
        processer.addBeforeRule(new UpdateMsgStatusRule("pk_order"));
    }

    private void atpBeforeUpdate(OrderVO[] vos) {
        ATPServices.modifyATPBefore(POBillType.Order.getCode(), vos);
    }

    private void atpUpdate(OrderVO[] vos) {
        ATPServices.modifyATPAfter(POBillType.Order.getCode(), vos);
    }
}
