package com.ruoyi.common.utils;

import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Component
public class NestedFieldAccessor {

    private static final Map<String, Method> METHOD_CACHE = new ConcurrentHashMap<>();
    private static final Map<String, Field> FIELD_CACHE = new ConcurrentHashMap<>();

    /**
     * 获取嵌套属性值
     * 支持：user.name、user.department.name、list[0].name 等格式
     */
    public Object getNestedFieldValue(Object obj, String fieldPath) {
        if (obj == null || fieldPath == null || fieldPath.trim().isEmpty()) {
            return null;
        }

        try {
            // 处理数组/列表索引
            if (fieldPath.contains("[")) {
                return getIndexedFieldValue(obj, fieldPath);
            }

            // 处理嵌套属性
            if (fieldPath.contains(".")) {
                return getNestedPropertyValue(obj, fieldPath);
            }

            // 简单属性
            return getSimplePropertyValue(obj, fieldPath);

        } catch (Exception e) {
            System.err.println("获取嵌套字段值失败: " + fieldPath + ", 错误: " + e.getMessage());
            // 返回空字符串而不是null，避免导出中断
            return "";
        }
    }

    /**
     * 获取嵌套属性值
     */
    private Object getNestedPropertyValue(Object obj, String fieldPath) {
        String[] parts = fieldPath.split("\\.");
        Object currentObj = obj;

        for (int i = 0; i < parts.length; i++) {
            String part = parts[i];

            if (currentObj == null) {
                System.err.println("路径中断: " + fieldPath + " 在 '" + part + "' 处对象为null");
                return null;
            }

            // 处理数组索引
            if (part.contains("[")) {
                currentObj = getIndexedFieldValue(currentObj, part);
            } else {
                currentObj = getSimplePropertyValue(currentObj, part);
            }

            // 如果中间任何一环为null，直接返回
            if (currentObj == null) {
                System.err.println("路径访问失败: " + fieldPath + " 在 '" + part + "' 处返回null");
                return null;
            }
        }

        return currentObj;
    }

    /**
     * 获取带索引的字段值（支持数组和List）
     */
    private Object getIndexedFieldValue(Object obj, String fieldPath) {
        // 解析字段名和索引：items[0] -> fieldName=items, index=0
        String fieldName = fieldPath.substring(0, fieldPath.indexOf('['));
        String indexStr = fieldPath.substring(fieldPath.indexOf('[') + 1, fieldPath.indexOf(']'));
        int index = Integer.parseInt(indexStr);

        Object fieldValue = getSimplePropertyValue(obj, fieldName);
        if (fieldValue == null) {
            return null;
        }

        // 处理List类型
        if (fieldValue instanceof List) {
            List<?> list = (List<?>) fieldValue;
            if (index >= 0 && index < list.size()) {
                return list.get(index);
            }
            return null;
        }

        // 处理数组类型
        if (fieldValue.getClass().isArray()) {
            Object[] array = (Object[]) fieldValue;
            if (index >= 0 && index < array.length) {
                return array[index];
            }
            return null;
        }

        return null;
    }

    /**
     * 获取简单属性值（优先使用getter方法，其次直接字段访问）
     */
    private Object getSimplePropertyValue(Object obj, String fieldName) {
        if (obj == null) {
            return null;
        }

        String cacheKey = obj.getClass().getName() + "#" + fieldName;

        try {
            // 1. 优先尝试getter方法
            Method getter = METHOD_CACHE.get(cacheKey);
            if (getter == null) {
                getter = findGetterMethod(obj.getClass(), fieldName);
                if (getter != null) {
                    METHOD_CACHE.put(cacheKey, getter);
                }
            }

            if (getter != null) {
                Object result = getter.invoke(obj);
                System.out.println("通过getter获取 '" + fieldName + "': " + result);
                return result;
            }

            // 2. 其次尝试直接字段访问
            Field field = FIELD_CACHE.get(cacheKey);
            if (field == null) {
                field = findField(obj.getClass(), fieldName);
                if (field != null) {
                    field.setAccessible(true);
                    FIELD_CACHE.put(cacheKey, field);
                }
            }

            if (field != null) {
                Object result = field.get(obj);
                System.out.println("通过字段获取 '" + fieldName + "': " + result);
                return result;
            }

            // 3. 如果都没找到，记录详细信息
            System.err.println("未找到属性 '" + fieldName + "' 在类 " + obj.getClass().getSimpleName());
            logAvailableProperties(obj);

        } catch (Exception e) {
            System.err.println("获取属性 '" + fieldName + "' 时出错: " + e.getMessage());
        }

        return null;
    }
    /**
     * 记录对象的可用属性
     */
    private void logAvailableProperties(Object obj) {
        if (obj == null) return;

        Class<?> clazz = obj.getClass();
        System.err.println("类 " + clazz.getSimpleName() + " 的可用属性:");

        // 字段
        System.err.println("  字段: " + Arrays.stream(clazz.getDeclaredFields())
                .map(f -> f.getName() + "(" + f.getType().getSimpleName() + ")")
                .collect(Collectors.joining(", ")));

        // getter方法
        System.err.println("  Getter方法: " + Arrays.stream(clazz.getMethods())
                .filter(m -> (m.getName().startsWith("get") || m.getName().startsWith("is")) && m.getParameterCount() == 0)
                .map(m -> m.getName() + "->" + m.getReturnType().getSimpleName())
                .collect(Collectors.joining(", ")));
    }

    /**
     * 查找getter方法
     */
    private Method findGetterMethod(Class<?> clazz, String fieldName) {
        String capitalized = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);

        // 尝试常规getter
        try {
            return clazz.getMethod("get" + capitalized);
        } catch (NoSuchMethodException e1) {
            // 尝试boolean类型的isGetter
            try {
                return clazz.getMethod("is" + capitalized);
            } catch (NoSuchMethodException e2) {
                return null;
            }
        }
    }

    /**
     * 查找字段
     */
    private Field findField(Class<?> clazz, String fieldName) {
        try {
            return clazz.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            // 在父类中查找
            if (clazz.getSuperclass() != null) {
                return findField(clazz.getSuperclass(), fieldName);
            }
            return null;
        }
    }

    /**
     * 清空缓存
     */
    public void clearCache() {
        METHOD_CACHE.clear();
        FIELD_CACHE.clear();
    }
}