package nc.bs.bd.bom.bom0202.bp;

import nc.bs.bd.bom.bom0202.plugin.bpplugin.BomPluginPoint;
import nc.bs.bd.bom.bom0202.rule.*;
import nc.bs.mmbd.pub.rule.MMAutoMaterialAssignRule;
import nc.bs.pubapp.pub.rule.FieldLengthCheckRule;
import nc.bs.pubapp.pub.rule.FillUpdateDataRule;
import nc.bs.pubapp.pub.rule.OrgDisabledCheckRule;
import nc.impl.pubapp.bd.material.assistant.MarAssistantSaveRule;
import nc.impl.pubapp.pattern.rule.ICompareRule;
import nc.impl.pubapp.pattern.rule.IRule;
import nc.impl.pubapp.pattern.rule.processer.CompareAroundProcesser;
import nc.itf.org.IOrgConstBasic;
import nc.mmbd.utils.factoryparam.MMBDFactoryParameter;
import nc.util.mmf.busi.rule.MMRowNoCheckRule;
import nc.util.mmf.framework.gc.GCUpdateBPTemplate;
import nc.vo.bd.bom.bom0202.entity.AggBomVO;
import nc.vo.bd.bom.bom0202.entity.BomActivityVO;
import nc.vo.bd.bom.bom0202.entity.BomItemVO;
import nc.vo.bd.bom.bom0202.entity.BomOutputsVO;
import nc.vo.bd.bom.bom0202.entity.BomPosVO;
import nc.vo.bd.bom.bom0202.entity.BomReplVO;
import nc.vo.bd.bom.bom0202.entity.BomVO;
import nc.vo.bd.bom.bom0202.entity.BomWipVO;
import nc.vo.pub.VOStatus;

import java.util.Map;

/**
 * BOM更新BP
 *
 * @author baijl
 */
public class BomUpdateBP {
    /**
     * 是否校验工程变更单是否启用
     */
    private boolean checkEcn = true;

    public boolean getCheckEcn() {
        return this.checkEcn;
    }

    public void setCheckEcn(boolean checkEcn) {
        this.checkEcn = checkEcn;
    }

    /**
     * 是否支持审批流
     */
    private boolean onApprove;

    public boolean getOnApprove() {
        return this.onApprove;
    }

    public void setOnApprove(boolean onApprove) {
        this.onApprove = onApprove;
    }

    /**
     * 是否是bom或bom树修改保存，区分反向bom维护、bom子项批量修改等节点
     */
    private boolean isFromBomAndBomTree = false;

    private boolean isEcnOrgChanged = false;

    private boolean isAssign = false;

    private boolean isCancleAssign = false;

    /**
     * 跨组织复制时，原bom主键
     */
    private String[] origins = null;

    private Map<String,String> rownoMap = null;

    public Map<String, String> getRownoMap() {
        return rownoMap;
    }

    public void setRownoMap(Map<String, String> rownoMap) {
        this.rownoMap = rownoMap;
    }
    public AggBomVO[] update(AggBomVO[] fullBills, AggBomVO[] originBills) {
        return this.update(fullBills, originBills, true, false, false);
    }

    public AggBomVO[] update(AggBomVO[] fullBills, AggBomVO[] originBills, boolean newCheckEcn) {
        return this.update(fullBills, originBills, newCheckEcn, false, false);
    }

    public AggBomVO[] update(AggBomVO[] fullBills, AggBomVO[] originBills, boolean newCheckEcn, boolean isFromBom,
                             boolean isEcnOrg) {
        return this.update(fullBills, originBills, newCheckEcn, isFromBom, isEcnOrg, null, false);
    }

