package yem.base.common.module.version.op;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import kd.bos.dataentity.OperateOption;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.metadata.IDataEntityType;
import kd.bos.dataentity.serialization.SerializationUtils;
import kd.bos.entity.*;
import kd.bos.entity.filter.FilterBuilder;
import kd.bos.entity.filter.FilterCondition;
import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
import kd.bos.entity.plugin.AddValidatorsEventArgs;
import kd.bos.entity.plugin.PreparePropertysEventArgs;
import kd.bos.entity.plugin.args.EndOperationTransactionArgs;
import kd.bos.entity.validate.AbstractValidator;
import kd.bos.entity.validate.ErrorLevel;
import kd.bos.exception.KDBizException;
import kd.bos.form.IFormView;
import kd.bos.form.operate.View;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.servicehelper.operation.OperationServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import yem.base.common.module.version.helper.NewVersionHelper;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 版本变更-服务插件
 *
 * @author longh
 * @description:
 * @date 2021年11月11日 下午3:54:22
 */
public class NewVersionOp extends AbstractOperationServicePlugIn {
    private static JSONObject validateMsg = new JSONObject();

    @Override
    public void onPreparePropertys(PreparePropertysEventArgs e) {
        super.onPreparePropertys(e);
        List<String> fieldKeys = e.getFieldKeys();
        fieldKeys.add("billstatus");//单据状态
        fieldKeys.add("yem_masterid");//主数据内码
        fieldKeys.add("yem_version");//版本号
        fieldKeys.add("yem_effective");//已生效
        fieldKeys.add("yem_changing");//变更中
    }

