package com.kingdee.eas.custom.webbeisen.thirdpartysystemsyn.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.kingdee.bos.BOSException;
import com.kingdee.bos.BOSObjectFactory;
import com.kingdee.bos.Context;
import com.kingdee.bos.dao.IObjectCollection;
import com.kingdee.bos.dao.IObjectValue;
import com.kingdee.bos.dao.query.IQueryExecutor;
import com.kingdee.bos.dao.query.QueryExecutorFactory;
import com.kingdee.bos.metadata.MetaDataPK;
import com.kingdee.bos.metadata.data.SortType;
import com.kingdee.bos.metadata.entity.*;
import com.kingdee.bos.metadata.query.util.CompareType;
import com.kingdee.bos.sql.ParserException;
import com.kingdee.bos.util.BOSObjectType;
import com.kingdee.bos.util.BOSUuid;
import com.kingdee.eas.common.EASBizException;
import com.kingdee.eas.custom.thirdpartysystemsyn.config.viewconfig.*;
import com.kingdee.eas.custom.thirdpartysystemsyn.enumerationset.DataTypeEnum;
import com.kingdee.eas.custom.thirdpartysystemsyn.enumerationset.EntityAttributeEnum;
import com.kingdee.eas.framework.CoreBaseCollection;
import com.kingdee.eas.framework.CoreBaseInfo;
import com.kingdee.eas.framework.ICoreBase;
import com.kingdee.shr.attachment.SHRAttachmentExtCollection;
import com.kingdee.shr.attachment.SHRAttachmentExtFactory;
import com.kingdee.shr.attachment.SHRAttachmentExtInfo;
import com.kingdee.shr.base.syssetting.MSFServiceFacadeFactory;
import com.kingdee.shr.base.syssetting.context.SHRContext;
import com.kingdee.shr.base.syssetting.exception.SHRWebException;
import com.kingdee.shr.base.syssetting.exception.ShrWebBizException;
import com.kingdee.shr.base.syssetting.model.VirtualDataFetcher;
import com.kingdee.shr.base.syssetting.util.MetaDataUtil;
import com.kingdee.util.Uuid;
import com.kingdee.util.enums.EnumUtils;
import org.apache.log4j.Logger;

import java.util.*;

public class AssistSynchronizingUtils {
    // 日志记录器，用于记录系统操作日志
    private static final Logger logger = Logger.getLogger("com.kingdee.eas.custom.webbeisen.thirdpartysystemsyn.utils.AssistSynchronizingUtils");

    /**
     * 重写父类方法，根据配置编号和过滤条件获取数据
     * 该方法主要执行以下步骤：
     * 1. 解析过滤条件JSON字符串
     * 2. 获取头部配置信息
     * 3. 构建查询条件并执行查询
     * 4. 处理查询结果并转换为JSON格式
     * 5. 处理分录数据（如果存在）
     *
     * @param ctx 上下文对象
     * @param configNumber 配置编号，用于定位具体的同步配置
     * @param filterInfos 过滤条件信息，JSON格式字符串
     * @return 处理后的结果数据，JSON格式字符串
     * @throws BOSException 当操作过程中发生业务异常时抛出
     */
    public JSONArray getData(Context ctx, String configNumber, String filterInfos) throws BOSException {
        // 记录方法调用日志，包含入参信息
        logger.info("Starting getData method with configNumber: " + configNumber + ", filterInfos: " + filterInfos);

        // 用于记录处理统计信息
        int totalRecords = 0;
        int successRecords = 0;
        int failedRecords = 0;
        JSONArray errorDetails = new JSONArray();

        // 解析过滤条件JSON字符串为JSONObject
        JSONObject jsonObject = JSONObject.parseObject(filterInfos);
        JSONArray resultArray = new JSONArray(); // 创建结果数组

        try {
            // 获取头部配置信息
            logger.debug("Getting head configuration for configNumber: " + configNumber);
            EntityViewInfo headEntry = createEntityViewInfo(configNumber, EntityAttributeEnum.HEAD_VALUE);
            ConfigInfoEntryCollection entries = ConfigInfoEntryFactory.getLocalInstance(ctx).getConfigInfoEntryCollection(headEntry);

            // 验证条目信息是否唯一
            if (entries.size() != 1) {
                String errorMsg = "头部信息配置异常，期望1条配置但找到" + entries.size() + "条";
                logger.error(errorMsg);
                throw new RuntimeException(errorMsg); // 抛出配置异常
            }

            // 获取唯一的条目信息
            ConfigInfoEntryInfo configInfoEntryInfo = entries.get(0);
            String entityName = configInfoEntryInfo.getEntityName(); // 获取实体名称
            logger.debug("Found entity: " + entityName + " for configNumber: " + configNumber);

            // 创建实体查询视图并设置查询条件
            EntityViewInfo headEntityViewInfo = new EntityViewInfo();
            String filterExpr = jsonObject.getString(entityName); // 获取实体对应的过滤条件
            if (filterExpr != null && !filterExpr.trim().isEmpty()) { // 检查过滤条件是否非空
                headEntityViewInfo.setFilter(filterExpr); // 设置过滤条件
                logger.debug("Set filter for entity " + entityName + ": " + filterExpr);
            }

            // 设置查询字段
            ConfigInfoEntryFieldCollection fields = configInfoEntryInfo.getFields();
            SelectorItemCollection selectorItem = getSelectorItem(fields); // 获取选择器项目
            headEntityViewInfo.setSelector(selectorItem); // 设置选择器
            logger.debug("Set selector with " + selectorItem.size() + " fields");

            // 设置排序
            String sortField = configInfoEntryInfo.getSortField(); // 获取排序字段
            SorterItemCollection sorterItemCollection = sorterProcessing(sortField); // 处理排序字段
            if (sorterItemCollection != null) {
                headEntityViewInfo.setSorter(sorterItemCollection); // 设置排序器
                logger.debug("Set sorter with " + sorterItemCollection.size() + " fields");
            }

            // 执行查询获取数据集合
            boolean isQuery = configInfoEntryInfo.isIsQuery(); // 判断是否为查询类型
            CoreBaseCollection collection; // 声明数据集合
            if (isQuery) {
                logger.debug("Initializing collection using query for entity: " + entityName);
                collection = this.initCollection(entityName, headEntityViewInfo, ctx); // 初始化集合
            } else {
                String bosType = configInfoEntryInfo.getBosType(); // 获取BOS类型
                BOSObjectType bosObjectType = BOSObjectType.create(bosType); // 创建BOS对象类型
                logger.debug("Getting collection using BOS object type: " + bosType);
                // 根据BOS类型创建对应的业务对象实例
                ICoreBase bosObject = (ICoreBase) BOSObjectFactory.createBOSObject(ctx, bosObjectType);
                collection = bosObject.getCollection(headEntityViewInfo); // 获取数据集合
            }

            totalRecords = collection.size();
            logger.info("Retrieved " + totalRecords + " records for processing");

            // 处理查询结果
            processCollectionData(ctx, configNumber, jsonObject, resultArray, collection,
                    configInfoEntryInfo, fields, errorDetails);

            successRecords = resultArray.size();
            failedRecords = totalRecords - successRecords;

            logger.info("Data processing completed. Success: " + successRecords +
                    ", Failed: " + failedRecords + ", Total: " + totalRecords);

        } catch (Exception e) {
            e.printStackTrace();
            String errorMsg = "Error occurred while getting data for configNumber: " + configNumber;
            logger.error(errorMsg, e);

            // 创建错误详情记录
            JSONObject errorDetail = new JSONObject();
            errorDetail.put("configNumber", configNumber);
            errorDetail.put("errorType", "MAIN_PROCESS_ERROR");
            errorDetail.put("errorMessage", e.getMessage());
            errorDetail.put("stackTrace", Arrays.toString(e.getStackTrace()));
            errorDetails.add(errorDetail);

            failedRecords = totalRecords; // 所有记录都标记为失败
            successRecords = 0;

            throw new BOSException("数据获取失败: " + e.getMessage(), e); // 抛出业务异常
        } finally {
            // 记录最终处理结果统计
            JSONObject processSummary = new JSONObject();
            processSummary.put("configNumber", configNumber);
            processSummary.put("totalRecords", totalRecords);
            processSummary.put("successRecords", successRecords);
            processSummary.put("failedRecords", failedRecords);
            processSummary.put("errorDetails", errorDetails);

            logger.info("Process summary: " + processSummary.toJSONString());
        }

        logger.info("Successfully retrieved data, result size: " + resultArray.size());
        return resultArray;
    }


