package com.yem.wm.bc.change.op;

import com.yem.wm.bc.change.business.ChangeModelHelper;
import com.yem.wm.bc.change.common.consts.BizChangeStatusEnum;
import com.yem.wm.bc.change.common.consts.BizValidStatusEnum;
import com.yem.wm.bc.change.common.consts.BizChangeTypeEnum;
import com.yem.wm.bc.common.CommonUtils;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.metadata.IDataEntityProperty;
import kd.bos.dataentity.utils.StringUtils;
import kd.bos.entity.EntityType;
import kd.bos.entity.EntryType;
import kd.bos.entity.TreeEntryType;
import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
import kd.bos.entity.plugin.AddValidatorsEventArgs;
import kd.bos.entity.plugin.PreparePropertysEventArgs;
import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
import kd.bos.entity.plugin.args.EndOperationTransactionArgs;
import kd.bos.entity.property.LinkEntryProp;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.metadata.entity.validation.ConditionValidation;
import kd.bos.orm.query.QFilter;
import kd.bos.service.operation.validate.ConditionValidator;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.bos.servicehelper.user.UserServiceHelper;

import java.util.*;

/**
 * @author 夜子
 * @ClassName csdf
 * @description: TODO
 * @date 2023年08月03日
 * @version: 1.0
 */
public class XBillBizValidOp extends AbstractOperationServicePlugIn {
    private static final Log LOGGER = LogFactory.getLog(kd.mpscmm.msbd.changemodel.opplugin.XBillBizValidOp.class);

    public void onPreparePropertys(PreparePropertysEventArgs e) {
        super.onPreparePropertys(e);
        e.getFieldKeys().add("sourcebillentity");
        e.getFieldKeys().add("sourcebillid");
        e.getFieldKeys().add("xvalidstatus");
    }

    public void onAddValidators(AddValidatorsEventArgs e) {
        super.onAddValidators(e);
        if (this.billEntityType != null) {
            String opkey = (String)this.operateMeta.get("key");
            List<ConditionValidation> vallist = ChangeModelHelper.getValidConditionList(this.billEntityType.getName(), opkey);
            if (vallist != null && vallist.size() > 0) {
                for (ConditionValidation conditionValidation : vallist) {
                    ConditionValidator XBillBizValidCV = new ConditionValidator();
                    XBillBizValidCV.setValidation(((ConditionValidation) conditionValidation).createValidate());
                    e.addValidator(XBillBizValidCV);
                }
            }
        }
    }

