package org.dromara.zjk.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.dromara.common.core.service.DictService;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.zjk.annotation.PropertyMsg;
import org.dromara.zjk.service.IZjkExpertMoneyConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.*;

@Component
public class FieldChangeRecorderUtils {

    private static DictService dictService;

    private static IZjkExpertMoneyConfigService zjkExpertMoneyConfigService;

    @Autowired
    public FieldChangeRecorderUtils(DictService dictService,IZjkExpertMoneyConfigService  zjkExpertMoneyConfigService) {
        FieldChangeRecorderUtils.dictService = dictService;
        FieldChangeRecorderUtils.zjkExpertMoneyConfigService = zjkExpertMoneyConfigService;
    }

    /**
     * 记录新增的数据，返回字段描述及对应的值的 JSON 字符串，处理嵌套的 List 并根据字典替换值。
     * @param newObject 新增对象
     * @return JSON 字符串，包含字段描述及其值的映射
     */
    public static String recordNewData(Object newObject) {
        Map<String, Object> changes = new HashMap<>();
        Set<String> ignoredFields = Set.of("createBy", "createTime", "updateBy", "updateTime","status"); // 忽略字段集合
        try {
            Field[] fields = newObject.getClass().getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true); // 允许访问私有字段
                // 跳过未标注 @PropertyMsg 注解的字段
                if (!field.isAnnotationPresent(PropertyMsg.class)) {
                    continue;
                }
                // 跳过忽略字段
                if (ignoredFields.contains(field.getName())) {
                    continue;
                }
                PropertyMsg propertyMsg = field.getAnnotation(PropertyMsg.class);
                String propertyName = propertyMsg.propertyName();
                Object value = field.get(newObject);
                if (value == null || (value instanceof String && ((String) value).trim().isEmpty())) {
                    continue; // 跳过空值字段
                }
                String dictType = propertyMsg.dictType();
                // 如果字段有dictType 注解，进行字典替换
                if (!dictType.isEmpty()) {
                    // 调用 dictService.getDictLabel 方法进行字典替换
                    if (value instanceof List<?>) {
                        List<Map<String, Object>> translatedList = new ArrayList<>();
                        for (Object item : (List<?>) value) {
                            translatedList.add(processListItem(item, dictType));
                        }
                        changes.put(propertyName, translatedList);
                    } else {
                        value = dictService.getDictLabel(dictType, value.toString());
                        changes.put(propertyName, value);
                    }
                } else {
                    // 无字典替换时的正常处理
                    if (value instanceof List<?>) {
                        List<Object> processedList = new ArrayList<>();
                        for (Object item : (List<?>) value) {
                            processedList.add(processSingleObject(item)); // 递归处理
                        }
                        changes.put(propertyName, processedList);
                    } else {
                        changes.put(propertyName, value);
                    }
                }
            }