    public AggBomVO[] update(AggBomVO[] fullBills, AggBomVO[] originBills, boolean newCheckEcn, boolean isFromBom,
                             boolean isEcnOrg, String[] origins, Boolean param) {
        this.setCheckEcn(newCheckEcn);
        this.setFromBomAndBomTree(isFromBom);
        this.setEcnOrgChanged(this.getIsOrgChanged(fullBills[0], isEcnOrg));
        if (origins != null) {
            this.setOrigins(origins);
        }
        // 调用修改模板
        GCUpdateBPTemplate<AggBomVO> bp = new GCUpdateBPTemplate<AggBomVO>(BomPluginPoint.UPDATE);
        for (AggBomVO vo : fullBills) {
            if (vo.getParent().getStatus() != VOStatus.UPDATED && !this.isAssign) {
                vo.getParent().setStatus(VOStatus.UPDATED);
            }
        }
        // 执行前规则
        this.addBeforeRule(bp.getAroundProcesser());
        // 执行后规则
        this.addAfterRule(bp.getAroundProcesser());
        return bp.update(fullBills, originBills);
    }

    /**
     * 带参的更新方法（是否支持ECN；是否支持审批流）
     *
     * @param fullBills
     * @param originBills
     * @param newCheckEcn
     * @param onApprove
     * @param isFromBom
     * @param isEcnOrg
     * @return
     */
    public AggBomVO[] update(AggBomVO[] fullBills, AggBomVO[] originBills, boolean newCheckEcn, boolean onapprove,
                             boolean isFromBom, boolean isEcnOrg) {
        this.setCheckEcn(newCheckEcn);
        this.setOnApprove(onapprove);
        this.setFromBomAndBomTree(isFromBom);
        this.setEcnOrgChanged(this.getIsOrgChanged(fullBills[0], isEcnOrg));
        // 调用修改模板
        GCUpdateBPTemplate<AggBomVO> bp = new GCUpdateBPTemplate<AggBomVO>(BomPluginPoint.UPDATE);
        for (AggBomVO vo : fullBills) {
            if (vo.getParent().getStatus() != VOStatus.UPDATED && !this.isAssign) {
                vo.getParent().setStatus(VOStatus.UPDATED);
            }
        }
        // 执行前规则
        this.addBeforeRule(bp.getAroundProcesser());
        // 执行后规则
        if (!this.isAssign && !this.isCancleAssign) {
            this.addAfterRule(bp.getAroundProcesser());
        }
        return bp.update(fullBills, originBills);
    }