    @Override
    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
        super.beginOperationTransaction(e);
        if (e.getDataEntities() != null && e.getDataEntities().length != 0) {
            DynamicObject[] bills = e.getDataEntities();
            DynamicObject changeModel = ChangeModelHelper
                    .getChangeModel4XBill(bills[0].getDataEntityType().getName());
            if (changeModel == null) {
                return;
            }
            for (DynamicObject bill : bills) {
                ChangeModelHelper.excutePluginMethod(changeModel, "beforeXBillBizValid",
                        bill);
            }
        }
    }

    public void endOperationTransaction(EndOperationTransactionArgs e) {
        if ("bizvalid".equals(e.getOperationKey()) && !CommonUtils.isNull(e.getDataEntities())) {
            long beginTime = System.currentTimeMillis();
            LOGGER.info("BizValidPerformance--BeginTime: " + new Date(beginTime));
            DynamicObject[] bills = e.getDataEntities();

            for (DynamicObject dynamicObject : bills) {
                DynamicObject bill = dynamicObject;
                bill = BusinessDataServiceHelper.loadSingle(bill.getPkValue(), bill.getDynamicObjectType().getName());
                DynamicObject changeModel = ChangeModelHelper.getChangeModel4XBill(bill.getDataEntityType().getName());
                if (!CommonUtils.isNull(changeModel)) {
                    String sourcebillentity = bill.getString("sourcebillentity");
                    Long sourcebillid = bill.getLong("sourcebillid");
                    if (sourcebillentity != null) {
                        DynamicObject srcBill = BusinessDataServiceHelper.loadSingle(sourcebillid, sourcebillentity);
                        if (!CommonUtils.isNull(srcBill)) {
                            String version;
                            int newVersion;
                            if (!changeModel.getBoolean("isnotupdateversion")) {
                                version = srcBill.getString("version");
                                if (version == null || version.length() == 0 || version.equals("0") || version.startsWith("0.") || version.startsWith("1.")) {
                                    version = "1";
                                }

                                newVersion = 1;

                                try {
                                    newVersion = Integer.parseInt(version) + 1;
                                } catch (NumberFormatException var45) {
                                    LOGGER.warn(var45);
                                }

                                srcBill.set("version", String.valueOf(newVersion));
                                srcBill.set("subversion", "1");
                            } else {
                                version = srcBill.getString("subversion");
                                if (version == null || version.length() == 0 || version.equals("0") || version.startsWith("0.") || version.startsWith("1.")) {
                                    version = "1";
                                }

                                newVersion = 1;

                                try {
                                    newVersion = Integer.parseInt(version) + 1;
                                } catch (NumberFormatException var44) {
                                    LOGGER.warn(var44);
                                }

                                srcBill.set("subversion", String.valueOf(newVersion));
                            }

                            srcBill.set("changestatus", BizChangeStatusEnum.CHANGED.getValue());
                            srcBill.set("changer", BusinessDataServiceHelper.loadSingle(UserServiceHelper.getCurrentUserId(), "bos_user"));
                            srcBill.set("changedate", new Date(System.currentTimeMillis()));
                            String[] enablePropertys = ChangeModelHelper.getCanWritebackProperty(bill.getDynamicObjectType());
                            int var14 = 0;
                            if (enablePropertys != null) {
                                var14 = enablePropertys.length;
                            }

                            for (int var15 = 0; var15 < var14; ++var15) {
                                String enableProperty = enablePropertys[var15];

                                try {
                                    Object oldObject = srcBill.get(enableProperty);
                                    Object newObject = bill.get(enableProperty);
                                    if (CommonUtils.isRealChanged(oldObject, newObject)) {
                                        ChangeModelHelper.SetPropertyValue(srcBill, enableProperty, bill.get(enableProperty));
                                    }
                                } catch (Exception ignored) {
                                }
                            }

                            long finishBillHeadValueTime = System.currentTimeMillis();
                            LOGGER.info("BizValidPerformance--finishBillHeadValueTime: " + new Date(finishBillHeadValueTime));
                            LOGGER.info("BizValidPerformance--finishBillHeadValueUse: " + (finishBillHeadValueTime - beginTime) + "ms");
                            List<EntityType> xBillentryEntitys = ChangeModelHelper.getChildEntities(bill.getDataEntityType());
                            Map<String, String[]> enableWBEntryPropertysMap = new HashMap<>();
                            Iterator<EntityType> var53 = xBillentryEntitys.iterator();

                            label348:
                            while (var53.hasNext()) {
                                EntityType xBillentryEntity = (EntityType) var53.next();
                                String xBillEntryEntityKey = xBillentryEntity.getName();
                                Map<String, String> fieldmap = this.getXBillEntryAndField(changeModel).get(xBillEntryEntityKey);
                                String[] enableEntryPropertys = null;
                                if (enableWBEntryPropertysMap.containsKey(xBillEntryEntityKey)) {
                                    enableEntryPropertys = (String[]) enableWBEntryPropertysMap.get(xBillEntryEntityKey);
                                } else {
                                    enableEntryPropertys = ChangeModelHelper.getCanWritebackProperty(bill.getDynamicObjectType(), xBillEntryEntityKey);
                                    if (enableEntryPropertys != null) {
                                        enableWBEntryPropertysMap.put(xBillEntryEntityKey, enableEntryPropertys);
                                    }
                                }

                                if (xBillentryEntity.getClass() == EntryType.class || xBillentryEntity.getClass() == TreeEntryType.class) {
                                    DynamicObjectCollection xBillEntrys = bill.getDynamicObjectCollection(xBillEntryEntityKey);
                                    if (!CommonUtils.isNull(xBillEntrys) && !CommonUtils.isNull(enableEntryPropertys) && !CommonUtils.isNull(fieldmap)) {
                                        DynamicObjectCollection srcBillEntrys = srcBill.getDynamicObjectCollection(xBillentryEntity.getName());
                                        Iterator<DynamicObject> var23 = xBillEntrys.iterator();

                                        while (true) {
                                            while (true) {
                                                label265:
                                                while (true) {
                                                    if (!var23.hasNext()) {
                                                        continue label348;
                                                    }

                                                    DynamicObject xBillEntry = (DynamicObject) var23.next();
                                                    String subEntityChangeTypePro;
                                                    DynamicObjectCollection subXBillEntrys;
                                                    DynamicObject subXBillEntry;
                                                    Iterator var36;
                                                    if (BizChangeTypeEnum.UPDATE.getValue().equals(xBillEntry.get((String) fieldmap.get("changetype")))) {

                                                        for (DynamicObject srcBillEntry : srcBillEntrys) {
                                                            if (srcBillEntry.getLong("id") == xBillEntry.getLong((String) fieldmap.get("srcid"))) {
                                                                for (String enableEntryProperty : enableEntryPropertys) {
                                                                    subEntityChangeTypePro = enableEntryProperty;
                                                                    ChangeModelHelper.SetPropertyValue(srcBillEntry, subEntityChangeTypePro, xBillEntry.get(subEntityChangeTypePro));
                                                                }

                                                                Iterator<IDataEntityProperty> var66 = xBillEntry.getDataEntityType().getProperties().iterator();

                                                                label344:
                                                                while (true) {
                                                                    String entityProName;
                                                                    String[] subEnableEntryPropertys;
                                                                    Map subfieldmap;
                                                                    do {
                                                                        do {
                                                                            do {
                                                                                do {
                                                                                    do {
                                                                                        if (!var66.hasNext()) {
                                                                                            continue label265;
                                                                                        }

                                                                                        IDataEntityProperty entityProperty = (IDataEntityProperty) var66.next();
                                                                                        entityProName = entityProperty.getName();
                                                                                    } while (!(xBillEntry.get(entityProName) instanceof DynamicObjectCollection));

                                                                                    subEntityChangeTypePro = null;
                                                                                    if (enableWBEntryPropertysMap.containsKey(entityProName)) {
                                                                                        subEnableEntryPropertys = (String[]) enableWBEntryPropertysMap.get(entityProName);
                                                                                    } else {
                                                                                        subEnableEntryPropertys = ChangeModelHelper.getCanWritebackProperty(bill.getDynamicObjectType(), entityProName);
                                                                                        if (subEnableEntryPropertys != null) {
                                                                                            enableWBEntryPropertysMap.put(entityProName, subEnableEntryPropertys);
                                                                                        }
                                                                                    }

                                                                                    subfieldmap = this.getXBillEntryAndField(changeModel).get(entityProName);
                                                                                } while (subEnableEntryPropertys == null);
                                                                            } while (subEnableEntryPropertys.length == 0);
                                                                        } while (subfieldmap == null);
                                                                    } while (subfieldmap.size() == 0);

                                                                    subXBillEntrys = (DynamicObjectCollection) xBillEntry.get(entityProName);
                                                                    DynamicObjectCollection subSrcBillEntrys = srcBillEntry.getDynamicObjectCollection(entityProName);
                                                                    Iterator<DynamicObject> var74 = subXBillEntrys.iterator();

                                                                    while (true) {
                                                                        while (true) {
                                                                            label332:
                                                                            while (true) {
                                                                                if (!var74.hasNext()) {
                                                                                    continue label344;
                                                                                }

                                                                                subXBillEntry = (DynamicObject) var74.next();
                                                                                DynamicObject subSrcBillEntry;
                                                                                if (BizChangeTypeEnum.CANCEL.getValue().equals(subXBillEntry.get((String) subfieldmap.get("changetype")))) {
                                                                                    var36 = subSrcBillEntrys.iterator();

                                                                                    while (var36.hasNext()) {
                                                                                        subSrcBillEntry = (DynamicObject) var36.next();
                                                                                        if (subSrcBillEntry.getLong("id") == subXBillEntry.getLong((String) subfieldmap.get("srcid"))) {
                                                                                            subSrcBillEntrys.remove(subSrcBillEntry);
                                                                                            break;
                                                                                        }
                                                                                    }
                                                                                } else if (BizChangeTypeEnum.ADDNEW.getValue().equals(subXBillEntry.get((String) subfieldmap.get("changetype")))) {
                                                                                    subSrcBillEntry = subSrcBillEntrys.addNew();

                                                                                    for (IDataEntityProperty subEntityProperty : subSrcBillEntry.getDataEntityType().getProperties()) {
                                                                                        String subEntityProName = subEntityProperty.getName();
                                                                                        if (!(subXBillEntry.get(subEntityProName) instanceof DynamicObjectCollection) && !(subXBillEntry.get(subEntityProName) instanceof LinkEntryProp)) {
                                                                                            try {
                                                                                                if (!subEntityProName.equals("id")) {
                                                                                                    if (subEntityProName.equals(subfieldmap.get("changetype"))) {
                                                                                                        subSrcBillEntry.set(subEntityProName, BizChangeTypeEnum.UPDATE.getValue());
                                                                                                    } else {
                                                                                                        ChangeModelHelper.SetPropertyValue(subSrcBillEntry, subEntityProName, subXBillEntry.get(subEntityProName));
                                                                                                    }
                                                                                                }
                                                                                            } catch (
                                                                                                    Exception ignored) {
                                                                                            }
                                                                                        }
                                                                                    }
                                                                                } else if (BizChangeTypeEnum.UPDATE.getValue().equals(subXBillEntry.get((String) subfieldmap.get("changetype")))) {
                                                                                    var36 = subSrcBillEntrys.iterator();

                                                                                    while (true) {
                                                                                        do {
                                                                                            if (!var36.hasNext()) {
                                                                                                continue label332;
                                                                                            }

                                                                                            subSrcBillEntry = (DynamicObject) var36.next();
                                                                                        } while (subSrcBillEntry.getLong("id") != subXBillEntry.getLong((String) subfieldmap.get("srcid")));

                                                                                        for (String subEnableEntryProperty : subEnableEntryPropertys) {
                                                                                            ChangeModelHelper.SetPropertyValue(subSrcBillEntry, subEnableEntryProperty, subXBillEntry.get(subEnableEntryProperty));
                                                                                        }
                                                                                    }
                                                                                }
                                                                            }
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    } else {

                                                        if (BizChangeTypeEnum.CANCEL.getValue().equals(xBillEntry.get((String) fieldmap.get("changetype")))) {
                                                            String rowCancel = this.getOption().getVariableValue("rowcancel", "true");
                                                            if (Boolean.parseBoolean(rowCancel)) {
                                                                Iterator<DynamicObject> var26 = srcBillEntrys.iterator();

                                                                while (true) {
                                                                    DynamicObject srcBillEntry;
                                                                    do {
                                                                        if (!var26.hasNext()) {
                                                                            continue label265;
                                                                        }

                                                                        srcBillEntry = (DynamicObject) var26.next();
                                                                    } while (srcBillEntry.getLong("id") != xBillEntry.getLong((String) fieldmap.get("srcid")));

                                                                    try {
                                                                        srcBillEntrys.remove(srcBillEntry);
                                                                        break;
                                                                    } catch (Exception ignored) {
                                                                    }
                                                                }
                                                            }
                                                        } else if (BizChangeTypeEnum.ADDNEW.getValue().equals(xBillEntry.get((String) fieldmap.get("changetype")))) {
                                                            DynamicObject srcBillEntry = srcBillEntrys.addNew();

                                                            for (IDataEntityProperty entityProperty : srcBillEntry.getDataEntityType().getProperties()) {
                                                                try {
                                                                    String newEntityProName = entityProperty.getName();
                                                                    if (!(xBillEntry.get(newEntityProName) instanceof DynamicObjectCollection) && !(xBillEntry.get(newEntityProName) instanceof LinkEntryProp)) {
                                                                        if (newEntityProName.equals(fieldmap.get("changetype"))) {
                                                                            srcBillEntry.set(newEntityProName, BizChangeTypeEnum.UPDATE.getValue());
                                                                        } else {
                                                                            ChangeModelHelper.SetPropertyValue(srcBillEntry, newEntityProName, xBillEntry.get(newEntityProName));
                                                                        }
                                                                    }

                                                                    if (xBillEntry.get(newEntityProName) instanceof DynamicObjectCollection) {
                                                                        Map<String, String> newSubFieldmap = this.getXBillEntryAndField(changeModel).get(newEntityProName);
                                                                        subEntityChangeTypePro = (String) newSubFieldmap.get("changetype");
                                                                        subXBillEntrys = (DynamicObjectCollection) xBillEntry.get(newEntityProName);
                                                                        subXBillEntrys = srcBillEntry.getDynamicObjectCollection(newEntityProName);
                                                                        Iterator<DynamicObject> var33 = subXBillEntrys.iterator();

                                                                        label259:
                                                                        while (var33.hasNext()) {
                                                                            subXBillEntry = (DynamicObject) var33.next();
                                                                            subXBillEntry = subXBillEntrys.addNew();
                                                                            var36 = subXBillEntry.getDataEntityType().getProperties().iterator();

                                                                            while (true) {
                                                                                while (true) {
                                                                                    String newSubEntityProName;
                                                                                    do {
                                                                                        do {
                                                                                            if (!var36.hasNext()) {
                                                                                                continue label259;
                                                                                            }

                                                                                            IDataEntityProperty subEntityProperty = (IDataEntityProperty) var36.next();
                                                                                            newSubEntityProName = subEntityProperty.getName();
                                                                                        } while (subXBillEntry.get(newSubEntityProName) instanceof DynamicObjectCollection);
                                                                                    } while (subXBillEntry.get(newSubEntityProName) instanceof LinkEntryProp);

                                                                                    if (StringUtils.isNotEmpty(subEntityChangeTypePro) && subEntityChangeTypePro.equals(newSubEntityProName)) {
                                                                                        subXBillEntry.set(newSubEntityProName, BizChangeTypeEnum.UPDATE.getValue());
                                                                                    } else {
                                                                                        ChangeModelHelper.SetPropertyValue(subXBillEntry, newSubEntityProName, subXBillEntry.get(newSubEntityProName));
                                                                                    }
                                                                                }
                                                                            }
                                                                        }
                                                                    }
                                                                } catch (Exception ignored) {
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }

                            long finishBillEntryValueTime = System.currentTimeMillis();
                            LOGGER.info("BizValidPerformance--finishBillEntryValueTime: " + new Date(finishBillEntryValueTime));
                            LOGGER.info("BizValidPerformance--finishBillEntryValueUse: " + (finishBillEntryValueTime - finishBillHeadValueTime) + "ms");
                            SaveServiceHelper.save(new DynamicObject[]{srcBill});
                            long finishTime = System.currentTimeMillis();
                            LOGGER.info("BizValidPerformance--finishTime: " + new Date(finishTime));
                            LOGGER.info("BizValidPerformance--finishUse: " + (finishTime - beginTime) + "ms");
                            QFilter qFilter = new QFilter("xbillid", "in", bill.getPkValue());
                            DynamicObject changeReCordObj = BusinessDataServiceHelper.loadSingle("yem_changeresume", "xvalidstatus", new QFilter[]{qFilter});
                            if (!CommonUtils.isNull(changeReCordObj)) {
                                String xValidStatus = (String) changeReCordObj.get("xvalidstatus");
                                if (xValidStatus.equals(BizValidStatusEnum.UNVALID.getValue())) {
                                    changeReCordObj.set("xvalidstatus", BizValidStatusEnum.VALID.getValue());
                                    SaveServiceHelper.update(new DynamicObject[]{changeReCordObj});
                                }
                            }
                        }
                    }
                }

                ChangeModelHelper.excutePluginMethod(changeModel, "afterXBillBizValid",
                        bill);
            }
        }

    }

    protected Map<String, Map<String, String>> getXBillEntryAndField(DynamicObject changeModel) {
        Map<String, Map<String, String>> result = ChangeModelHelper.getXBillEntryAndOp(changeModel);
        if (result.size() != 0) {
            return result;
        } else {
            Map<String, String> value = new HashMap<>();
            value.put("entity", "billentry");
            value.put("changetype", "billentrychangetype");
            value.put("srcid", "billentrysrcid");
            result.put(value.get("entity"), value);
            return result;
        }
    }
}