    public void saveData(Context ctx, String configNumber, String controllerBeanEx) throws BOSException {
        EntityViewInfo headEntry = createEntityViewInfo(configNumber, EntityAttributeEnum.HEAD_VALUE);
        ConfigInfoEntryCollection entries = ConfigInfoEntryFactory.getLocalInstance(ctx).getConfigInfoEntryCollection(headEntry);

        // 验证条目信息是否唯一
        if (entries.size() != 1) {
            String errorMsg = "头部信息配置异常，期望1条配置但找到" + entries.size() + "条";
            logger.error(errorMsg);
            throw new RuntimeException(errorMsg); // 抛出配置异常
        }

        // 获取唯一的条目信息
        ConfigInfoEntryInfo configInfoEntryInfo = entries.get(0);
        String entityName = configInfoEntryInfo.getEntityName(); // 获取实体名称
        logger.debug("Found entity: " + entityName + " for configNumber: " + configNumber);
        ConfigInfoInfo parent = configInfoEntryInfo.getParent();
        //osf服务名
        String osfName = parent.getOsfName();
        String osfParam = parent.getOsfParam();
        Object o = null;
        try {
            o = MSFServiceFacadeFactory.getLocalInstance(ctx).processService(osfName, this.getOSFParam(osfParam));

        } catch (EASBizException e) {
            throw new RuntimeException(e);
        }
        JSONArray osfReturnData = JSONArray.parseArray(o.toString());
        for (int i = 0; i < osfReturnData.size(); i++) {
            JSONObject osfReturnDataEntry = osfReturnData.getJSONObject(i);
            //处理头部信息
            boolean isCreateData = configInfoEntryInfo.isIsCreateData();//是否创建数据

            String thirdUniqueValue = configInfoEntryInfo.getThirdUniqueValue();//第三方唯一值
            String hrUniqueValue = configInfoEntryInfo.getHrUniqueValue();//hr唯一值
            String bosType = configInfoEntryInfo.getBosType();
            Class objectValueClass1 = null;
            try {
                objectValueClass1 = MetaDataUtil.getObjectValueClass(entityName);
                // 创建对应的实体对象
                CoreBaseInfo coreBaseInfo = (CoreBaseInfo) MetaDataUtil.newInstance(objectValueClass1, entityName);
                if (!isCreateData){
                    String value = getThirdUniqueValue(osfReturnDataEntry, thirdUniqueValue);
                    if (value!=null){
                        CoreBaseInfo coreBaseInfo1 = findCoreBaseInfo(ctx, coreBaseInfo.getBOSType(), value, hrUniqueValue);
                        if (coreBaseInfo1!=null){
                            coreBaseInfo = coreBaseInfo1;
                        }
                    }
                }
            } catch (ShrWebBizException e) {
                throw new RuntimeException(e);
            }
        }
    }
    public String getThirdUniqueValue(JSONObject jsonObject,String thirdUniqueValue){
        String[] split = thirdUniqueValue.split("\\.");
        Object value = null;
        for (int i = 0; i < split.length; i++) {
            String s = split[i];
            value = jsonObject.get(s);
            if (value instanceof JSONArray){
                JSONArray jsonArray = jsonObject.getJSONArray(s);
                value = jsonArray.get(0);
            }
        }
        return value==null?null:value.toString();
    }


