package com.spring.infra.db.orm.mybatis;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import com.spring.infra.db.SecondaryDataSourceConfig;
import com.spring.infra.db.orm.mybatis.annotation.SecondaryMapper;

/**
 * 보조 데이터베이스에 대한 MyBatis 설정을 담당하는 구성 클래스입니다.
 * 
 * <p>이 클래스는 다음과 같은 주요 기능을 제공합니다:</p>
 * <ul>
 *   <li>보조 데이터베이스용 SqlSessionFactory 설정</li>
 *   <li>MyBatis 매퍼 스캔 설정</li>
 *   <li>MyBatis 관련 설정 (카멜 케이스 변환, null 처리 등)</li>
 * </ul>
 * 
 * @author mindol
 * @version 1.0
 */
@Configuration
@MapperScan(
    basePackages = {SecondaryMybatisConfig.BASE_PACKAGE},
    sqlSessionFactoryRef = SecondaryMybatisConfig.SESSION_FACTORY,
    annotationClass = SecondaryMapper.class
)
public class SecondaryMybatisConfig {

    private static final String BASE_PACKAGE = "com.spring.domain.*.mapper";
    private static final String ALIASES_PACKAGE = "com.spring.domain.*.dto,com.spring.domain.*.entity";
    private static final String MAPPER_RESOURCES = "classpath:mapper/**/*.xml";
    private static final String SESSION_FACTORY = "secondarySqlSessionFactory";

    /**
     * 보조 데이터베이스용 SqlSessionFactory를 생성합니다.
     * 
     * @param dataSource 보조 데이터 소스
     * @return 구성된 SqlSessionFactory 객체
     * @throws Exception SqlSessionFactory 생성 중 발생할 수 있는 예외
     */
    @Bean(name = SESSION_FACTORY)
    SqlSessionFactory sqlSessionFactory(@Qualifier(SecondaryDataSourceConfig.DATASOURCE) DataSource dataSource) throws Exception {
        var sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setConfiguration(mybatisConfiguration());
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_RESOURCES));
        sessionFactory.setTypeAliasesPackage(ALIASES_PACKAGE);
        sessionFactory.setVfs(SpringBootVFS.class);
        return sessionFactory.getObject();
    }

    /**
     * MyBatis 설정을 구성합니다.
     * 
     * @return 구성된 MyBatis Configuration 객체
     */
    private org.apache.ibatis.session.Configuration mybatisConfiguration() {
        var configuration = new org.apache.ibatis.session.Configuration();
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setCallSettersOnNulls(true);
        configuration.setReturnInstanceForEmptyRow(true);
        configuration.setJdbcTypeForNull(JdbcType.NULL);
        return configuration;
    }

}
