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

import com.yem.wm.bc.change.common.consts.ChangeTypeEnum;
import com.yem.wm.bc.change.common.pojo.ChangeResumeLogFieldInfo;
import com.yem.wm.bc.change.common.pojo.ChangeResumeLogInfo;
import com.yem.wm.bc.common.CommonUtils;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.entity.OrmLocaleValue;
import kd.bos.dataentity.metadata.ICollectionProperty;
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.DynamicProperty;
import kd.bos.dataentity.metadata.dynamicobject.DynamicPropertyCollection;
import kd.bos.dataentity.resource.ResManager;
import kd.bos.entity.EntityType;
import kd.bos.entity.ValueMapItem;
import kd.bos.entity.property.*;
import kd.bos.servicehelper.inte.InteServiceHelper;
import kd.bos.servicehelper.user.UserServiceHelper;
import kd.bos.util.StringUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author 夜子
 * @ClassName ChangeResumeLogHelper
 * @description: TODO
 * @date 2023年08月03日
 * @version: 1.0
 */
public class ChangeResumeLogHelper {
    private static final String KEY_UPDATE = "*";
    private static final String KEY_ADD = "+";
    private static final String KEY_DELETE = "-";
    private static final String KEY_EQUAL = "=";

    public ChangeResumeLogHelper() {
    }

    public static String getBilljson(DynamicObject srcBill, DynamicObject xBill) {
        if (srcBill != null && xBill != null) {
            ChangeResumeLogInfo cifo = new ChangeResumeLogInfo();
            cifo.setKeyId(String.valueOf(srcBill.getPkValue()));
            cifo.setKeyName(ResManager.loadKDString("单据信息", "ChangeLogHelper_0", "yem-yc-changemodel", new Object[0]));
            cifo.setKeyLine(null);
            String eq = "=";
            String[] billfields = ChangeModelHelper.getCanLogProperty(xBill.getDynamicObjectType());
            DynamicPropertyCollection srcEntitys = (DynamicPropertyCollection)srcBill.getDataEntityType().getProperties();
            if (!CommonUtils.isNull(billfields)) {
                for( String billfield:billfields) {
                    if (srcEntitys.get(billfield) != null) {
                        Object srcField = srcBill.get(billfield);
                        Object newField = xBill.get(billfield);
                        String caption = MetaDataHelper.getPropertyAlias(srcBill.getDataEntityType(), billfield);
                        DynamicProperty srcdp = srcBill.getDynamicObjectType().getProperty(billfield);
                        String oField = displayFieldValue(srcField, srcdp);
                        String nField = displayFieldValue(newField, srcdp);
                        boolean equal = compareField(srcField, newField);
                        ChangeResumeLogFieldInfo logFieldInfo = new ChangeResumeLogFieldInfo();
                        if (equal) {
                            logFieldInfo.setIsequals("=");
                        } else {
                            eq = "*";
                            logFieldInfo.setIsequals("*");
                            if (srcField instanceof BigDecimal && newField instanceof BigDecimal || srcdp instanceof IntegerProp) {
                                nField = nField + compareSizes(srcField, newField);
                            }
                        }

                        logFieldInfo.setFieldname(caption);
                        logFieldInfo.setOldValue(oField);
                        logFieldInfo.setNewValue(nField);
                        cifo.setLogFieldInfo(billfield, logFieldInfo);
                    }
                }
            }

            cifo.setKeyFlag(eq);
            return cifo.formatJson();
        } else {
            return null;
        }
    }

    public static String getBillEntryjson(DynamicObject srcBill, DynamicObject xBill, Map<String, Map<String, String>> xbillEntryAndField) {
        if (srcBill != null && xBill != null) {
            Map<String, String[]> allChangeLogProperty = getAllChangeLogPropertyMap(xBill);
            if (allChangeLogProperty.size() == 0) {
                return "";
            } else {
                List<EntityType> entryEntities = getChildEntities(xBill.getDataEntityType());
                StringBuilder billEntrys = new StringBuilder();

                Iterator<EntityType> var6 = entryEntities.iterator();
                while(true) {
                    EntityType entryEntity;
                    String name;
                    do {
                        if (!var6.hasNext()) {
                            if (billEntrys.length() > 0) {
                                return "{" + billEntrys.substring(0, billEntrys.length() - 1) + "}";
                            }
                            return "";
                        }
                        entryEntity = (EntityType)var6.next();
                        name = entryEntity.getName();
                    } while(xbillEntryAndField.get(name) == null);

                    try {
                        srcBill.getDynamicObjectCollection(name);
                    } catch (Exception var11) {
                        continue;
                    }

                    String[] canLogProperty = (String[])allChangeLogProperty.get(name);
                    if (!CommonUtils.isNull(canLogProperty)) {
                        String billEntry = genFormatString(srcBill, xBill, xbillEntryAndField, entryEntity, allChangeLogProperty);
                        if (!CommonUtils.isNull(billEntry)) {
                            billEntrys.append(billEntry).append(",");
                        }
                    }
                }
            }
        } else {
            return "";
        }
    }

