package com.yem.wm.sys.formplugin.form;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yem.wm.sys.formplugin.dynamic.VersionResumeBillInfoEdit;
import com.yem.wm.sys.utils.NewVersionHelper;
import com.yem.wm.utils.DynamicObjectUtil;

import kd.bos.bill.AbstractBillPlugIn;
import kd.bos.bill.BillShowParameter;
import kd.bos.bill.OperationStatus;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.metadata.IDataEntityProperty;
import kd.bos.dataentity.metadata.IDataEntityType;
import kd.bos.dataentity.metadata.clr.DataEntityPropertyCollection;
import kd.bos.dataentity.metadata.dynamicobject.DynamicLocaleProperty;
import kd.bos.dataentity.metadata.dynamicobject.DynamicObjectType;
import kd.bos.dataentity.metadata.dynamicobject.DynamicProperty;
import kd.bos.entity.EntityMetadataCache;
import kd.bos.entity.EntityType;
import kd.bos.entity.EntryType;
import kd.bos.entity.MainEntityType;
import kd.bos.entity.SubEntryType;
import kd.bos.entity.botp.runtime.BFRow;
import kd.bos.entity.datamodel.IDataModel;
import kd.bos.entity.operate.result.OperationResult;
import kd.bos.entity.property.EntryProp;
import kd.bos.entity.property.MulBasedataProp;
import kd.bos.entity.report.CellStyle;
import kd.bos.form.ClientActions;
import kd.bos.form.FormShowParameter;
import kd.bos.form.IClientViewProxy;
import kd.bos.form.IFormView;
import kd.bos.form.ShowType;
import kd.bos.form.control.EntryGrid;
import kd.bos.form.events.AfterDoOperationEventArgs;
import kd.bos.form.events.BeforeDoOperationEventArgs;
import kd.bos.form.operate.FormOperate;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.botp.BFTrackerServiceHelper;

/**
 * 版本变更功能基类
 * @description:单据插件
 * @author longh
 * @date 2021年9月7日 下午2:49:09
 */
public class AbstractVersionBillPlugIn extends AbstractBillPlugIn {


    private static final String KEY_REL = NewVersionHelper.KEY_REL;
    private static final String KEY_LIST = NewVersionHelper.KEY_LIST;
    //定义变更功能的可见控件标识
    private static final String[] VCTRLS = {"yem_versionhistory", "yem_version", "yem_changeman", "yem_changedate", "yem_effector", "yem_effectdate"};
    //定义变更功能的仅需求单据可见控件标识
    private static final String[] S = {"yem_newversion", "yem_changing"};
    //定义变更功能的仅变更单据可见控件标识
    private static final String[] V = {"yem_effective"};
    //定义变更功能的仅变更单据不可见控件标识
    private static final String[] UNV = {"bar_new", "bar_submitandnew", "bar_push", "bar_more", "yem_push", "yem_track",
            "yem_bizfile", "yem_bizaction", "yem_changeco", "yem_changepayer", "yem_changegys"};

    @Override
    public void afterBindData(EventObject e) {
        super.afterBindData(e);
        this.initNewVersionSetting();
        this.initHighLightSetting();
    }

