package com.ecep.contract.config;

import java.io.IOException;

import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;

import com.ecep.contract.model.IdentityEntity;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

/**
 * 专门用于处理HibernateProxy对象的序列化器
 */
class HibernateProxySerializer extends StdSerializer<HibernateProxy> {

    protected HibernateProxySerializer() {
        super(HibernateProxy.class);
    }

    @Override
    public void serialize(HibernateProxy value, JsonGenerator gen, SerializerProvider serializers) 
            throws IOException {
        // 尝试初始化代理对象，如果未初始化则只输出ID
        try {
            LazyInitializer lazyInitializer = value.getHibernateLazyInitializer();
            if (lazyInitializer.isUninitialized()) {
                // 如果代理对象未初始化，只输出ID
                if (lazyInitializer.getIdentifier() != null) {
                    gen.writeStartObject();
                    gen.writeFieldName("id");
                    gen.writeObject(lazyInitializer.getIdentifier());
                    gen.writeStringField("_proxy_", lazyInitializer.getEntityName());
                    gen.writeEndObject();
                } else {
                    gen.writeNull();
                }
            } else {
                // 如果代理对象已初始化，获取实际对象并序列化
                Object unwrapped = lazyInitializer.getImplementation();
                if (unwrapped instanceof IdentityEntity) {
                    // 对于IdentityEntity类型，输出更简洁的格式
                    gen.writeStartObject();
                    gen.writeNumberField("id", ((IdentityEntity) unwrapped).getId());
                    gen.writeEndObject();
                } else {
                    // 对于非IdentityEntity类型，使用默认序列化
                    serializers.defaultSerializeValue(unwrapped, gen);
                }
            }
        } catch (Exception e) {
            // 如果发生异常，输出最小化信息
            gen.writeStartObject();
            gen.writeStringField("error", "Failed to serialize Hibernate proxy: " + e.getMessage());
            gen.writeStringField("class", value.getClass().getName());
            gen.writeEndObject();
        }
    }
    
    @Override
    public void serializeWithType(HibernateProxy value, JsonGenerator gen, SerializerProvider serializers, 
            TypeSerializer typeSer) throws IOException {
        // 当启用类型信息时，Jackson会调用这个方法
        try {
            LazyInitializer lazyInitializer = value.getHibernateLazyInitializer();
            
            // 获取实际的实体类型名称
            String entityTypeName = lazyInitializer.getEntityName();
            Class<?> entityClass = Class.forName(entityTypeName);
            
            if (lazyInitializer.isUninitialized()) {
                // 确保输出@class: 'org.hibernate.proxy.HibernateProxy'
                // 直接使用HibernateProxy.class作为typeId
                gen.writeStartObject();
                gen.writeStringField("@class", "org.hibernate.proxy.HibernateProxy");
                // 对于未初始化的对象，添加代理信息
                gen.writeStringField("_proxy_", entityTypeName);
                // 写入ID信息
                if (lazyInitializer.getIdentifier() != null) {
                    gen.writeFieldName("id");
                    gen.writeObject(lazyInitializer.getIdentifier());
                }
                gen.writeEndObject();
            } else {
                // 如果代理对象已初始化，获取实际对象
                Object unwrapped = lazyInitializer.getImplementation();
                
                // 使用实际对象的类型信息进行序列化
                // 查找能够处理类型信息的序列化器
                JsonSerializer<Object> serializer = serializers.findTypedValueSerializer(
                        unwrapped.getClass(), true, null);
                
                // 委托给实际对象的序列化器处理，确保类型信息正确添加
                serializer.serializeWithType(unwrapped, gen, serializers, typeSer);
            }
        } catch (Exception e) {
            // 如果发生异常，输出最小化信息并添加类型信息
            // 先写入类型前缀
            typeSer.writeTypePrefix(gen, typeSer.typeId(value.getClass(), JsonToken.START_OBJECT));
            // 输出错误信息
            gen.writeStringField("error", "Failed to serialize Hibernate proxy with type: " + e.getMessage());
            gen.writeStringField("class", value.getClass().getName());
            // 写入类型后缀
            typeSer.writeTypeSuffix(gen, typeSer.typeId(value.getClass(), JsonToken.START_OBJECT));
        }
    }
}