package com.ga.common.mybatis;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import org.postgresql.util.PGobject;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * PostgreSQL JSONB ↔ Jackson JsonNode 변환 TypeHandler.
 */
@MappedTypes(JsonNode.class)
public class JsonTypeHandler extends BaseTypeHandler<JsonNode> {

    private static final ObjectMapper M = new ObjectMapper();

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, JsonNode parameter, JdbcType jdbcType) throws SQLException {
        PGobject pg = new PGobject();
        pg.setType("jsonb");
        try {
            pg.setValue(M.writeValueAsString(parameter));
        } catch (Exception e) {
            throw new SQLException(e);
        }
        ps.setObject(i, pg);
    }

    @Override public JsonNode getNullableResult(ResultSet rs, String columnName) throws SQLException { return parse(rs.getString(columnName)); }
    @Override public JsonNode getNullableResult(ResultSet rs, int columnIndex) throws SQLException   { return parse(rs.getString(columnIndex)); }
    @Override public JsonNode getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return parse(cs.getString(columnIndex)); }

    private JsonNode parse(String json) throws SQLException {
        if (json == null || json.isBlank()) return null;
        try {
            return M.readTree(json);
        } catch (Exception e) {
            throw new SQLException(e);
        }
    }
}