    /**
     * 设置新版本界面字段属性
     */
    private void initNewVersionSetting() {
        IDataModel model = this.getModel();
        IFormView view = this.getView();
        String entityNumber = model.getDataEntityType().getName();
        DynamicObject tplObj = NewVersionHelper.queryTemplate(entityNumber);
        if(tplObj != null) {
            //设置控件可见（变更单/非变更单）
            view.setVisible(true, VCTRLS);
            String yem_requirebill = tplObj.getString("yem_requirebill.number");
            String yem_changebill = tplObj.getString("yem_changebill.number");
            if(entityNumber.equals(yem_requirebill)) {
                //设置控件可见（非变更单）
                view.setVisible(true, S);
            }else if(entityNumber.equals(yem_changebill)) {
                //设置字段可用（变更单）
                String billstatus = (String) model.getValue("billstatus");
                if("A".equals(billstatus)) {
                    List<String> ableList = new ArrayList<>();
                    List<String> unableList = new ArrayList<>();
                    DynamicObjectCollection colsmap = tplObj.getDynamicObjectCollection("yem_colsmap");
                    for (DynamicObject colmap : colsmap) {
                        if(colmap.getBoolean("yem_enable")) {
                            ableList.add(colmap.getString("yem_billcolno"));
                        }else {
                            unableList.add(colmap.getString("yem_billcolno"));
                        }
                    }
                    //表头处理
                    view.setEnable(true, ableList.toArray(new String[0]));
                    view.setEnable(false, unableList.toArray(new String[0]));
                    //分录处理
                    int size = 0;
                    DynamicObject dataEntity = model.getDataEntity(true);
                    DynamicObjectType dyObjType = dataEntity.getDynamicObjectType();
                    DataEntityPropertyCollection properties = dyObjType.getProperties();
                    for(IDataEntityProperty property : properties) {
                        String name = property.getName();
                        if(property instanceof EntryProp) {
                            DynamicObjectCollection dyObjCollection = dataEntity.getDynamicObjectCollection(name);
                            size = dyObjCollection.size() > size ? dyObjCollection.size() : size;
                        }
                    }
                    for (int i = 0; i < size; i++) {
                        view.setEnable(true, i, ableList.toArray(new String[0]));
                        view.setEnable(false, i, unableList.toArray(new String[0]));
                    }
                }
                //设置控件可见（变更单）
                view.setVisible(true, V);
                String effectOption = tplObj.getString("yem_effectoption");
                if(!"audit".equals(effectOption)) {
                    view.setVisible(true, "yem_effectchange");
                }
                //设置控件不可见（变更单）
                view.setVisible(false, UNV);
            }
        }//设置未配置变更功能的单据列表控件可见性
        else {
            view.setVisible(false, S);
            view.setVisible(false, V);
            view.setVisible(false, VCTRLS);
        }
    }

    @Override
    public void afterDoOperation(AfterDoOperationEventArgs e) {
        super.afterDoOperation(e);
        IFormView view = this.getView();
        String operateKey = e.getOperateKey();
        switch (operateKey) {
            case "newversion":
                viewNewVersion(e, view);
                break;
            case "versionhistory":
                viewVersionHistory(e, view);
                break;
            case "audit":
            case "effectchange":
                OperationResult operationResult = e.getOperationResult();
                if(operationResult.isSuccess()) {
                    view.invokeOperation("refresh");
                }
                break;
            default:
                break;
        }
    }

    /**
     * 变更操作生成变更单成功后，跳转到变更单
     * @param e
     * @param view
     */
    public static void viewNewVersion(AfterDoOperationEventArgs e, IFormView view) {
        OperationResult operationResult = e.getOperationResult();
        if(operationResult.isSuccess()) {
            view.invokeOperation("refresh");
            String message = operationResult.getMessage();
            JSONObject parseObject = JSON.parseObject(message);
            if(parseObject != null) {
                BillShowParameter showParameter = new BillShowParameter();
                showParameter.setFormId(parseObject.getString("yem_changebill"));
                showParameter.setPkId(parseObject.getString("pkId"));
                showParameter.setStatus(OperationStatus.EDIT);
                showParameter.getOpenStyle().setShowType(ShowType.MainNewTabPage);
                view.showForm(showParameter);
            }
        }else {

        }
    }

    /**
     * 编辑页面点击【历史版本】按钮，查看变更单记录
     * @param e
     * @param view
     */
    public static void viewVersionHistory(AfterDoOperationEventArgs e, IFormView view) {
        OperationResult operationResult = e.getOperationResult();
        if(operationResult.isSuccess()) {
            String message = operationResult.getMessage();
            JSONObject parseObject = JSON.parseObject(message);
            if(parseObject != null) {
                FormShowParameter showParameter = new FormShowParameter();
                showParameter.setFormId(KEY_LIST);
                showParameter.setStatus(OperationStatus.EDIT);
                showParameter.getOpenStyle().setShowType(ShowType.MainNewTabPage);
                showParameter.setCustomParam("data", parseObject);
                view.showForm(showParameter);
            }
        }
    }