    public CoreBaseInfo findCoreBaseInfo(Context ctx,BOSObjectType bosObjectType,
                                         String thirdUniqueValue,
                                         String hrUniqueValue) throws BOSException {

        ICoreBase bosObject =  (ICoreBase) (BOSObjectFactory.createBOSObject(ctx,bosObjectType));
        CoreBaseCollection collection = bosObject.getCollection("where " + hrUniqueValue + " = '" + thirdUniqueValue + "' ");
        if (collection.size()>1){
            throw new RuntimeException("");
        } else if (collection.size()==0) {
            return null;
        }else {
            return collection.get(0);
        }
    }

    public Map<String,Object> getOSFParam(String jsonData){
        if (jsonData!=null&&!jsonData.equals("")){
            JSONObject param = JSONObject.parseObject(jsonData);
            Set<String> strings = param.keySet();
            Iterator<String> iterator = strings.iterator();
            Map<String,Object> map = new HashMap<String,Object>();
            while (iterator.hasNext()){
                String next = iterator.next();
                map.put(next,param.get(next));
            }
            return map;
        }else {
            return null;
        }
    }

    /**
     * 处理查询结果集合数据
     * 遍历集合中的每个CoreBaseInfo对象，将其转换为JSON格式，并处理相关的分录数据
     *
     * @param ctx 上下文对象
     * @param configNumber 配置编号
     * @param jsonObject 过滤条件JSON对象
     * @param resultArray 结果数组
     * @param collection 查询结果集合
     * @param configInfoEntryInfo 配置条目信息
     * @param fields 字段配置集合
     * @param errorDetails 错误详情数组，用于记录处理过程中的错误
     * @throws BOSException 业务异常
     * @throws ClassNotFoundException 类未找到异常
     * @throws ParserException 解析异常
     * @throws SHRWebException SHR Web异常
     */
    public void processCollectionData(Context ctx, String configNumber, JSONObject jsonObject,
                                      JSONArray resultArray, CoreBaseCollection collection,
                                      ConfigInfoEntryInfo configInfoEntryInfo,
                                      ConfigInfoEntryFieldCollection fields,
                                      JSONArray errorDetails)
            throws BOSException, ClassNotFoundException, ParserException, SHRWebException {
        for (int i = 0; i < collection.size(); i++) { // 遍历集合中的每个元素
            String recordId = "unknown";
            try {
                CoreBaseInfo coreBaseInfo = collection.get(i); // 获取当前元素
                recordId = coreBaseInfo.getId() != null ? coreBaseInfo.getId().toString() : "unknown";
                logger.debug("Processing record " + (i+1) + "/" + collection.size() + ", ID: " + recordId);
                JSONObject resultData = new JSONObject(); // 创建结果数据对象
                JSONObject mainData = new JSONObject(); // 创建主数据对象
                // 处理单条数据，转换为JSON格式
                dataProcessing(mainData, coreBaseInfo, fields, recordId, ctx);
                String name = configInfoEntryInfo.getName(); // 获取配置名称
                resultData.put(name, mainData); // 将主数据添加到结果数据
                // 处理分录数据
                processEntryData(ctx, configNumber, jsonObject, resultData, coreBaseInfo, recordId, errorDetails);
                resultArray.add(resultData); // 将结果数据添加到结果数组
                logger.debug("Successfully processed record ID: " + recordId);
            } catch (Exception e) {
                e.printStackTrace();
                String errorMsg = "Error processing record " + (i+1) + "/" + collection.size() + ", ID: " + recordId;
                logger.error(errorMsg, e);
                // 创建错误详情记录
                JSONObject errorDetail = new JSONObject();
                errorDetail.put("configNumber", configNumber);
                errorDetail.put("recordId", recordId);
                errorDetail.put("recordIndex", i);
                errorDetail.put("errorType", "RECORD_PROCESSING_ERROR");
                errorDetail.put("errorMessage", e.getMessage());
                errorDetail.put("stackTrace", Arrays.toString(e.getStackTrace()));
                errorDetails.add(errorDetail);
                // 继续处理下一条记录
                continue;
            }
        }
    }