    /**
     * 更新前规则
     *
     * @param processer
     */
    @SuppressWarnings("unchecked")
    private void addBeforeRule(CompareAroundProcesser<AggBomVO> processer) {
        IRule<AggBomVO> rule = null;
        if (this.isAssign || this.isCancleAssign) {
            // 分配校验
            if (this.isAssign) {
                rule = new BomAssignCheckRule();
                processer.addBeforeRule(rule);

                // 分配组织vid
                rule = new BomAssgnUseorgRule();
                processer.addBeforeRule(rule);
            }
            if (this.isCancleAssign) {
                // 分配部分校验
                rule = new BomCancelAssignCheckRule();
                processer.addBeforeRule(rule);
            }
        } else {

            // 组织停用校验
            rule = new OrgDisabledCheckRule(BomVO.PK_ORG, IOrgConstBasic.PRODUCEPLANTYPE);
            processer.addBeforeRule(rule);

            if (this.getIsFromBomAndBomTree()) {
                // 判断组织启用工程变更的状态前后是否一致，不一致不能修改
                if (this.getIsEcnOrgChanged()) {
                    rule = new ECNOrgChangedRule();
                    processer.addBeforeRule(rule);
                }
            } else {
                if (this.getCheckEcn()) {
                    // 如果启用工程的话，不能修改保存bom(适用于批改、反向bom维护、bom子项批量替换场景)
                    rule = new ECNCheckForModifyBomRule();
                    processer.addBeforeRule(rule);
                }
            }

            if (this.getCheckEcn()) {
                // 数据检查
                BomSaveDataCheckRule saveDataCheckRule = new BomSaveDataCheckRule();
                saveDataCheckRule.setRownoMap(this.getRownoMap());
                processer.addBeforeRule(saveDataCheckRule);
            } else {
                // 数据检查
                BomSaveDataCheckRule saveDataCheckRule = new BomSaveDataCheckRule(!this.getCheckEcn());
                saveDataCheckRule.setRownoMap(this.getRownoMap());
                processer.addBeforeRule(saveDataCheckRule);
            }
            // 行号检查
            rule = new MMRowNoCheckRule<AggBomVO>();
            processer.addBeforeRule(rule);

            // 物料信息检查
            rule = new BomMaterialCheckRule();
            processer.addBeforeRule(rule);

            // 保存时分配信息校验
            rule = new BomSaveAssignVersionCheckRule();
            processer.addBeforeRule(rule);

            // 长度检查
            rule = new FieldLengthCheckRule();
            processer.addBeforeRule(rule);

            // if (this.getOnApprove()) {
            // // 设置审计信息
            // rule = new FillUpdateDataRule();
            // processer.addBeforeRule(rule);
            // } 注掉 因为定制BOM修改保存时最后修改人修改时间信息会写不进去
            // 设置审计信息
            rule = new FillUpdateDataRule();
            processer.addBeforeRule(rule);

            // 检查自由项
            rule = new MarAssistantSaveRule<AggBomVO>();
            processer.addBeforeRule(rule);

            // 检查自定义项
            String[] prefixs = new String[] { "hvdef", "vdef", "vbdef", "vdef", "vdef", "vdef", "vdef" };
            Class<?>[] voClasses = new Class<?>[] { BomVO.class, BomItemVO.class, BomOutputsVO.class,
                    BomActivityVO.class, BomWipVO.class, BomPosVO.class, BomReplVO.class };
            rule = new nc.impl.pubapp.bd.userdef.UserDefSaveRule<AggBomVO>(prefixs, voClasses);
            processer.addBeforeRule(rule);

            // delete by qianzhx
            // BOM在非审批通过态可以支持存在多个默认 20150425
            // BOM默认版本规则
            // rule = new BomDefaultVersionCheckRule();
            // processer.addBeforeRule(rule);
            // edited by renshch 20150507
            // 定制BOM不支持审批流，最多一个默认，此规则已做调整，只对定制BOM处理
            rule = new BomDefaultVersionCheckRule();
            processer.addBeforeRule(rule);

            //选配修改：增加模型BOM/可选类BOM/定制BOM 校验
            rule=new BomCheckForMatchRule();
            processer.addBeforeRule(rule);

            // 默认卷积：在同一维度下只能有一个默认卷积（业务单元+物料+物料版本+bom类型）
            ConvolutionRule ctRule = new ConvolutionRule();
            processer.addBeforeRule(ctRule);

            // 是否委外：在同一维度下只能有一个委外BOM（业务单元+物料+物料版本）
            OutsourceRule osRule = new OutsourceRule();
            processer.addBeforeRule(osRule);

            // 子项物料启用序列号校验规则
            rule = new SerialManageCheckRule();
            processer.addBeforeRule(rule);

            // 配置BOM 材料页签的相关校验
            // 选配修改：去掉之前定制BOM关于特征码的校验，改到下面的rule里校验
            rule = new CfgBomAndCBomItemCheckRule();
            processer.addBeforeRule(rule);

            // 注册事件源
            rule = new BomUpdateBeforeEventRule();
            processer.addBeforeRule(rule);

            // 被替代方案引用的子项不能修改
            ICompareRule<AggBomVO> compareRule = new UpdateHasReplsCheckRule();
            processer.addBeforeRule(compareRule);

        }
        // 物料表头自动分配
        rule = new MMAutoMaterialAssignRule<AggBomVO>(new String[] { BomVO.HCMATERIALVID, BomVO.HCMATERIALID }, null,
                null, new String[] { BomVO.PK_ORG }, null, null, BomVO.class, this.isAssign);
        processer.addBeforeFinalRule(rule);
        // 表体材料物料自动分配
        rule = new MMAutoMaterialAssignRule<AggBomVO>(null,
                new String[] { BomItemVO.CMATERIALVID, BomItemVO.CMATERIALID }, null, null,
                new String[] { BomItemVO.PK_ORG }, null, BomItemVO.class, this.isAssign);
        processer.addBeforeFinalRule(rule);
        // 表体联副产品物料自动分配
        rule = new MMAutoMaterialAssignRule<AggBomVO>(null,
                new String[] { BomOutputsVO.CMATERIALVID, BomOutputsVO.CMATERIALID }, null, null,
                new String[] { BomOutputsVO.PK_ORG }, null, BomOutputsVO.class, this.isAssign);
        processer.addBeforeFinalRule(rule);
        // 孙表线上仓物料表体自动分配
//		rule = new MMAutoMaterialAssignRule<AggBomVO>(null, BomWipVO.G_CMATERIALVID, null,
//				new String[] { BomWipVO.PK_ORG });
//		processer.addBeforeFinalRule(rule);
//		// 孙表组装位置物料表体自动分配
//		rule = new MMAutoMaterialAssignRule<AggBomVO>(null, BomPosVO.G_CMATERIALVID, null,
//				new String[] { BomPosVO.PK_ORG });
//		processer.addBeforeFinalRule(rule);
//		// 孙表阶梯变动损耗物料表体自动分配
//		rule = new MMAutoMaterialAssignRule<AggBomVO>(null, BomLossVO.CLMATERIALVID, null,
//				new String[] { BomLossVO.PK_ORG });
//		processer.addBeforeFinalRule(rule);

        // 孙表替代料物料表体自动分配
        rule = new MMAutoMaterialAssignRule<AggBomVO>(null, null,
                new String[] { BomReplVO.CREPLMATERIALVID, BomReplVO.CREPLMATERIALOID }, null, null,
                new String[] { BomReplVO.PK_ORG }, BomReplVO.class, this.isAssign);
        processer.addBeforeFinalRule(rule);

        if (this.origins != null) {
            // 替代方案-物料分配
            rule = new BomReplsMaterialAssignRule(this.origins);
            processer.addBeforeRule(rule);
        }

        //2025年6月13日09点38分 -- BOM保存时校验各BOM子件本业务单元库存组织是否启用项目，如果启用，则项目专用料自动启用（包含接口导入）
        rule =new BOMBprojectmaterialEnableRule();
        processer.addBeforeRule(rule);
    }

