package com.ecep.contract.util;

import java.lang.reflect.Field;
import java.lang.reflect.Proxy;

import com.ecep.contract.model.IdentityEntity;
import com.fasterxml.jackson.annotation.JsonIgnore;

public class ProxyUtils {
    /**
     * 判断传入的对象是否已完成初始化。
     * 在客户端接收服务器返回数据的场景下，代理对象序列化后通常仅包含 id 属性，其余属性均为 null。
     * 本方法通过检查对象除 id 外的其他非 @JsonIgnore 字段是否为 null 来判断对象是否已初始化。
     * 若执行过程中出现异常，则默认对象已初始化。
     * 
     * @param proxy 待检查的对象
     * @return 若对象已初始化返回 true，否则返回 false
     */
    public static boolean isInitialized(Object proxy) {
        if (proxy == null) {
            return false;
        }

        // 检查 proxy 中除了id其他属性都为null
        try {
            Field[] fields = proxy.getClass().getFields();
            for (Field field : fields) {
                if (field.getName().equals("id")) {
                    continue;
                }
                // 忽略被JsonIgnore注解标记的字段
                if (field.getAnnotation(JsonIgnore.class) != null) {
                    continue;
                }
                // 检查字段是否为null
                if (field.get(proxy) != null) {
                    return true;
                }
            }
            // 如果除了id其他属性都为null，认为未初始化
            return false;
        } catch (Exception e) {
            // 发生异常时默认已初始化
            return true;
        }
    }

    /**
     * 检查对象是否是代理对象
     */
    public static boolean isProxyObject(Object obj) {
        return false;
    }

    /**
     * 创建代理对象
     */
    @SuppressWarnings("unchecked")
    public static <T> T createProxy(T original, Class<?>... interfaces) {
        if (original == null) {
            return null;
        }

        // 如果对象已经是代理对象，直接返回
        if (isProxyObject(original)) {
            return original;
        }

        // 创建代理对象
        T proxy = (T) Proxy.newProxyInstance(
                original.getClass().getClassLoader(),
                interfaces,
                (proxyObj, method, args) -> {
                    // 如果代理对象未初始化，先初始化
                    if (!isInitialized(proxyObj)) {
                        // 这里可以添加初始化逻辑
                        markInitialized(proxyObj);
                    }
                    // 调用原始对象的方法
                    return method.invoke(original, args);
                });
        return proxy;
    }

    /**
     * 标记对象为已初始化
     */
    public static void markInitialized(Object proxy) {
        if (proxy != null && isProxyObject(proxy)) {
            // 标记为已初始化
        }
    }

    /**
     * 检查对象是否是实体类
     */
    public static boolean isEntityClass(Class<?> clazz) {
        return clazz != null && IdentityEntity.class.isAssignableFrom(clazz);
    }
}