    /**
     * 处理分录数据
     * 获取配置中的分录信息，根据关联字段查询相关的分录数据，并将其转换为JSON格式
     *
     * @param ctx 上下文对象
     * @param configNumber 配置编号
     * @param jsonObject 过滤条件JSON对象
     * @param resultData 结果数据对象
     * @param coreBaseInfo 核心基础信息对象
     * @param recordId 当前处理的主记录ID
     * @param errorDetails 错误详情数组，用于记录处理过程中的错误
     * @throws BOSException 业务异常
     * @throws ClassNotFoundException 类未找到异常
     * @throws ParserException 解析异常
     * @throws SHRWebException SHR Web异常
     */
    public void processEntryData(Context ctx, String configNumber, JSONObject jsonObject,
                                 JSONObject resultData, CoreBaseInfo coreBaseInfo,
                                 String recordId, JSONArray errorDetails)
            throws BOSException, ClassNotFoundException, ParserException, SHRWebException {
        try {
            // 获取分录为 boy类型的配置
            EntityViewInfo boyEntry = createEntityViewInfo(configNumber, EntityAttributeEnum.BOY_VALUE);
            ConfigInfoEntryCollection entryCollection = ConfigInfoEntryFactory.getLocalInstance(ctx).getConfigInfoEntryCollection(boyEntry);

            for (int j = 0; j < entryCollection.size(); j++) { // 遍历分录配置集合
                ConfigInfoEntryInfo configInfoEntryInfo1 = entryCollection.get(j); // 获取当前分录配置
                String boyEntityName = configInfoEntryInfo1.getEntityName(); // 获取分录实体名称
                ConfigInfoEntryFieldCollection boyFields = configInfoEntryInfo1.getFields(); // 获取分录字段配置
                logger.debug("Processing entry data for entity: " + boyEntityName + ", main record ID: " + recordId);
                // 创建分录查询视图
                EntityViewInfo boyEntityViewInfo = new EntityViewInfo();
                String boyFilterExpr = jsonObject.getString(boyEntityName); // 获取分录过滤条件
                // 设置关联字段过滤条件
                String crelatedField = configInfoEntryInfo1.getCrelatedField(); // 获取关联字段
                FilterInfo filter = new FilterInfo(); // 创建过滤器
                String id = coreBaseInfo.getId().toString(); // 获取主数据ID
                filter.getFilterItems().add(new FilterItemInfo(crelatedField, id, CompareType.EQUALS)); // 添加关联字段过滤条件
                if (boyFilterExpr != null && !boyFilterExpr.trim().isEmpty()) { // 检查分录过滤条件是否非空
                    filter.getFilterItems().add(new FilterItemInfo(boyFilterExpr)); // 添加分录过滤条件
                }
                boyEntityViewInfo.setFilter(filter); // 设置过滤器
                // 设置查询字段
                SelectorItemCollection boySelectorItem = getSelectorItem(boyFields); // 获取分录选择器
                boyEntityViewInfo.setSelector(boySelectorItem); // 设置选择器
                // 执行查询获取分录数据
                boolean isQuery1 = configInfoEntryInfo1.isIsQuery(); // 判断是否为查询类型
                CoreBaseCollection boyCollection; // 声明分录数据集合
                if (isQuery1) {
                    boyCollection = this.initCollection(boyEntityName, boyEntityViewInfo, ctx); // 初始化分录集合
                } else {
                    String boyDosType = configInfoEntryInfo1.getBosType(); // 获取分录BOS类型
                    BOSObjectType boyBosObjectType = BOSObjectType.create(boyDosType); // 创建BOS对象类型
                    ICoreBase boyBosObject = (ICoreBase) BOSObjectFactory.createBOSObject(ctx, boyBosObjectType); // 创建业务对象
                    boyCollection = boyBosObject.getCollection(boyEntityViewInfo); // 获取分录数据集合
                }
                logger.debug("Retrieved " + boyCollection.size() + " entry records for entity: " +
                        boyEntityName + ", main record ID: " + recordId);
                // 处理分录数据
                JSONArray entryDataArray = new JSONArray(); // 创建分录数据数组
                for (int k = 0; k < boyCollection.size(); k++) { // 遍历分录数据集合
                    try {
                        CoreBaseInfo coreBaseInfo1 = boyCollection.get(k); // 获取当前分录数据
                        String entryRecordId = coreBaseInfo1.getId() != null ? coreBaseInfo1.getId().toString() : "unknown";

                        JSONObject entryData = new JSONObject(); // 创建分录数据对象
                        dataProcessing(entryData, coreBaseInfo1, boyFields, entryRecordId, ctx); // 处理分录数据
                        entryDataArray.add(entryData); // 将分录数据添加到数组

                        logger.debug("Processed entry record " + (k+1) + "/" + boyCollection.size() +
                                ", ID: " + entryRecordId + " for main record ID: " + recordId);
                    } catch (Exception e) {
                        e.printStackTrace();
                        String errorMsg = "Error processing entry record " + (k+1) + "/" + boyCollection.size() +
                                " for main record ID: " + recordId;
                        logger.error(errorMsg, e);

                        // 创建错误详情记录
                        JSONObject errorDetail = new JSONObject();
                        errorDetail.put("configNumber", configNumber);
                        errorDetail.put("mainRecordId", recordId);
                        errorDetail.put("entryEntity", boyEntityName);
                        errorDetail.put("entryIndex", k);
                        errorDetail.put("errorType", "ENTRY_RECORD_PROCESSING_ERROR");
                        errorDetail.put("errorMessage", e.getMessage());
                        errorDetail.put("stackTrace", Arrays.toString(e.getStackTrace()));
                        errorDetails.add(errorDetail);
                        // 继续处理下一条分录记录
                        continue;
                    }
                }
                String name1 = configInfoEntryInfo1.getName(); // 获取分录配置名称
                resultData.put(name1, entryDataArray); // 将分录数据添加到结果数据
                logger.debug("Completed processing entry data for entity: " + boyEntityName +
                        ", main record ID: " + recordId + ", records: " + entryDataArray.size());
            }
        } catch (Exception e) {
            e.printStackTrace();
            String errorMsg = "Error processing entry data for main record ID: " + recordId;
            logger.error(errorMsg, e);
            // 创建错误详情记录
            JSONObject errorDetail = new JSONObject();
            errorDetail.put("configNumber", configNumber);
            errorDetail.put("mainRecordId", recordId);
            errorDetail.put("errorType", "ENTRY_PROCESSING_ERROR");
            errorDetail.put("errorMessage", e.getMessage());
            errorDetail.put("stackTrace", Arrays.toString(e.getStackTrace()));
            errorDetails.add(errorDetail);
            // 抛出异常，由上层处理
            throw new RuntimeException(e);
        }
    }

