package incheon.com.config;

import incheon.com.cmm.MybatisClobStringTypeHandler;
import incheon.com.config.mybatis.MybatisUserSessionInterceptor;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.*;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.io.IOException;

/**
 * @ClassName : EgovConfigAppMapper.java
 * @Description : MyBatis 매퍼 설정
 *
 * @author : 윤주호
 * @since  : 2021. 7. 20
 * @version : 1.0
 *
 * <pre>
 * << 개정이력(Modification Information) >>
 *
 *   수정일              수정자               수정내용
 *  -------------  ------------   ---------------------
 *   2021. 7. 20    윤주호               최초 생성
 *   2024. 12. 19   개선작업             deprecated AltibaseClobStringTypeHandler를 MybatisClobStringTypeHandler로 교체
 * </pre>
 */
@Configuration
@PropertySources({
	@PropertySource("classpath:/application.properties"),
	@PropertySource(value = "classpath:/application-${spring.profiles.active}.properties", ignoreResourceNotFound = true)
})
public class EgovConfigAppMapper {

	/**
	 * SqlSessionFactory
	 */
	@Primary
	@Bean(name = "sqlSessionFactory")
	public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
		SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
		sqlSessionFactoryBean.setDataSource(dataSource);

		// MyBatis 설정
		sqlSessionFactoryBean.setConfigLocation(
			new PathMatchingResourcePatternResolver().getResource("classpath:/incheon/mapper/config/mapper-config.xml")
		);

		// 인터셉터 등록 (사용자 세션 자동 주입)
		sqlSessionFactoryBean.setPlugins(new Interceptor[]{new MybatisUserSessionInterceptor()});

		// 타입 핸들러 설정 제거 (전역 적용 시 문제 발생)
		// sqlSessionFactoryBean.setTypeHandlers(new MybatisClobStringTypeHandler());

		// 매퍼 파일 로드
		PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();

		try {
			Resource[] allMappers = pathMatchingResourcePatternResolver
					.getResources("classpath:/incheon/mapper/**/*.xml");

			// mapper-config.xml만 제외하고 모든 매퍼 파일 로드
			Resource[] mappers = java.util.Arrays.stream(allMappers)
					.filter(mapper -> !"mapper-config.xml".equals(mapper.getFilename()))
					.toArray(Resource[]::new);

			sqlSessionFactoryBean.setMapperLocations(mappers);
		} catch (IOException e) {
			throw new RuntimeException("매퍼 파일 로드 중 오류 발생", e);
		}

		return sqlSessionFactoryBean.getObject();
	}

	/**
	 * SqlSessionTemplate
	 */
	@Primary
	@Bean(name = "sqlSessionTemplate")
	public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
		return new SqlSessionTemplate(sqlSessionFactory);
	}

	/**
	 * BatchSqlSessionTemplate
	 */
	@Bean(name = "batchSqlSessionTemplate")
	public SqlSessionTemplate batchSqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
		return new SqlSessionTemplate(sqlSessionFactory, ExecutorType.BATCH);
	}

	/**
	 * 외부 DB SqlSessionFactory
	 */
	@Bean(name = "externalSqlSessionFactory")
	public SqlSessionFactory externalSqlSessionFactory(@Qualifier("externalDataSource") DataSource externalDataSource) throws Exception {
		SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
		sqlSessionFactoryBean.setDataSource(externalDataSource);

		// MyBatis 설정
		sqlSessionFactoryBean.setConfigLocation(
			new PathMatchingResourcePatternResolver().getResource("classpath:/incheon/mapper-ext/config/mapper-config.xml")
		);

		// 인터셉터 등록 (사용자 세션 자동 주입)
		sqlSessionFactoryBean.setPlugins(new Interceptor[]{new MybatisUserSessionInterceptor()});

		// 타입 핸들러 설정 제거 (전역 적용 시 문제 발생)
		// sqlSessionFactoryBean.setTypeHandlers(new MybatisClobStringTypeHandler());

		// 매퍼 파일 로드
		PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();

		try {
			Resource[] allMappers = pathMatchingResourcePatternResolver
					.getResources("classpath:/incheon/mapper-ext/**/*.xml");

			// mapper-config.xml만 제외하고 모든 매퍼 파일 로드
			Resource[] mappers = java.util.Arrays.stream(allMappers)
					.filter(mapper -> !"mapper-config.xml".equals(mapper.getFilename()))
					.toArray(Resource[]::new);

			sqlSessionFactoryBean.setMapperLocations(mappers);
		} catch (IOException e) {
			throw new RuntimeException("외부 DB 매퍼 파일 로드 중 오류 발생", e);
		}

		return sqlSessionFactoryBean.getObject();
	}

	/**
	 * 외부 DB SqlSessionTemplate
	 */
	@Bean(name = "externalSqlSessionTemplate")
	public SqlSessionTemplate externalSqlSessionTemplate(@Qualifier("externalSqlSessionFactory") SqlSessionFactory externalSqlSessionFactory) {
		return new SqlSessionTemplate(externalSqlSessionFactory);
	}
}
