package incheon.com.cmm;

import java.io.IOException;
import java.io.Reader;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Clob;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import lombok.extern.slf4j.Slf4j;

/**
 * MyBatis TypeHandler implementation for Strings that get mapped to CLOBs.
 * 
 * <p>Particularly useful for storing Strings with more than 4000 characters in an
 * Oracle database (only possible via CLOBs), and for Altibase database compatibility.
 *
 * <p>This handler replaces the deprecated AltibaseClobStringTypeHandler which was
 * based on the deprecated iBATIS AbstractLobTypeHandler.
 *
 * @author 개선작업
 * @since 2024.12.19
 * @version 1.0
 * 
 * <pre>
 * << 개정이력(Modification Information) >>
 *
 *   수정일              수정자               수정내용
 *  -------------  ------------   ---------------------
 *   2024.12.19    개선작업             최초 생성 (AltibaseClobStringTypeHandler 대체)
 * </pre>
 */
@Slf4j
public class MybatisClobStringTypeHandler extends BaseTypeHandler<String> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        // String을 CLOB으로 설정
        ps.setString(i, parameter);
    }

    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return getClobAsString(rs.getClob(columnName));
    }

    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return getClobAsString(rs.getClob(columnIndex));
    }

    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return getClobAsString(cs.getClob(columnIndex));
    }

    /**
     * CLOB 데이터를 String으로 변환
     * 
     * @param clob CLOB 객체
     * @return String 변환된 문자열
     * @throws SQLException SQL 예외
     */
    private String getClobAsString(Clob clob) throws SQLException {
        if (clob == null) {
            return null;
        }

        StringBuilder sb = new StringBuilder();
        Reader reader = null;
        
        try {
            reader = clob.getCharacterStream();
            char[] buffer = new char[1024];
            int length;
            
            while ((length = reader.read(buffer)) != -1) {
                sb.append(buffer, 0, length);
            }
            
            return sb.toString();
            
        } catch (IOException e) {
            log.error("CLOB 데이터 읽기 중 오류 발생: {}", e.getMessage(), e);
            throw new SQLException("CLOB 데이터 읽기 중 오류 발생", e);
            
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    log.debug("Reader 닫기 중 오류 발생 (무시): {}", e.getMessage());
                }
            }
        }
    }
} 