    /**
     * 处理单条CoreBaseInfo数据，将其字段信息转换为JSONObject
     * 根据字段类型的不同，采用不同的处理方式：
     * 1. 枚举类型：获取枚举列表和当前值的别名
     * 2. 对象值类型：提取对象的名称和编号
     * 3. 对象集合类型：提取集合中每个对象的名称和编号
     * 4. 其他类型：直接使用字段值
     * 5. 最后处理附件信息
     *
     * @param jsonObject 用于存储处理后数据的JSON对象
     * @param coreBaseInfo 待处理的业务数据对象
     * @param fieldCollection 配置的字段集合，包含需要处理的字段信息
     * @param recordId 当前处理的记录ID，用于日志记录
     * @param context 上下文对象，用于获取附件信息
     * @throws ClassNotFoundException 当枚举类找不到时抛出
     */
    public void dataProcessing(JSONObject jsonObject, CoreBaseInfo coreBaseInfo,
                               ConfigInfoEntryFieldCollection fieldCollection, String recordId, Context context)
            throws ClassNotFoundException {
        for (int i = 0; i < fieldCollection.size(); i++) { // 遍历字段配置集合
            String fieldName = "unknown";

            try {
                ConfigInfoEntryFieldInfo configInfoEntryFieldInfo = fieldCollection.get(i); // 获取当前字段配置
                ConfigInfoEntryInfo parent = configInfoEntryFieldInfo.getParent1(); // 获取父配置信息
                fieldName = configInfoEntryFieldInfo.getFieldName(); // 获取字段名称
                Object fieldValue = coreBaseInfo.get(fieldName); // 获取字段值
                logger.debug("Processing field: " + fieldName + " for record ID: " + recordId);
                // 封装字段信息为JSON对象
                JSONObject fieldJson = createFieldJson(configInfoEntryFieldInfo, fieldValue);
                // 将字段JSON对象存入结果JSON中
                jsonObject.put(fieldName, fieldJson);
                logger.debug("Successfully processed field: " + fieldName + " for record ID: " + recordId);
            } catch (Exception e) {
                e.printStackTrace();
                String errorMsg = "Error processing field: " + fieldName + " for record ID: " + recordId;
                logger.error(errorMsg, e);
                // 创建错误字段标记
                JSONObject errorField = new JSONObject();
                errorField.put("fieldName", fieldName);
                errorField.put("error", true);
                errorField.put("errorMessage", e.getMessage());
                jsonObject.put(fieldName, errorField);
                // 继续处理下一个字段
                continue;
            }
        }
        // 处理附件信息
        String id = coreBaseInfo.getId().toString();
        fileProcessor(id, jsonObject, context);
    }

    /**
     * 处理业务对象的附件信息
     * 根据业务对象ID查询关联的附件信息，并将附件详情添加到结果JSON对象中
     * 该方法通常在dataProcessing方法的最后调用，用于补充附件数据
     *
     * 处理流程：
     * 1. 根据业务ID查询关联的附件信息
     * 2. 提取附件名称和ID等关键信息
     * 3. 将附件信息组织成JSON格式并添加到结果集中
     * 4. 异常情况下记录错误日志并添加错误标记
     *
     * @param id 业务对象ID，用于查询关联的附件
     * @param jsonObject 结果数据集，附件信息将添加到该对象的"file"字段中
     * @param context 上下文对象，用于获取数据库连接和执行环境
     */
    public void fileProcessor(String id, JSONObject jsonObject, Context context) {
        JSONArray jsonArray = new JSONArray();
        try {
            JSONObject file = new JSONObject();
            // 查询与业务对象ID关联的所有附件信息
            SHRAttachmentExtCollection shrAttachmentExtCollection = SHRAttachmentExtFactory
                    .getLocalInstance(context)
                    .getSHRAttachmentExtCollection("select *,attachment.* where boid = '" + id + "'");

            // 遍历所有附件，提取关键信息
            for (int i = 0; i < shrAttachmentExtCollection.size(); i++) {
                SHRAttachmentExtInfo shrAttachmentExtInfo = shrAttachmentExtCollection.get(i);
                file.put("name", shrAttachmentExtInfo.getName()); // 附件名称
                file.put("id", shrAttachmentExtInfo.getAttachment().getId().toString()); // 附件ID
                jsonArray.add(file);
            }

            // 将附件信息数组添加到结果集
            jsonObject.put("file", jsonArray);
        } catch (BOSException e) {
            e.printStackTrace();
            // 记录附件处理错误日志
            String errorMsg = "Error processing file for business object ID: " + id;
            logger.error(errorMsg, e);

            // 创建错误字段标记，便于前端识别和处理
            JSONObject errorField = new JSONObject();
            errorField.put("field", "file");
            errorField.put("error", true);
            errorField.put("errorMessage", e.getMessage());
            jsonObject.put("file", errorField);
        }
    }

    /**
     * 创建字段JSON对象
     * 包含字段的基本信息（名称、别名、第三方字段名）和类型信息，以及根据类型处理后的字段值
     *
     * @param configInfoEntryFieldInfo 配置信息条目字段信息
     * @param fieldValue 字段值
     * @return 字段JSON对象
     * @throws ClassNotFoundException 当枚举类找不到时抛出
     */
    public JSONObject createFieldJson(ConfigInfoEntryFieldInfo configInfoEntryFieldInfo, Object fieldValue)
            throws ClassNotFoundException {
        JSONObject fieldJson = new JSONObject(); // 创建字段JSON对象
        String fieldName = configInfoEntryFieldInfo.getFieldName(); // 获取字段名称
        String fieldAlias = configInfoEntryFieldInfo.getFieldAlias(); // 获取字段别名
        DataTypeEnum fieldType = configInfoEntryFieldInfo.getFieldType(); // 获取字段类型
        String thirdField = configInfoEntryFieldInfo.getThirdField(); // 获取第三方字段名

        fieldJson.put("fieldName", fieldName); // 添加字段名称
        fieldJson.put("fieldAlias", fieldAlias); // 添加字段别名
        fieldJson.put("thirdField", thirdField); // 添加第三方字段名

        // 添加字段类型信息
        JSONObject fieldTypeJson = new JSONObject(); // 创建字段类型JSON对象
        fieldTypeJson.put("alias", fieldType.getAlias()); // 添加类型别名
        fieldTypeJson.put("name", fieldType.getName()); // 添加类型名称
        fieldTypeJson.put("value", fieldType.getValue()); // 添加类型值
        fieldJson.put("fieldType", fieldTypeJson); // 添加字段类型信息

        // 根据字段类型处理字段值
        processFieldValueByType(configInfoEntryFieldInfo, fieldValue, fieldJson);

        return fieldJson; // 返回字段JSON对象
    }