    @Override
    public void onAddValidators(AddValidatorsEventArgs e) {
        super.onAddValidators(e);
        e.addValidator(new AbstractValidator() {

            @Override
            public void validate() {
                validateMsg.clear();
                String operateKey = this.getOperateKey();
                String entityNumber = this.getEntityKey();
                DynamicObject tplObj = NewVersionHelper.queryTemplate(entityNumber);//查询是否配置变更功能
                if (tplObj == null) {
                    return;
                }
                ExtendedDataEntity[] dataEntities = this.getDataEntities();
                for (ExtendedDataEntity extendedDataEntity : dataEntities) {
                    validateMsg.put("tplObj", tplObj);
                    boolean yem_requirebill = entityNumber.equals(tplObj.getString("yem_requirebill.number"));
                    boolean yem_changebill = entityNumber.equals(tplObj.getString("yem_changebill.number"));
                    if ("newversion".equals(operateKey)) {//变更
                        this.checkOnlyOneData();
                        if (yem_requirebill) {
                            this.newVersionValidate(extendedDataEntity, tplObj);
                        } else {
                            this.checkEnableOp(extendedDataEntity);
                        }
                    }
                    if ("versionhistory".equals(operateKey)) {//变更履历
                        this.checkOnlyOneData();
                        this.historyValidate(extendedDataEntity, tplObj, entityNumber);
                    }
                    //删除历史版本的一个校验
                    if("deletehistory".equals(operateKey)){
                        this.checkOnlyOneData();
                        this.deleteHistoryValidate(extendedDataEntity,tplObj);//删除历史版本的校验器
                    }
                    if ("submit".equals(operateKey)) {//提交
                        if (yem_changebill) {
                            this.checkRuleValidate(extendedDataEntity, tplObj);
                        }
                    }
                    if ("audit".equals(operateKey)) {//审核
                        if (yem_changebill) {
                            this.effectValidate(extendedDataEntity, tplObj);
                        }
                    }
                    if ("unaudit".equals(operateKey)) {//反审核
                        this.unAuditValidate(extendedDataEntity, tplObj);
                    }
                    if ("effectchange".equals(operateKey)) {//生效
                        if (yem_changebill) {
                            this.effectValidate(extendedDataEntity, tplObj);
                        } else {
                            this.checkEnableOp(extendedDataEntity);
                        }
                    }
                }
            }

            private void deleteHistoryValidate(ExtendedDataEntity extendedDataEntity, DynamicObject tplObj) {
                //获取表单的状态是否已审核，并且获取是否变更生效，在获取版本号，如果是已审核状态，并且版本号大于1并且是否版本生效是true则允许删除否则提示不能删除
                DynamicObject dataEntity = extendedDataEntity.getDataEntity();
                String billstatus = dataEntity.getString("billstatus");
                if (!"C".equals(billstatus)) {
                    this.addErrorMessage(extendedDataEntity, "当前单据未审核，不允许删除操作。");
                }
                if (!dataEntity.getBoolean("yem_effective")) {
                    this.addErrorMessage(extendedDataEntity, "当前版本未生效，不允许删除操作。");
                }
                int version = dataEntity.getInt("yem_version");
                if (version == 1) {
                    this.addErrorMessage(extendedDataEntity, "当前版本是初始版本，不允许删除操作。");
                }
            }

            /**
             * 检查是否允许的操作
             * @param extendedDataEntity
             */
            private void checkEnableOp(ExtendedDataEntity extendedDataEntity) {
                this.addErrorMessage(extendedDataEntity, "不允许的操作。");
            }

            /**
             * 检查是否批量操作，批量操作抛出异常
             * @return
             */
            private void checkOnlyOneData() {
                ExtendedDataEntity[] dataEntities = this.getDataEntities();
                if (dataEntities.length > 1) {
                    throw new KDBizException("只能选中一张单据进行操作。");
                }
            }

            /**
             * 审核-生效-校验器
             * @param extendedDataEntity
             * @param tplObj
             */
            private void effectValidate(ExtendedDataEntity extendedDataEntity, DynamicObject tplObj) {
                DynamicObject dataEntity = extendedDataEntity.getDataEntity();
                //检测是否已生效
                boolean yem_effective = dataEntity.getBoolean("yem_effective");
                if (yem_effective) {
                    this.addErrorMessage(extendedDataEntity, "变更已生效，不允许再次生效。");
                }
            }

            /**
             * 反审核-校验器
             //			 * @param checkOnlyOneData
             * @param tplObj
             */
            private void unAuditValidate(ExtendedDataEntity extendedDataEntity, DynamicObject tplObj) {
                DynamicObject dataEntity = extendedDataEntity.getDataEntity();
                //检测是否已生效
                boolean yem_effective = dataEntity.getBoolean("yem_effective");
                if (yem_effective) {
                    this.addErrorMessage(extendedDataEntity, "已变更生效不允许反审核。");
                }
            }

            /**
             * 变更-校验器
             * @param extendedDataEntity
             * @param tplObj
             */
            private void newVersionValidate(ExtendedDataEntity extendedDataEntity, DynamicObject tplObj) {
                DynamicObject dataEntity = extendedDataEntity.getDataEntity();
                String billstatus = dataEntity.getString("billstatus");
                if (!"C".equals(billstatus)) {
                    this.addErrorMessage(extendedDataEntity, "当前单据未审核，不允许变更。");
                } else {
                    String yem_requirebill = tplObj.getString("yem_requirebill.number");
                    String yem_changebill = tplObj.getString("yem_changebill.number");
                    DynamicObject showBill = BusinessDataServiceHelper.loadSingle(yem_changebill, "id", new QFilter[]{new QFilter("yem_masterid", QCP.equals, dataEntity.getPkValue()), new QFilter("yem_effective", QCP.equals, false)});
                    validateMsg.put("tplPkId", tplObj.getPkValue());
                    validateMsg.put("yem_requirebill", yem_requirebill);
                    validateMsg.put("yem_changebill", yem_changebill);
                    if (showBill != null) {
                        validateMsg.put("pkId", showBill.getPkValue().toString());
                        this.addWarningMessage(extendedDataEntity, "检测到有未生效的变更单，无法创建新的变更单，是否前往查看？");
                    }
                }
            }

            /**
             * 变更履历-校验器
             * @param extendedDataEntity
             * @param tplObj
             * @param entityNumber
             */
            private void historyValidate(ExtendedDataEntity extendedDataEntity, DynamicObject tplObj, String entityNumber) {
                DynamicObject dataEntity = extendedDataEntity.getDataEntity();
                String yem_requirebill = tplObj.getString("yem_requirebill.number");
                String yem_changebill = tplObj.getString("yem_changebill.number");
                Object pkId = null;
                if (entityNumber.equals(yem_requirebill)) {
                    pkId = dataEntity.getPkValue();
                } else if (entityNumber.equals(yem_changebill)) {
                    pkId = dataEntity.get("yem_masterid");
                }
                if (pkId != null) {
                    DynamicObject[] bills = BusinessDataServiceHelper.load(yem_changebill, "id", new QFilter[]{new QFilter("yem_masterid", QCP.equals, pkId)});
                    if (bills.length == 0) {
                        this.addErrorMessage(extendedDataEntity, "无变更记录。");
                    } else {
                        validateMsg.put("tplPkId", tplObj.getPkValue());
                        validateMsg.put("yem_requirebill", yem_requirebill);
                        validateMsg.put("yem_changebill", yem_changebill);
                        validateMsg.put("pkId", pkId);
                    }
                }
            }

            /**
             * 提交-校验器（依据变更方案校验）
             * @param extendedDataEntity
             * @param tplObj
             */
            private void checkRuleValidate(ExtendedDataEntity extendedDataEntity, DynamicObject tplObj) {
                DynamicObject dataEntity = extendedDataEntity.getDataEntity();
                String yem_changebill = tplObj.getString("yem_changebill.number");
                MainEntityType dataType = EntityMetadataCache.getDataEntityType(yem_changebill);
                //提交前先保存
                SaveServiceHelper.saveOperate(yem_changebill, new DynamicObject[]{dataEntity}, OperateOption.create());

                DynamicObjectCollection yem_checkmap = tplObj.getDynamicObjectCollection("yem_checkmap");
                for (DynamicObject row : yem_checkmap) {
                    //验证校验是否启用
                    if (!row.getBoolean("yem_isused")) {
                        continue;
                    }
                    String yem_checklevel = row.getString("yem_checklevel");//校验级别
                    String yem_checkentity = row.getString("yem_checkentity");//校验实体
                    String yem_checkjson = row.getString("yem_checkjson");//序列化校验条件

                    if (!yem_checkjson.isEmpty()) {
                        JSONObject parseObject = JSON.parseObject(yem_checkjson);
                        if (parseObject == null) {
                            continue;
                        }
                        boolean yem_truethrow = parseObject.getBoolean("yem_truethrow");//为真提示
                        String yem_message = parseObject.getString("yem_message");//提示信息
                        String yem_filtergridap = parseObject.getString("yem_filtergridap");//通用过滤条件

                        List<QFilter> qFilters = new ArrayList<>();
                        qFilters.add(new QFilter("id", QCP.equals, dataEntity.getPkValue()));
                        FilterCondition filterCondition = SerializationUtils.fromJsonString(yem_filtergridap, FilterCondition.class);
                        if (filterCondition != null) {
                            FilterBuilder fBuilder = new FilterBuilder(dataType, filterCondition);
                            fBuilder.buildFilter();
                            qFilters.addAll(fBuilder.getQFilters());
                        }
                        //查询满足条件的数据并注入校验
                        if (yem_changebill.equals(yem_checkentity)) {
                            //表头处理
                            DynamicObjectCollection query = QueryServiceHelper.query(yem_changebill, "id", qFilters.toArray(new QFilter[0]));
                            List<Object> pkIds = new ArrayList<>();
                            query.forEach((v) -> {
                                pkIds.add(v.get("id"));
                            });
                            if ((pkIds.contains(dataEntity.getPkValue()) && yem_truethrow) || (!pkIds.contains(dataEntity.getPkValue()) && !yem_truethrow)) {
                                String errorMsg = String.format("【单据头】%s", yem_message);
                                this.addLevelMessage(extendedDataEntity, yem_checklevel, errorMsg);
                            }
                        } else {
                            Map<String, EntityType> allEntities = dataType.getAllEntities();
                            EntityType entityType = allEntities.get(yem_checkentity);
                            if (entityType instanceof EntryType && !(entityType instanceof SubEntryType)) {
                                //分录处理
                                DynamicObjectCollection query = QueryServiceHelper.query(yem_changebill, yem_checkentity, qFilters.toArray(new QFilter[0]));
                                List<Object> pkIds = new ArrayList<>();
                                query.forEach((v) -> {
                                    pkIds.add(v.get(yem_checkentity));
                                });
                                DynamicObjectCollection dyObjCollection = dataEntity.getDynamicObjectCollection(yem_checkentity);
                                for (DynamicObject dyObj : dyObjCollection) {
                                    if ((pkIds.contains(dyObj.getPkValue()) && yem_truethrow) || (!pkIds.contains(dyObj.getPkValue()) && !yem_truethrow)) {
                                        String seq = dyObj.getString("seq");//分录序号
                                        String displayName = entityType.getDisplayName().getLocaleValue();//分录名称
                                        String errorMsg = String.format("【%s】第%s行，%s", displayName, seq, yem_message);
                                        this.addLevelMessage(extendedDataEntity, yem_checklevel, errorMsg);
                                    }
                                }
                            } else if (entityType instanceof SubEntryType) {
                                //子分录处理
                                IDataEntityType parent = entityType.getParent();
                                String parentKey = parent.getName();
                                String selectId = parentKey + "." + yem_checkentity;
                                DynamicObjectCollection query = QueryServiceHelper.query(yem_changebill, selectId, qFilters.toArray(new QFilter[0]));
                                List<Object> pkIds = new ArrayList<>();
                                query.forEach((v) -> {
                                    pkIds.add(v.get(selectId));
                                });
                                DynamicObjectCollection dyObjCollection = dataEntity.getDynamicObjectCollection(parentKey);
                                for (DynamicObject dyObj : dyObjCollection) {
                                    String seq = dyObj.getString("seq");//分录序号
                                    String displayName = parent.getDisplayName().getLocaleValue();//分录名称
                                    DynamicObjectCollection subDyObjCollection = dyObj.getDynamicObjectCollection(yem_checkentity);
                                    for (DynamicObject subDyObj : subDyObjCollection) {
                                        if ((pkIds.contains(subDyObj.getPkValue()) && yem_truethrow) || (!pkIds.contains(subDyObj.getPkValue()) && !yem_truethrow)) {
                                            String subSeq = subDyObj.getString("seq");//子分录序号
                                            String subDisplayName = entityType.getDisplayName().getLocaleValue();//子分录名称
                                            String errorMsg = String.format("【%s】第%s行【%s】第%s行，%s", displayName, seq, subDisplayName, subSeq, yem_message);
                                            this.addLevelMessage(extendedDataEntity, yem_checklevel, errorMsg);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            /**
             * 根据校验等级注入校验结果
             * @param extendedDataEntity
             * @param yem_checklevel
             * @param errorMsg
             */
            private void addLevelMessage(ExtendedDataEntity extendedDataEntity, String yem_checklevel, String errorMsg) {
                if ("A".equals(yem_checklevel)) {
                    this.addMessage(extendedDataEntity, "警告，允许忽略：" + errorMsg, ErrorLevel.Warning);
                } else if ("B".equals(yem_checklevel)) {
                    this.addMessage(extendedDataEntity, "错误，立即终止：" + errorMsg, ErrorLevel.Error);
                } else if ("C".equals(yem_checklevel)) {
                    this.addMessage(extendedDataEntity, "错误，立即终止：" + errorMsg, ErrorLevel.FatalError);
                }
            }

        });
    }

    @Override
    public void endOperationTransaction(EndOperationTransactionArgs e) {
        super.endOperationTransaction(e);
        if (validateMsg.isEmpty()) {
            return;
        }
        String operationKey = e.getOperationKey();
        DynamicObject[] dataEntities = e.getDataEntities();
        for (DynamicObject dataEntity : dataEntities) {
            switch (operationKey) {
                case "delete":
                    this.deleteNewVersion(dataEntity);
                    break;
                case "newversion":
                    this.createNewVersion(dataEntity);
                    break;
                case "audit":
                case "effectchange":
                    this.effectNewVersion(dataEntity, operationKey);
                    break;
                case "versionhistory":
                    this.versionHistory(dataEntity, operationKey);
                    break;
                case "deletehistory"://删除历史版本
                    this.deleteHistory(dataEntity, operationKey);
                    break;
                default:
                    break;
            }
        }
    }

    private void deleteHistory(DynamicObject dataEntity, String operationKey) {
        DynamicObject tplObj = (DynamicObject) validateMsg.get("tplObj");
        String entityNumber = dataEntity.getDynamicObjectType().getName();
        boolean yem_requirebill = entityNumber.equals(tplObj.getString("yem_requirebill.number"));
        if (yem_requirebill) {
            NewVersionHelper.deleteAllChangesForMaster(tplObj, dataEntity);
        }
    }

    private void deleteNewVersion(DynamicObject dataEntity) {
        DynamicObject tplObj = (DynamicObject) validateMsg.get("tplObj");
        String entityNumber = dataEntity.getDynamicObjectType().getName();
        boolean yem_changebill = entityNumber.equals(tplObj.getString("yem_changebill.number"));
        if (yem_changebill) {
            NewVersionHelper.deleteChange(tplObj, dataEntity);
        }
    }

    /**
     * @param dataEntity
     * @param operationKey
     */
    private void versionHistory(DynamicObject dataEntity, String operationKey) {
//		JSONObject clone = (JSONObject) validateMsg.clone();
//		clone.remove("tplObj");
//		this.getOperationResult().setMessage(clone.toJSONString());
        validateMsg.remove("tplObj");
        this.getOperationResult().setMessage(validateMsg.toJSONString());
    }

    /**
     * 点击【变更】按钮，新建新版本单据
     *
     * @param dataEntity
     */
    private void createNewVersion(DynamicObject dataEntity) {
        DynamicObject tplObj = (DynamicObject) validateMsg.get("tplObj");
        String pkId = validateMsg.getString("pkId");
        if (pkId == null) {
            DynamicObject newVersion = NewVersionHelper.newVersion(tplObj, dataEntity.getPkValue());
            validateMsg.put("pkId", newVersion.getPkValue());
        }
//		JSONObject clone = (JSONObject) validateMsg.clone();
//		clone.remove("tplObj");
//		this.getOperationResult().setMessage(clone.toJSONString());
        validateMsg.remove("tplObj");
        this.getOperationResult().setMessage(validateMsg.toJSONString());
    }

    /**
     * 变更单生效
     *
     * @param dataEntity
     * @param operationKey
     */
    private void effectNewVersion(DynamicObject dataEntity, String operationKey) {
        DynamicObject tplObj = (DynamicObject) validateMsg.get("tplObj");
        String entityNumber = dataEntity.getDynamicObjectType().getName();
        boolean yem_changebill = entityNumber.equals(tplObj.getString("yem_changebill.number"));
        //检测是否是方案配置的生效操作
        String effectOption = tplObj.getString("yem_effectoption");
        if (operationKey.equals(effectOption) && yem_changebill) {
            NewVersionHelper.effectChange(tplObj, dataEntity);
        }
    }

}