            // 转换 Map 为 JSON 字符串
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.writeValueAsString(changes);

        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return "{}";
    }

    /**
     * 处理 List 中的每个元素，若该元素的字段含有字典注解则进行字典替换。
     * @param item 列表项对象
     * @param dictionaryName 字典名称
     * @return 字典替换后的字段值映射
     */
    private static Map<String, Object> processListItem(Object item, String dictionaryName) {
        Map<String, Object> fieldValues = new HashMap<>();
        if (item == null) {
            return fieldValues;
        }

        try {
            Field[] fields = item.getClass().getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);

                if (!field.isAnnotationPresent(PropertyMsg.class)) {
                    continue;
                }

                PropertyMsg propertyMsg = field.getAnnotation(PropertyMsg.class);
                String propertyName = propertyMsg.propertyName();
                Object value = field.get(item);

                if (value == null || (value instanceof String && ((String) value).trim().isEmpty())) {
                    continue; // 跳过空值字段
                }

                String dictType = propertyMsg.dictType();
                // 递归处理嵌套对象或列表
                if (value instanceof List<?>) {
                    List<Object> processedList = new ArrayList<>();
                    for (Object listItem : (List<?>) value) {
                        processedList.add(processListItem(listItem, dictionaryName)); // 递归处理列表内的对象
                    }
                    fieldValues.put(propertyName, processedList);
                } else if (!dictType.isEmpty()) {
                    value = dictService.getDictLabel(dictType, value.toString());
                    fieldValues.put(propertyName, value);
                } else {
                    fieldValues.put(propertyName, value);
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        return fieldValues;
    }



    /**
     * 通过反射对比两个实体类数据值差异，并返回变更前和变更后的数据，支持嵌套对象和字典转换。
     * @param oldObject 变更前的实体对象
     * @param newObject 变更后的实体对象
     * @return 包含变更前和变更后字段描述及值的映射，返回 JSON 格式
     */
    public static Map<String, Map<String, Object>> compareAndRecordChanges(Object oldObject, Object newObject) {
        Map<String, Object> beforeChanges = new HashMap<String, Object>();
        Map<String, Object> afterChanges = new HashMap<String, Object>();
        Set<String> ignoredFields = Set.of("createBy", "createTime", "updateBy", "updateTime", "tenantId", "createDept");

        try {
            Field[] fields = oldObject.getClass().getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);

                // 跳过未标注 @PropertyMsg 注解的字段
                if (!field.isAnnotationPresent(PropertyMsg.class)) {
                    continue;
                }

                // 跳过忽略字段
                if (ignoredFields.contains(field.getName())) {
                    continue;
                }

                PropertyMsg propertyMsg = field.getAnnotation(PropertyMsg.class);
                String propertyName = propertyMsg.propertyName();
                Object oldValue = field.get(oldObject);
                Object newValue = field.get(newObject);
                if (Objects.isNull(oldValue) && Objects.isNull(newValue)) {
                    continue;
                }
                // 处理 List 类型字段
                if (oldValue instanceof List<?> && newValue instanceof List<?>) {
                    List<?> oldList = (List<?>) oldValue;
                    List<?> newList = (List<?>) newValue;

                    boolean hasDifference = false;

                    List<Map<String, Object>> oldListChanges = getItemListChanges(oldList);
                    List<Map<String, Object>> newListChanges = getItemListChanges(newList);

                    // 检查两列表内容是否不同
                    if (!oldListChanges.equals(newListChanges)) {
                        hasDifference = true;
                    }

                    if (hasDifference) {
                        // 检查两列表是否不同或其中一个不为空
                        if (!oldListChanges.equals(newListChanges) || !oldList.isEmpty() || !newList.isEmpty()) {
                            // 检查只要有一个列表不为空就记录
                            if (!oldList.isEmpty() || !newList.isEmpty()) {
                                beforeChanges.put(propertyName, oldListChanges);
                                afterChanges.put(propertyName, newListChanges);
                            }
                        }
                    }
                } else {
                    // 处理非 List 类型字段的差异，只在值不同情况下记录
                    String dictType = propertyMsg.dictType();
                    String tableName = propertyMsg.tableName();
                    if (!dictType.isEmpty()) {
                        oldValue = oldValue != null ? dictService.getDictLabel(dictType, oldValue.toString()) : null;
                        newValue = newValue != null ? dictService.getDictLabel(dictType, newValue.toString()) : null;
                    } else if (!tableName.isEmpty()) {
                        // 表明不为空 根据 id 获取对应的数据
                        if (oldValue instanceof Long && newValue instanceof Long) {
                            oldValue = oldValue != null && zjkExpertMoneyConfigService.queryById((Long) oldValue) != null
                                ? zjkExpertMoneyConfigService.queryById((Long) oldValue).getMoneyType()
                                : null;
                            newValue = newValue != null && zjkExpertMoneyConfigService.queryById((Long) newValue)!=null
                                ?zjkExpertMoneyConfigService.queryById((Long) newValue).getMoneyType()
                                : null;
                        }
                    } else {
                        if (oldValue instanceof Date && newValue instanceof Date) {
                            oldValue = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, (Date) oldValue);
                            newValue = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, (Date) newValue);
                        }
                    }

                    if (!Objects.equals(oldValue, newValue)) {
                        beforeChanges.put(propertyName, oldValue != null ? oldValue : "");
                        afterChanges.put(propertyName, newValue != null ? newValue : "");
                    }
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        Map<String, Map<String, Object>> result = new HashMap<>();
        result.put("beforeOper", beforeChanges);
        result.put("afterOper", afterChanges);
        return result;
    }

    private static List<Map<String, Object>> getItemListChanges(List<?> itemList) {
        List<Map<String, Object>> itemChangesList = new ArrayList<>();
        for (Object item : itemList) {
            Map<String, Object> itemChanges = new HashMap<>();
            Field[] itemFields = item.getClass().getDeclaredFields();
            for (Field field : itemFields) {
                field.setAccessible(true);
                if (!field.isAnnotationPresent(PropertyMsg.class)) {
                    continue;
                }
                PropertyMsg propertyMsg = field.getAnnotation(PropertyMsg.class);
                String propertyName = propertyMsg.propertyName();
                String dictType = propertyMsg.dictType();

                try {
                    Object value = field.get(item);
                    if (!dictType.isEmpty()) {
                        value = value != null ? dictService.getDictLabel(dictType, value.toString()) : null;
                    } else if (value instanceof Date) {
                        value = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, (Date) value);
                    }

                    if (value != null) {
                        itemChanges.put(propertyName, value);
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            itemChangesList.add(itemChanges);
        }
        return itemChangesList;
    }



    /**
     * 递归处理对象，返回字段描述及对应的值。
     * @param obj 需要处理的对象
     * @return 字段描述及值的 Map
     */
    private static Map<String, Object> processSingleObject(Object obj) {
        Map<String, Object> changes = new HashMap<>();
        if (obj == null) {
            return changes;
        }

        try {
            Field[] fields = obj.getClass().getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true); // 允许访问私有字段
                // 跳过未标注 @PropertyMsg 注解的字段
                if (!field.isAnnotationPresent(PropertyMsg.class)) {
                    continue;
                }

                PropertyMsg propertyMsg = field.getAnnotation(PropertyMsg.class);
                String propertyName = propertyMsg.propertyName();
                Object value = field.get(obj);

                if (value == null || (value instanceof String && ((String) value).trim().isEmpty())) {
                    continue; // 跳过空值字段
                }

                String dictType = propertyMsg.dictType();
                // 检查是否有 dictType 并进行字典转换
                if (!dictType.isEmpty()) {
                    value = dictService.getDictLabel(dictType, value.toString());
                }

                changes.put(propertyName, value);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        return changes;
    }

}