    /**
     * 根据字段类型处理字段值
     * 针对不同类型的数据采用不同的处理策略，确保数据格式符合预期
     *
     * @param configInfoEntryFieldInfo 配置信息条目字段信息
     * @param fieldValue 字段值
     * @param fieldJson 字段JSON对象
     * @throws ClassNotFoundException 当枚举类找不到时抛出
     */
    public void processFieldValueByType(ConfigInfoEntryFieldInfo configInfoEntryFieldInfo,
                                        Object fieldValue, JSONObject fieldJson)
            throws ClassNotFoundException {
        DataTypeEnum fieldType = configInfoEntryFieldInfo.getFieldType(); // 获取字段类型
        String typeAlias = fieldType.getAlias(); // 获取类型别名

        if ("Enum".equals(typeAlias)) { // 处理枚举类型
            processEnumFieldValue(configInfoEntryFieldInfo, fieldValue, fieldJson);
        } else if ("ObjectValue".equals(typeAlias)) { // 处理对象值类型
            processObjectValueFieldValue(fieldValue, fieldJson);
        } else if ("ObjectCollection".equals(typeAlias)) { // 处理对象集合类型
            processObjectCollectionFieldValue(fieldValue, fieldJson);
        } else { // 处理其他类型
            fieldJson.put("value", fieldValue); // 直接添加字段值
        }
    }

    /**
     * 处理枚举类型字段值
     * 获取枚举类的所有可能值列表，并将当前字段值转换为对应的枚举别名
     *
     * @param configInfoEntryFieldInfo 配置信息条目字段信息
     * @param fieldValue 字段值
     * @param fieldJson 字段JSON对象
     * @throws ClassNotFoundException 当枚举类找不到时抛出
     */
    public void processEnumFieldValue(ConfigInfoEntryFieldInfo configInfoEntryFieldInfo,
                                      Object fieldValue, JSONObject fieldJson)
            throws ClassNotFoundException {
        String source = configInfoEntryFieldInfo.getSource(); // 获取枚举源
        List<?> enumList = EnumUtils.getEnumList(source); // 获取枚举列表
        fieldJson.put("source", enumList); // 添加枚举源信息

        if (fieldValue != null) { // 检查字段值是否为空
            Integer value = (Integer) fieldValue; // 转换字段值为整数
            fieldJson.put("value", EnumUtils.getEnum(Class.forName(source), value).getAlias()); // 添加枚举值别名
        }
    }

    /**
     * 处理对象值类型字段值
     * 提取对象的名称和编号属性，构建简化的对象表示
     *
     * @param fieldValue 字段值
     * @param fieldJson 字段JSON对象
     */
    public void processObjectValueFieldValue(Object fieldValue, JSONObject fieldJson) {
        if (fieldValue instanceof CoreBaseInfo) { // 检查字段值是否为CoreBaseInfo类型
            CoreBaseInfo sourceCoreBaseInfo = (CoreBaseInfo) fieldValue; // 转换字段值
            JSONObject sourceJSONObject = new JSONObject(); // 创建源JSON对象
            sourceJSONObject.put("name", sourceCoreBaseInfo.get("name")); // 添加名称属性
            sourceJSONObject.put("number", sourceCoreBaseInfo.get("number")); // 添加编号属性
            fieldJson.put("value", sourceJSONObject); // 添加源对象信息
        }
    }

    /**
     * 处理对象集合类型字段值
     * 遍历集合中的每个对象，提取名称和编号属性，构建对象数组
     *
     * @param fieldValue 字段值
     * @param fieldJson 字段JSON对象
     */
    public void processObjectCollectionFieldValue(Object fieldValue, JSONObject fieldJson) {
        if (fieldValue instanceof IObjectCollection) { // 检查字段值是否为对象集合类型
            IObjectCollection collection = (IObjectCollection) fieldValue; // 转换字段值
            JSONArray jsonArray = new JSONArray(); // 创建JSON数组

            for (int j = 0; j < collection.size(); j++) { // 遍历集合
                Object object = collection.getObject(j); // 获取当前对象
                if (object instanceof CoreBaseInfo) { // 检查对象是否为CoreBaseInfo类型
                    CoreBaseInfo coreBaseInfo = (CoreBaseInfo) object; // 转换对象
                    JSONObject sourceJSONObject = new JSONObject(); // 创建源JSON对象
                    sourceJSONObject.put("name", coreBaseInfo.get("name")); // 添加名称属性
                    sourceJSONObject.put("number", coreBaseInfo.get("number")); // 添加编号属性
                    jsonArray.add(sourceJSONObject); // 将源对象添加到数组
                }
            }

            fieldJson.put("value", jsonArray); // 添加对象数组
        }
    }

    /**
     * 根据配置的字段集合构建查询选择器，指定查询时需要返回的字段
     * 对于对象值类型的字段，额外添加相关字段（名称、编号和所有字段）
     *
     * @param fields 配置的字段集合
     * @return 包含所有需要查询的字段的选择器集合
     */
    public SelectorItemCollection getSelectorItem(ConfigInfoEntryFieldCollection fields) {
        SelectorItemCollection selectorItemCollection = new SelectorItemCollection(); // 创建选择器集合

        for (int i = 0; i < fields.size(); i++) { // 遍历字段配置集合
            ConfigInfoEntryFieldInfo configInfoEntryFieldInfo = fields.get(i); // 获取当前字段配置
            String fieldName = configInfoEntryFieldInfo.getFieldName(); // 获取字段名称
            DataTypeEnum fieldType = configInfoEntryFieldInfo.getFieldType(); // 获取字段类型

            // 添加字段到选择器
            selectorItemCollection.add(fieldName); // 添加字段名称

            // 对于对象值类型，额外添加相关字段
            if ("ObjectValue".equals(fieldType.getAlias())) { // 检查是否为对象值类型
                selectorItemCollection.add(fieldName + ".name"); // 添加名称字段
                selectorItemCollection.add(fieldName + ".number"); // 添加编号字段
                selectorItemCollection.add(fieldName + ".*"); // 添加所有字段
            }
        }
        selectorItemCollection.add("id"); // 添加ID字段
        return selectorItemCollection; // 返回选择器集合
    }