    @Override
    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
        super.beforeDoOperation(args);
        FormOperate formOperate = (FormOperate) args.getSource();
        switch (formOperate.getType()) {//操作类型
            case "newentry"://新增分录
            case "copyentryrow"://复制分录
            case "insertentry	"://插入分录
                this.checkAddRow(args, formOperate);
                break;
            case "deleteentry"://删除分录
                this.checkDeleteRow(args, formOperate);
                break;
            default:
                break;
        }
    }

    /**
     * 增行前校验：查询分录是否由上游携带，是则阻断增行并提示
     * @param args
     * @param formOperate
     */
    private void checkAddRow(BeforeDoOperationEventArgs args, FormOperate formOperate) {
        IFormView view = this.getView();
        IDataModel model = this.getModel();
        String entityNumber = model.getDataEntityType().getName();
        DynamicObject tplObj = NewVersionHelper.queryTemplate(entityNumber);//校验是否变更单
        if(tplObj != null && entityNumber.equals(tplObj.getString("yem_changebill.number"))) {
            String yem_requirebill = tplObj.getString("yem_requirebill.number");
            //查询主数据分录内码
            List<Long> entryIds = new ArrayList<>();
            DynamicObject requirebill = BusinessDataServiceHelper.loadSingle(model.getValue("yem_masterid"), yem_requirebill);
            String entryKey = (String) formOperate.getParameter().get("entryId");//分录标识

            MainEntityType dataType  = EntityMetadataCache.getDataEntityType(yem_requirebill);
            Map<String, EntityType> allEntities = dataType.getAllEntities();
            EntityType entityType = allEntities.get(entryKey);
            if(entityType instanceof EntryType && !(entityType instanceof SubEntryType)) {
                //分录处理
                for (DynamicObject obj : requirebill.getDynamicObjectCollection(entryKey)) {
                    entryIds.add(obj.getLong("id"));
                }
            }else if(entityType instanceof SubEntryType) {
                //子分录处理
                IDataEntityType parent = entityType.getParent();
                String parentKey = parent.getName();
                for (DynamicObject obj : requirebill.getDynamicObjectCollection(parentKey)) {
                    for (DynamicObject subObj : obj.getDynamicObjectCollection(entryKey)) {
                        entryIds.add(subObj.getLong("id"));
                    }
                }
            }
            if(entryIds.size() > 0) {
                //查询分录是否由上游携带，是则阻断增行并提示
                @SuppressWarnings("deprecation")
                List<BFRow> loadSourceRowIds = BFTrackerServiceHelper.loadSourceRowIds(yem_requirebill, entryKey, entryIds.toArray(new Long[0]));
                if(loadSourceRowIds.size() > 0) {
                    args.setCancel(true);//阻断增行
                    view.showTipNotification("该分录为上游关联数据，不允许增行。");
                }
            }
        }
    }

    /**
     * 删行前校验：查询分录字段是否满足条件，不满足则阻断删行并提示
     * @param args
     * @param formOperate
     */
    private void checkDeleteRow(BeforeDoOperationEventArgs args, FormOperate formOperate) {
        IFormView view = this.getView();
        IDataModel model = this.getModel();
        String entityNumber = model.getDataEntityType().getName();
        DynamicObject tplObj = NewVersionHelper.queryTemplate(entityNumber);//校验是否变更单
        if(tplObj != null && entityNumber.equals(tplObj.getString("yem_changebill.number"))) {
            String entryKey = (String) formOperate.getParameter().get("entryId");//分录标识
            int index = model.getEntryCurrentRowIndex(entryKey);
            DynamicObject entryRow = model.getEntryRowEntity(entryKey, index);

            StringBuilder errorMsg = new StringBuilder();
            DynamicObjectCollection yem_checkdelrow = tplObj.getDynamicObjectCollection("yem_checkdelrow");
            for (DynamicObject row : yem_checkdelrow) {
                if(entryKey.equals(row.getString("yem_checkdelentity"))) {
                    String yem_checkcolsjson = row.getString("yem_checkcolsjson");
                    JSONArray parseArray = JSON.parseArray(yem_checkcolsjson);
                    if(parseArray != null) {
                        for (Object obj : parseArray) {
                            String colno = obj.toString();
                            BigDecimal bigDecimal = entryRow.getBigDecimal(colno);
                            if(bigDecimal.compareTo(BigDecimal.ZERO) != 0) {
                                DynamicProperty property = entryRow.getDynamicObjectType().getProperty(colno);
                                String displayName = property.getDisplayName() == null ? "" : property.getDisplayName().getLocaleValue();
                                if(errorMsg.length() > 0) {
                                    errorMsg.append("、");
                                }
                                errorMsg.append(displayName);
                            }
                        }
                    }
                }
            }
            if(errorMsg.length() > 0) {
                args.setCancel(true);//阻断删行
                errorMsg.insert(0, "【").append("】").append("不为零，不允许删行。");
                view.showTipNotification(errorMsg.toString());
            }
        }
    }

    /**
     * 设置变更履历比较变色
     */
    private void initHighLightSetting() {
        IDataModel model = this.getModel();
        IFormView view = this.getView();
        IClientViewProxy proxy = this.getView().getService(IClientViewProxy.class);
        FormShowParameter formShowParameter = view.getFormShowParameter();
        Object compareId = formShowParameter.getCustomParam(VersionResumeBillInfoEdit.HighLight);
        if(compareId == null) {
            return;
        }
        DynamicObject selectData = model.getDataEntity(true);
        DynamicObjectType selectType = selectData.getDynamicObjectType();
        DynamicObject compareData = BusinessDataServiceHelper.loadSingle(compareId, selectType);

        //查询变更方案
        DynamicObject queryTemplate = NewVersionHelper.queryTemplate(selectType.getName());
        //查询关联表数据
        QFilter qFilter = new QFilter("yem_tplid", QCP.equals, queryTemplate.getPkValue());
        qFilter.and(new QFilter("yem_masterid", QCP.equals, selectData.getLong("yem_masterid")));
        qFilter.and(new QFilter("yem_xmasterid", QCP.in, new Object[] {selectData.getPkValue(), compareData.getPkValue()}));
        String selectFields = DynamicObjectUtil.getSelectfields(KEY_REL, false);
        DynamicObject[] rels = BusinessDataServiceHelper.load(KEY_REL, selectFields, new QFilter[] { qFilter });

        this.compareDynamicObject(proxy, selectData, compareData, rels);

    }

    private void compareDynamicObject(IClientViewProxy proxy, DynamicObject selectData, DynamicObject compareData, DynamicObject[] rels) {
        compareDynamicObject(proxy, selectData, compareData, rels, null, null);
    }

    private void compareDynamicObject(IClientViewProxy proxy, DynamicObject selectData, DynamicObject compareData, DynamicObject[] rels, String entryKey, Integer rowIndex) {
        ArrayList<CellStyle> csList = new ArrayList<>();
        boolean isEntry = false;
        if(entryKey != null && !entryKey.isEmpty()) {
            isEntry = true;
        }

        DynamicObjectType selectType = selectData.getDynamicObjectType();
        DataEntityPropertyCollection selectProperties = selectType.getProperties();
        for(IDataEntityProperty selectProperty : selectProperties) {
            String name = selectProperty.getName();
            //分录处理
            if(selectProperty instanceof EntryProp) {
                //分录对象
                DynamicObjectCollection compareDynamicObjectCollection = compareData.getDynamicObjectCollection(name);
                DynamicObjectCollection selectDynamicObjectCollection = selectData.getDynamicObjectCollection(name);
                for (int i = 0; i < selectDynamicObjectCollection.size(); i++) {
                    DynamicObject selectObj = selectDynamicObjectCollection.get(i);
                    String src_selectEntryPk = null;
                    String selectEntryPk = selectObj.getPkValue() == null ? "" : selectObj.getPkValue().toString();
                    DynamicObject dynamicObject = null;
                    boolean isadd = false;//是追加的行
                    if(selectEntryPk.length() > 0) {
                        for (DynamicObject compareObj : compareDynamicObjectCollection) {
                            String src_compareEntryPk = null;
                            String compareEntryPk = compareObj.getPkValue() == null ? "" : compareObj.getPkValue().toString();//原始分录ID
                            if(compareEntryPk.length() > 0) {
                                //关联处理
                                for (DynamicObject rel : rels) {
                                    String yem_entitykey = rel.getString("yem_entitykey");//单据体标识
                                    String yem_pkid = rel.getString("yem_pkid");//原始主键
                                    String yem_xpkid = rel.getString("yem_xpkid");//变更单主键
                                    if(name.equals(yem_entitykey) && selectEntryPk.equals(yem_xpkid)) {
                                        src_selectEntryPk = yem_pkid;
                                    }
                                    if(name.equals(yem_entitykey) && compareEntryPk.equals(yem_xpkid)) {
                                        src_compareEntryPk = yem_pkid;
                                    }
                                }
                                if(src_selectEntryPk == null) {
                                    isadd = true;
                                }else if(src_selectEntryPk.equals(src_compareEntryPk)) {
                                    dynamicObject = compareObj;
                                }
                            }
                        }
                    }
                    if(isadd) {
                        ClientActions.createRowStyleBuilder()
                                .setRows(new int[]{i})
                                .setBackColor(VersionResumeBillInfoEdit.HighLightColor)
                                .buildStyle()
                                .build()
                                .invokeControlMethod(proxy, name);
                    }else if(dynamicObject != null){
                        compareDynamicObject(proxy, selectObj, dynamicObject, rels, name, i);
                    }
                }
            }//多选基础资料类处理
            else if(selectProperty instanceof MulBasedataProp) {/*
				MulBasedataProp mulBasedataProp = ((MulBasedataProp) selectProperty);

				IDataEntityType itemType = mulBasedataProp.getItemType();
				ISimpleProperty primaryKey = itemType.getPrimaryKey();
				DynamicObjectCollection compareColls = (DynamicObjectCollection)compareData.get(name);
				compareColls.clear();
				DynamicObjectType toDynamicObjectType = compareColls.getDynamicObjectType();

				DynamicObjectCollection selectColls = (DynamicObjectCollection)selectData.get(name);
				for (DynamicObject coll : selectColls) {
					DynamicObject mulBaseData = new DynamicObject(toDynamicObjectType);
					compareDynamicObject(proxy, coll, mulBaseData);
					primaryKey.resetValue(mulBaseData);
					compareColls.add(mulBaseData);
				}
			*/}//多语言表处理
            else if(selectProperty instanceof DynamicLocaleProperty) {/*
				DynamicLocaleProperty localeProperty = ((DynamicLocaleProperty) selectProperty);

				IDataEntityType itemType = localeProperty.getItemType();
				ISimpleProperty primaryKey = itemType.getPrimaryKey();
				DynamicObjectCollection compareColls = (DynamicObjectCollection)compareData.get(name);
				compareColls.clear();
				DynamicObjectType toDynamicObjectType = compareColls.getDynamicObjectType();

				DynamicObjectCollection selectColls = (DynamicObjectCollection)selectData.get(name);
				for (DynamicObject coll : selectColls) {
					DynamicObject mulBaseData = new DynamicObject(toDynamicObjectType);
					compareDynamicObject(proxy, coll, mulBaseData);
					primaryKey.resetValue(mulBaseData);
					compareColls.add(mulBaseData);
				}
			*/}//字段处理
            else {
                String selectCol = selectData.get(name) == null ? "null" :
                        selectData.get(name).toString() == null ? "null" : selectData.get(name).toString();
                String compareCol = compareData.get(name) == null ? "null" :
                        compareData.get(name).toString() == null ? "null" : compareData.get(name).toString();
                if(selectCol.equals(compareCol)) {
                    continue;
                }
                if(!isEntry) {
                    ClientActions.createControlStyleBuilder().setBackColor(VersionResumeBillInfoEdit.HighLightColor).build(proxy, name);
                }else {
                    CellStyle cs = new CellStyle();
                    cs.setBackColor(VersionResumeBillInfoEdit.HighLightColor);//外边框颜色
                    cs.setFieldKey(name);//列标识
                    cs.setRow(rowIndex);//行索引
                    csList.add(cs);
                }
            }
        }
        if(isEntry) {
            EntryGrid grid = this.getView().getControl(entryKey);//获取分录表体
            if(grid != null) {
                grid.setCellStyle(csList);//设置单元格样式
            }
        }
    }
}
