package com.qqchen.deploy.backend.workflow.entity.converter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qqchen.deploy.backend.workflow.dto.definition.workflow.WorkflowDefinitionGraph;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.usertype.UserType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

/**
 * 自定义 Hibernate 类型，用于处理 WorkflowGraph 的序列化和反序列化
 */
public class WorkflowGraphType implements UserType<WorkflowDefinitionGraph> {
    private static final Logger log = LoggerFactory.getLogger(WorkflowGraphType.class);
    private final ObjectMapper objectMapper;

    public WorkflowGraphType() {
        this.objectMapper = new ObjectMapper();
        // 配置 ObjectMapper
        this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    @Override
    public int getSqlType() {
        return Types.VARCHAR;
    }

    @Override
    public Class<WorkflowDefinitionGraph> returnedClass() {
        return WorkflowDefinitionGraph.class;
    }

    @Override
    public boolean equals(WorkflowDefinitionGraph x, WorkflowDefinitionGraph y) {
        if (x == y) {
            return true;
        }
        if (x == null || y == null) {
            return false;
        }
        return x.equals(y);
    }

    @Override
    public int hashCode(WorkflowDefinitionGraph x) {
        return x == null ? 0 : x.hashCode();
    }

    @Override
    public WorkflowDefinitionGraph nullSafeGet(ResultSet rs, int position, SharedSessionContractImplementor session, Object owner)
            throws SQLException {
        String value = rs.getString(position);
        if (value == null) {
            return null;
        }
        try {
            return objectMapper.readValue(value, WorkflowDefinitionGraph.class);
        } catch (JsonProcessingException e) {
            // 记录错误日志，但不抛出异常，返回 null 使得单条记录的错误不影响整体查询
            log.error("Failed to convert String to WorkflowGraph: " + value, e);
            return null;
        }
    }

    @Override
    public void nullSafeSet(PreparedStatement st, WorkflowDefinitionGraph value, int index, SharedSessionContractImplementor session)
            throws SQLException {
        if (value == null) {
            st.setNull(index, Types.VARCHAR);
            return;
        }
        try {
            st.setString(index, objectMapper.writeValueAsString(value));
        } catch (JsonProcessingException e) {
            throw new HibernateException("Failed to convert WorkflowGraph to String: " + value, e);
        }
    }

    @Override
    public WorkflowDefinitionGraph deepCopy(WorkflowDefinitionGraph value) {
        if (value == null) {
            return null;
        }
        try {
            return objectMapper.readValue(objectMapper.writeValueAsString(value), WorkflowDefinitionGraph.class);
        } catch (JsonProcessingException e) {
            throw new HibernateException("Failed to deep copy WorkflowGraph", e);
        }
    }

    @Override
    public boolean isMutable() {
        return true;
    }

    @Override
    public Serializable disassemble(WorkflowDefinitionGraph value) {
        try {
            return value == null ? null : objectMapper.writeValueAsString(value);
        } catch (JsonProcessingException e) {
            throw new HibernateException("Failed to disassemble WorkflowGraph", e);
        }
    }

    @Override
    public WorkflowDefinitionGraph assemble(Serializable cached, Object owner) {
        try {
            return cached == null ? null : objectMapper.readValue(cached.toString(), WorkflowDefinitionGraph.class);
        } catch (JsonProcessingException e) {
            throw new HibernateException("Failed to assemble WorkflowGraph", e);
        }
    }

    @Override
    public WorkflowDefinitionGraph replace(WorkflowDefinitionGraph detached, WorkflowDefinitionGraph managed, Object owner) {
        return deepCopy(detached);
    }
}