    /**
     * 创建实体视图查询条件，用于查询配置信息
     * 根据配置编号和实体属性类型过滤配置信息，并指定需要返回的字段
     *
     * @param configNumber 配置编号，用于精确匹配配置
     * @param type 实体属性类型（如HEAD/ENTRY），用于过滤特定类型的配置
     * @return 构建好的实体查询视图
     */
    public EntityViewInfo createEntityViewInfo(String configNumber, String type) {
        EntityViewInfo entityViewInfo = new EntityViewInfo(); // 创建实体视图信息

        // 创建过滤条件
        FilterInfo filterInfo = new FilterInfo(); // 创建过滤器
        filterInfo.getFilterItems().add(new FilterItemInfo("parent.number", configNumber, CompareType.EQUALS)); // 添加父级编号过滤条件
        filterInfo.getFilterItems().add(new FilterItemInfo("entityAttribute", type, CompareType.EQUALS)); // 添加实体属性过滤条件
        entityViewInfo.setFilter(filterInfo); // 设置过滤器

        // 构建查询选择器，指定需要返回的字段
        SelectorItemCollection selectorItemCollection = new SelectorItemCollection(); // 创建选择器集合
        selectorItemCollection.add("parent.*"); // 添加父表所有字段
        selectorItemCollection.add("*"); // 添加条目表所有字段
        selectorItemCollection.add("Fields.*"); // 添加字段配置表所有字段
        entityViewInfo.setSelector(selectorItemCollection); // 设置选择器

        return entityViewInfo; // 返回实体视图信息
    }

    /**
     * 处理排序字段字符串，转换为排序器集合
     * 支持以下格式：
     * 1. "field1 ASC, field2 DESC" - 明确指定排序方向
     * 2. "field1, field2" - 默认使用升序
     *
     * @param sortField 排序字段字符串，格式如 "field1 ASC, field2 DESC"
     * @return 排序器集合，如果排序字段为空则返回null
     */
    public SorterItemCollection sorterProcessing(String sortField) {
        if (sortField == null || sortField.trim().isEmpty()) { // 检查排序字段是否为空
            return null; // 返回空值
        }

        SorterItemCollection sorterItemCollection = new SorterItemCollection(); // 创建排序器集合
        String[] sortFields = sortField.split(","); // 分割排序字段

        for (String field : sortFields) { // 遍历排序字段数组
            SorterItemInfo sorterItemInfo = new SorterItemInfo(); // 创建排序器信息
            String trimmedField = field.trim().toLowerCase(); // 去除空格并转换为小写

            if (trimmedField.contains("asc")) { // 检查是否包含升序关键字
                String propertyName = trimmedField.replace("asc", "").trim(); // 移除升序关键字
                sorterItemInfo.setPropertyName(propertyName); // 设置属性名称
                sorterItemInfo.setSortType(SortType.ASCEND); // 设置升序排序
            } else if (trimmedField.contains("desc")) { // 检查是否包含降序关键字
                String propertyName = trimmedField.replace("desc", "").trim(); // 移除降序关键字
                sorterItemInfo.setPropertyName(propertyName); // 设置属性名称
                sorterItemInfo.setSortType(SortType.DESCEND); // 设置降序排序
            } else { // 默认情况
                sorterItemInfo.setPropertyName(trimmedField); // 设置属性名称
                sorterItemInfo.setSortType(SortType.ASCEND); // 设置升序排序
            }
            sorterItemCollection.add(sorterItemInfo); // 添加排序器到集合
        }

        return sorterItemCollection; // 返回排序器集合
    }

    /**
     * 初始化集合数据
     * 通过业务接口获取指定实体的数据集合
     *
     * @param entityName 实体名称
     * @param entityViewInfo 实体视图信息
     * @param context 上下文对象
     * @return 核心基础集合
     * @throws SHRWebException SHR Web异常
     * @throws ParserException 解析异常
     * @throws BOSException 业务异常
     */
    public CoreBaseCollection initCollection(String entityName, EntityViewInfo entityViewInfo, Context context)
            throws SHRWebException, ParserException, BOSException {
        IQueryExecutor queryExecutor = this.getQueryExecutor(context, entityViewInfo, entityName); // 获取查询执行器
        Uuid uuid = queryExecutor.openQuery(); // 打开查询
        VirtualDataFetcher vdf = VirtualDataFetcher.createInstance(queryExecutor, uuid, 0, 1000); // 创建虚拟数据获取器
        List<Map<String, Object>> data = vdf.getData(); // 获取数据
        CoreBaseCollection collection = new CoreBaseCollection(); // 创建核心基础集合

        for (int i = 0; i < data.size(); i++) { // 遍历数据
            Map<String, Object> stringObjectMap = data.get(i); // 获取当前数据项
            String string = stringObjectMap.get("id").toString(); // 获取ID字符串
            BOSUuid read = BOSUuid.read(string); // 读取BOS UUID
            EntityObjectInfo entityObject = MetaDataUtil.getEntityObjectByBosType(read.getType()); // 获取实体对象信息
            String fullName = entityObject.getFullName(); // 获取完整类名
            Class<?> targetClass = MetaDataUtil.getObjectValueClass(fullName); // 获取目标类
            CoreBaseInfo coreBaseInfo = (CoreBaseInfo) MetaDataUtil.newInstance(targetClass, fullName); // 创建核心基础信息实例
            SelectorItemCollection selector = entityViewInfo.getSelector(); // 获取选择器

            for (int j = 0; j < selector.size(); j++) { // 遍历选择器
                SelectorItemInfo selectorItemInfo = selector.get(j); // 获取当前选择器项
                String propertyName = selectorItemInfo.getPropertyName(); // 获取属性名称
                coreBaseInfo.put(propertyName, stringObjectMap.get(propertyName)); // 设置属性值
            }
            collection.add(coreBaseInfo); // 添加到集合
        }
        return collection; // 返回集合
    }