    /**
     * 更新后规则
     *
     * @param processer
     */

    private void addAfterRule(CompareAroundProcesser<AggBomVO> processer) {
        // BOM版本检查规则
        IRule<AggBomVO> rule = new BomVersionCheckRule();
        processer.addAfterRule(rule);

        // 同步BOM匹配规则中的BOM版本 add by lijbe
        ICompareRule<AggBomVO> updateBmrtRule = new BomUpdateBmrtVersionRule();
        processer.addBeforeRule(updateBmrtRule);

        // 注册事件源
        IRule<AggBomVO> eventRrule = new BomUpdateAfterEventRule();
        processer.addAfterRule(eventRrule);

    }

    public boolean getIsFromBomAndBomTree() {
        return this.isFromBomAndBomTree;
    }

    public void setFromBomAndBomTree(boolean isFromBomAndBomTree) {
        this.isFromBomAndBomTree = isFromBomAndBomTree;
    }

    public boolean getIsEcnOrgChanged() {
        return false;
    }

    public void setEcnOrgChanged(boolean isEcnOrgChanged) {
        this.isEcnOrgChanged = isEcnOrgChanged;
    }

    public boolean getIsOrgChanged(AggBomVO aggvo, boolean isEcn_old) {
        BomVO bomvo = (BomVO) aggvo.getParentVO();
        boolean isEcn_new = MMBDFactoryParameter.isAlterCtrl(bomvo.getPk_org());
        if (isEcn_new != isEcn_old) {
            // 前后不一致则赋值
            return true;
        }
        return false;
    }

    public boolean isAssign() {
        return this.isAssign;
    }

    public void setAssign(boolean isAssign) {
        this.isAssign = isAssign;
    }

    public boolean isCancleAssign() {
        return this.isCancleAssign;
    }

    public void setCancleAssign(boolean isCancleAssign) {
        this.isCancleAssign = isCancleAssign;
    }

    public String[] getOrigins() {
        return origins;
    }

    public void setOrigins(String[] origins) {
        this.origins = origins;
    }

}