    public static String genFormatString(DynamicObject srcBill, DynamicObject xBill, Map<String, Map<String, String>> xBillEntryAndField, EntityType entryEntity, Map<String, String[]> allCanLogProperty) {
        if (xBill != null && entryEntity != null && !CommonUtils.isNull(xBillEntryAndField) && !CommonUtils.isNull(allCanLogProperty)) {
            String entryName = entryEntity.getName();
            Map<String, String> entryRegisterField = (Map)xBillEntryAndField.get(entryName);
            if (CommonUtils.isNull(entryRegisterField)) {
                return "";
            } else {
                String registerEntryID = (String)entryRegisterField.get("srcid");
                String registerChangeType = (String)entryRegisterField.get("changetype");
                DynamicObjectCollection xBillEntrys = xBill.getDynamicObjectCollection(entryName);
                String[] billEntryFields = (String[])allCanLogProperty.get(entryName);
                if (billEntryFields.length > 0 && !CommonUtils.isNull(xBillEntrys)) {
                    StringBuilder fieldJson = new StringBuilder();
                    ChangeResumeLogInfo fieldinfo = new ChangeResumeLogInfo();
                    fieldinfo.setKey_caption(entryName);
                    int rows = 1;
                    Iterator var14 = xBillEntrys.iterator();

                    while(true) {
                        String eq;
                        ChangeResumeLogInfo cifo;
                        StringBuilder childField;
                        String changetype;
                        label152:
                        while(true) {
                            if (!var14.hasNext()) {
                                if (fieldJson.length() > 0) {
                                    fieldJson = new StringBuilder(fieldJson.substring(0, fieldJson.length() - 1));
                                }

                                return fieldinfo.formatJson(fieldJson.toString());
                            }

                            DynamicObject xBillEntry = (DynamicObject)var14.next();
                            long xBillID = xBillEntry.getLong(registerEntryID);
                            eq = "=";
                            cifo = new ChangeResumeLogInfo();
                            cifo.setKeyId(String.valueOf(xBillID));
                            cifo.setKeyName(String.valueOf(entryEntity.getDisplayName()));
                            cifo.setKeyLine(String.valueOf(rows));
                            ++rows;
                            List<EntityType> childEntities = getChildEntities(xBillEntry.getDataEntityType());
                            childField = new StringBuilder();
                            changetype = String.valueOf(xBillEntry.get(registerChangeType));
                            String billEntryField;
                            String childEnName;
                            if (ChangeTypeEnum.ADDNEW.getValue().equals(changetype)) {
                                String[] var39 = billEntryFields;
                                int var42 = billEntryFields.length;

                                for(int var44 = 0; var44 < var42; ++var44) {
                                    billEntryField = var39[var44];
                                    Object newField = xBillEntry.get(billEntryField);
                                    DynamicProperty newdp = xBillEntry.getDynamicObjectType().getProperty(billEntryField);
                                    childEnName = MetaDataHelper.getEntryPropertyAlias(xBill.getDataEntityType(), entryName, billEntryField);
                                    billEntryField = displayFieldValue(newField, newdp);
                                    if (newField != null) {
                                        if (newField instanceof BigDecimal) {
                                            BigDecimal newBig = (BigDecimal)newField;
                                            if (newBig.compareTo(BigDecimal.valueOf(0L)) != 0) {
                                                billEntryField = billEntryField + "↑";
                                            }
                                        } else if (newField instanceof Integer) {
                                            Integer newBig = (Integer)newField;
                                            if (newBig.compareTo(0) != 0) {
                                                billEntryField = billEntryField + "↑";
                                            }
                                        }
                                    }

                                    ChangeResumeLogFieldInfo logFieldInfo = new ChangeResumeLogFieldInfo();
                                    logFieldInfo.setOldValue((String)null);
                                    logFieldInfo.setNewValue(billEntryField);
                                    logFieldInfo.setIsequals("+");
                                    logFieldInfo.setFieldname(childEnName);
                                    cifo.setLogFieldInfo(billEntryField, logFieldInfo);
                                }

                                eq = "+";
                                if (childEntities.size() <= 0) {
                                    break;
                                }

                                Iterator var40 = childEntities.iterator();

                                while(true) {
                                    if (!var40.hasNext()) {
                                        break label152;
                                    }

                                    EntityType childEntity = (EntityType)var40.next();
                                    childEnName = childEntity.getName();
                                    String[] canLogProperty = (String[])allCanLogProperty.get(childEnName);
                                    if (!CommonUtils.isNull(canLogProperty)) {
                                        String childJson = genFormatString((DynamicObject)null, xBillEntry, xBillEntryAndField, childEntity, allCanLogProperty);
                                        if (!CommonUtils.isNull(childJson)) {
                                            childField.append(childJson).append(",");
                                        }
                                    }
                                }
                            }

                            if (!ChangeTypeEnum.UPDATE.getValue().equals(changetype) && !ChangeTypeEnum.CANCEL.getValue().equals(changetype)) {
                                break;
                            }

                            if (srcBill != null) {
                                DynamicObjectCollection srcBillEntrys = srcBill.getDynamicObjectCollection(entryName);
                                Iterator var23 = srcBillEntrys.iterator();

                                while(true) {
                                    DynamicObject srcBillEntry;
                                    do {
                                        long srcBillID;
                                        long srcBilXlID;
                                        do {
                                            if (!var23.hasNext()) {
                                                break label152;
                                            }

                                            srcBillEntry = (DynamicObject)var23.next();
                                            srcBillID = (Long)srcBillEntry.getPkValue();
                                            srcBilXlID = srcBillEntry.getLong(registerEntryID);
                                        } while(xBillID != srcBillID&&xBillID != srcBilXlID);

                                        String[] var26 = billEntryFields;
                                        int var27 = billEntryFields.length;

                                        for(int var28 = 0; var28 < var27; ++var28) {
                                            billEntryField = var26[var28];
                                            Object srcField = srcBillEntry.get(billEntryField);
                                            DynamicProperty srcdp = srcBillEntry.getDynamicObjectType().getProperty(billEntryField);
                                            Object newField = xBillEntry.get(billEntryField);
                                            DynamicProperty newdp = xBillEntry.getDynamicObjectType().getProperty(billEntryField);
                                            String caption = MetaDataHelper.getEntryPropertyAlias(xBill.getDataEntityType(), entryName, billEntryField);
                                            String nField = displayFieldValue(newField, newdp);
                                            String oField = displayFieldValue(srcField, srcdp);
                                            boolean equal = compareField(srcField, newField);
                                            ChangeResumeLogFieldInfo logFieldInfo = new ChangeResumeLogFieldInfo();
                                            if (equal) {
                                                logFieldInfo.setIsequals("=");
                                            } else {
                                                eq = "*";
                                                logFieldInfo.setIsequals("*");
                                                if (srcField instanceof BigDecimal && newField instanceof BigDecimal || srcdp instanceof IntegerProp && newdp instanceof IntegerProp) {
                                                    nField = nField + compareSizes(srcField, newField);
                                                }
                                            }

                                            logFieldInfo.setOldValue(oField);
                                            logFieldInfo.setNewValue(nField);
                                            logFieldInfo.setFieldname(caption);
                                            cifo.setLogFieldInfo(billEntryField, logFieldInfo);
                                        }
                                    } while(childEntities.size() <= 0);

                                    Iterator var48 = childEntities.iterator();

                                    while(var48.hasNext()) {
                                        EntityType childEntity = (EntityType)var48.next();
                                        childEnName = childEntity.getName();
                                        String[] canLogProperty = (String[])allCanLogProperty.get(childEnName);
                                        if (!CommonUtils.isNull(canLogProperty)) {
                                            String childJson = genFormatString(srcBillEntry, xBillEntry, xBillEntryAndField, childEntity, allCanLogProperty);
                                            if (!CommonUtils.isNull(childJson)) {
                                                childField.append(childJson).append(",");
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        if (ChangeTypeEnum.CANCEL.getValue().equals(changetype)) {
                            eq = "-";
                        }

                        cifo.setKeyFlag(eq);
                        if (childField.length() > 0) {
                            childField.deleteCharAt(childField.length() - 1);
                        }

                        if (cifo.formatJson().length() > 0) {
                            StringBuilder cifoStrBuilder = new StringBuilder(cifo.formatJson());
                            if (childField.length() > 0) {
                                cifoStrBuilder.deleteCharAt(cifoStrBuilder.length() - 1);
                                childField = cifoStrBuilder.append(",").append(childField).append("}");
                            } else {
                                childField = cifoStrBuilder;
                            }
                        }

                        fieldJson.append(childField).append(",");
                    }
                } else {
                    return "";
                }
            }
        } else {
            return "";
        }
    }

    public static boolean compareField(Object srcField, Object newField) {
        if (srcField == null && newField == null) {
            return true;
        } else if (srcField instanceof OrmLocaleValue && ((OrmLocaleValue)srcField).isEmpty() && newField instanceof OrmLocaleValue && ((OrmLocaleValue)newField).isEmpty()) {
            return true;
        } else if (srcField instanceof BigDecimal && newField instanceof BigDecimal && srcField.equals(newField)) {
            return true;
        } else if (srcField instanceof DynamicObject && newField instanceof DynamicObject && ((DynamicObject)srcField).getPkValue().equals(((DynamicObject)newField).getPkValue())) {
            return true;
            //多选基础资料
        }else if(srcField instanceof DynamicObjectCollection && newField instanceof DynamicObjectCollection) {
                DynamicObjectCollection srcCol = (DynamicObjectCollection) srcField;
                DynamicObjectCollection newCol = (DynamicObjectCollection) newField;
                if(srcCol.size()!=newCol.size()) {
                    return false;
                }
                List<Object> srcList = new ArrayList<Object>();
                for(DynamicObject srcObj:srcCol) {
                    if(srcObj.getDynamicObject(1)!=null) {
                        srcList.add(srcObj.getDynamicObject(1).getPkValue());
                    }

                }
                List<Object> newList = new ArrayList<Object>();
                for(DynamicObject newObj:newCol) {
                    if(newObj.getDynamicObject(1)!=null) {
                        newList.add(newObj.getDynamicObject(1).getPkValue());
                    }

                }
                if(new HashSet<>(srcList).containsAll(newList)&&newList.size()>0) {
                    return true;
                }else{
                    return false;
                }

        } else if (newField != null && newField.equals(srcField)) {
            return true;
        } else if (srcField != null && srcField.equals(newField)) {
            return true;
        } else if (srcField != null && newField != null) {
            String srcFieldStr = srcField.toString();
            String newFieldStr = newField.toString();
            if (srcFieldStr == null && newFieldStr == null) {
                return true;
            } else {
                return srcFieldStr != null && srcFieldStr.equals(newFieldStr);
            }
        } else {
            return false;
        }
    }

    public static String compareSizes(Object srcField, Object newField) {
        if (srcField instanceof BigDecimal && newField instanceof BigDecimal) {
            BigDecimal oldBig = (BigDecimal)srcField;
            BigDecimal newBig = (BigDecimal)newField;
            if (CommonUtils.isNull(oldBig) || CommonUtils.isNull(newBig)) {
                return "";
            }

            if (oldBig.compareTo(newBig) < 0) {
                return "↑";
            }

            if (oldBig.compareTo(newBig) > 0) {
                return "↓";
            }
        } else if (srcField instanceof Integer && newField instanceof Integer) {
            Integer oldBig = (Integer)srcField;
            Integer newBig = (Integer)newField;
            if (CommonUtils.isNull(oldBig) || CommonUtils.isNull(newBig)) {
                return "";
            }

            if (oldBig.compareTo(newBig) < 0) {
                return "↑";
            }

            if (oldBig.compareTo(newBig) > 0) {
                return "↓";
            }
        }

        return "";
    }

    public static String displayFieldValue(Object newField, DynamicProperty newdp) {
        if (newField == null) {
            return "";
        } else if (newField instanceof BigDecimal) {
            BigDecimal b = (BigDecimal)newField;
            return b.stripTrailingZeros().toPlainString();
        } else if (newField instanceof Date) {
            Date d = (Date)newField;
            String format = InteServiceHelper.getUserFormat(UserServiceHelper.getCurrentUserId()).getDateFormat().getDateFormat();
            SimpleDateFormat df = new SimpleDateFormat(format);
            return getTransString(df.format(d));
        } else if (newField instanceof Boolean) {
            Boolean b = (Boolean)newField;
            return b ? ResManager.loadKDString("是", "ChangeLogHelper_1", "yem-yc-changemodel", new Object[0]) : ResManager.loadKDString("否", "ChangeLogHelper_2", "yem-yc-changemodel", new Object[0]);
        } else if (newField instanceof DynamicObject) {
            DynamicObject dyo = (DynamicObject)newField;
            if (newdp instanceof BasedataProp) {
                if (newdp instanceof FlexProp) {
                    return getTransString(dyo.toString());
                } else {
                    BasedataProp bdProp = (BasedataProp)newdp;
                    return getTransString(bdProp.getDisplayValue(newField));
                }
            } else {
                return getTransString(dyo.toString());
            }
        } else {
            if (newField instanceof DynamicObjectCollection) {
                DynamicObjectCollection dyoCol = (DynamicObjectCollection)newField;
                if (dyoCol.isEmpty()) {
                    return "";
                }

                if (newdp instanceof MulBasedataProp) {
                    if (newdp instanceof AttachmentProp) {
                        AttachmentProp panel = (AttachmentProp)newdp;
                        return getTransString(panel.getDisplayValue(newField));
                    }

                    MulBasedataProp mulbdPro = (MulBasedataProp)newdp;
                    return getTransString(mulbdPro.getDisplayValue(newField));
                }
            } else {
                if (newdp instanceof MulComboProp) {
                    MulComboProp cbPros = (MulComboProp)newdp;
                    return getTransString(cbPros.getItemByName((String)newField));
                }

                if (newdp instanceof ComboProp) {
                    ComboProp cbPro = (ComboProp)newdp;
                    List<ValueMapItem> cbItems = cbPro.getComboItems();
                    Iterator var4 = cbItems.iterator();

                    while(var4.hasNext()) {
                        ValueMapItem cbItem = (ValueMapItem)var4.next();
                        if (cbItem != null && newField.equals(cbItem.getValue())) {
                            return getTransString(cbItem.getName().toString());
                        }
                    }
                } else {
                    if (newField instanceof OrmLocaleValue) {
                        String str = ((OrmLocaleValue)newField).getLocaleValue();
                        if (str == null) {
                            return "";
                        }

                        return getTransString(str);
                    }

                    if (newdp instanceof AssistantProp) {
                        AssistantProp assistantPropdp = (AssistantProp)newdp;
                        return getTransString(assistantPropdp.getDisplayValue(newField));
                    }
                }
            }

            return getTransString(newField.toString());
        }
    }

    public static String getTransString(String str) {
        if (StringUtils.isNotEmpty(str)) {
            if (str.contains("\\")) {
                str = str.replaceAll("\\\\", "&#123;");
            }

            if (str.contains("\"")) {
                str = str.replaceAll("\"", "&#124;");
            }
        } else {
            str = "";
        }

        return str;
    }

    public static Map<String, String[]> getAllChangeLogPropertyMap(DynamicObject xBill) {
        Map<String, String[]> allCanLogProperty = new HashMap();
        if (xBill == null) {
            return allCanLogProperty;
        } else {
            List<EntityType> entities = getAllEntities(xBill.getDynamicObjectType().getProperties());
            if (entities.size() > 0) {
                Iterator var3 = entities.iterator();

                while(var3.hasNext()) {
                    EntityType entitie = (EntityType)var3.next();
                    String enName = entitie.getName();
                    String[] canLogProperty = ChangeModelHelper.getCanLogProperty(xBill.getDataEntityType(), enName);
                    allCanLogProperty.put(enName, canLogProperty);
                }
            }

            return allCanLogProperty;
        }
    }

    public static List<EntityType> getChildEntities(IDataEntityType entityType) {
        List<EntityType> childEntities = new ArrayList();
        if (entityType == null) {
            return childEntities;
        } else {
            Iterator var2 = entityType.getProperties().iterator();

            while(var2.hasNext()) {
                IDataEntityProperty property = (IDataEntityProperty)var2.next();
                if (property instanceof ICollectionProperty) {
                    ICollectionProperty collProp = (ICollectionProperty)property;
                    if (collProp.getItemType() instanceof EntityType) {
                        EntityType childEntity = (EntityType)collProp.getItemType();
                        childEntities.add(childEntity);
                    }
                }
            }

            return childEntities;
        }
    }

    public static List<EntityType> getAllEntities(DataEntityPropertyCollection entityType) {
        List<EntityType> entities = new ArrayList();
        if (entityType == null) {
            return entities;
        } else {
            Iterator var2 = entityType.iterator();

            while(var2.hasNext()) {
                IDataEntityProperty property = (IDataEntityProperty)var2.next();
                if (property instanceof ICollectionProperty) {
                    ICollectionProperty collProp = (ICollectionProperty)property;
                    if (collProp.getItemType() instanceof EntityType) {
                        EntityType childEntity = (EntityType)collProp.getItemType();
                        entities.add(childEntity);
                        entities.addAll(getAllEntities(childEntity.getProperties()));
                    }
                }
            }

            return entities;
        }
    }
}