    /**
     * 获取查询执行器
     * 创建并配置查询执行器，用于执行数据查询操作
     *
     * @param context 上下文对象
     * @param entityViewInfo 实体视图信息
     * @param query 查询字符串
     * @return 查询执行器
     * @throws SHRWebException SHR Web异常
     * @throws ShrWebBizException 业务异常
     * @throws BOSException 业务异常
     * @throws ParserException 解析异常
     */
    public IQueryExecutor getQueryExecutor(Context context,
                                           EntityViewInfo entityViewInfo,
                                           String query) throws SHRWebException, ShrWebBizException, BOSException, ParserException {
        IQueryExecutor exec = QueryExecutorFactory.getLocalInstance(context, MetaDataPK.create(query)); // 创建查询执行器
        exec.setObjectView(entityViewInfo); // 设置对象视图
        exec.option().isIgnoreOrder = true; // 设置忽略排序
        exec.option().isAutoIgnoreZero = true; // 设置自动忽略零值
        exec.option().isAutoTranslateBoolean = true; // 设置自动转换布尔值
        exec.option().isAutoTranslateEnum = true; // 设置自动转换枚举
        exec.option().isIgnorePermissionCheck = false; // 设置不忽略权限检查
        return exec; // 返回查询执行器
    }

    /**
     * 获取业务接口
     * 根据实体名称获取对应的业务接口实例
     *
     * @param entityName 实体名称
     * @return 核心基础接口
     * @throws SHRWebException SHR Web异常
     */
    public ICoreBase getBizInterface(String entityName) throws SHRWebException {
        if (entityName == null) { // 检查实体名称是否为空
            return null; // 返回空值
        }
        try {
            return MetaDataUtil.getBizInterface(SHRContext.getInstance().getContext(), entityName); // 获取业务接口
        } catch (BOSException e) {
            e.printStackTrace();
            throw new SHRWebException(e); // 抛出SHR Web异常
        }
    }

    /**
     * 给CoreBaseInfo类型对象设置属性值，支持级联属性
     * 支持"主属性.子属性"格式的属性路径，可以设置嵌套对象的属性值
     *
     * @param ctx 上下文对象，用于获取元数据信息
     * @param coreBaseInfo 要设置属性值的目标对象
     * @param name 属性名称，支持"主属性.子属性"格式的级联属性
     * @param value 要设置的属性值
     * @throws BOSException 当操作过程中发生业务异常时抛出
     */
    public void setCoreBaseInfo(Context ctx, IObjectValue coreBaseInfo, String name, Object value) throws BOSException {
        // 判断是否为级联属性
        if (name.contains(".")) { // 检查是否包含点号
            String[] split = name.split("\\."); // 分割属性名称
            Object parentValue = coreBaseInfo.get(split[0]); // 获取父属性值

            // 获取实体元数据信息
            EntityObjectInfo entityObject = MetaDataUtil.getEntityObjectByBosType(coreBaseInfo.getBOSType()); // 获取实体对象信息
            PropertyCollection properties = entityObject.getInheritedNoDuplicatedProperties(); // 获取属性集合
            PropertyInfo propertyInfo = (PropertyInfo) properties.getObject(split[0]); // 获取属性信息
            // 处理关联属性
            if (propertyInfo instanceof LinkPropertyInfo) { // 检查是否为链接属性
                LinkPropertyInfo linkProperty = (LinkPropertyInfo) propertyInfo; // 转换属性信息
                RelationshipInfo relationship = linkProperty.getRelationship(); // 获取关系信息
                String targetFullName = relationship.getSupplierObject().getFullName(); // 获取目标完整名称
                try {
                    Class<?> targetClass = MetaDataUtil.getObjectValueClass(targetFullName); // 获取目标类
                    CoreBaseInfo childObject = getOrCreateChildObject(parentValue, targetClass, targetFullName); // 获取或创建子对象
                    // 给子对象设置级联属性的子属性值
                    if (childObject != null) { // 检查子对象是否为空
                        childObject.put(split[1], value); // 设置子属性值
                    }
                } catch (ShrWebBizException e) {
                    e.printStackTrace();
                    throw new BOSException("获取目标类失败: " + e.getMessage(), e); // 抛出业务异常
                }
            }
        } else {
            // 非级联属性，直接设置值
            coreBaseInfo.put(name, value); // 设置属性值
        }
    }

    /**
     * 获取或创建子对象
     * 根据父属性值的类型（集合或单个对象），获取现有子对象或创建新的子对象
     *
     * @param parentValue 父属性值
     * @param targetClass 目标类
     * @param targetFullName 目标全名
     * @return 子对象
     */
    public CoreBaseInfo getOrCreateChildObject(Object parentValue, Class<?> targetClass, String targetFullName) {
        CoreBaseInfo childObject = null; // 初始化子对象

        if (parentValue instanceof IObjectCollection) { // 检查父属性值是否为对象集合
            IObjectCollection collection = (IObjectCollection) parentValue; // 转换父属性值
            if (collection.size() == 0) { // 检查集合是否为空
                childObject = (CoreBaseInfo) MetaDataUtil.newInstance(targetClass, targetFullName); // 创建新实例
                collection.addObject(childObject); // 添加到集合
            } else {
                childObject = (CoreBaseInfo) collection.getObject(0); // 获取第一个对象
            }
        } else if (parentValue instanceof CoreBaseInfo) { // 检查父属性值是否为CoreBaseInfo
            if (parentValue == null) { // 检查是否为空
                childObject = (CoreBaseInfo) MetaDataUtil.newInstance(targetClass, targetFullName); // 创建新实例
            } else {
                childObject = (CoreBaseInfo) parentValue; // 使用现有对象
            }
        }

        return childObject; // 返回子对象
    }

    /**
     * 主方法，用于本地测试
     * 可以在此添加测试代码，验证类的功能
     *
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        // 测试代码可以在这里添加
        System.out.println("AssistSynchronizingFacadeControllerBean main method"); // 输出主方法信息
    }
}
