package com.spring.infra.db;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy;

import com.zaxxer.hikari.HikariDataSource;

/**
 * 주 데이터 소스 설정을 위한 구성 클래스입니다.
 * 
 * <p>이 클래스는 애플리케이션의 주 데이터 소스를 설정하며, 다음과 같은 기능을 제공합니다:</p>
 * <ul>
 *   <li>주 데이터 소스 속성 설정</li>
 *   <li>HikariCP를 사용한 주 데이터 소스 생성</li>
 * </ul>
 * 
 * @author mindol
 * @version 1.0
 */
@Configuration
public class PrimaryDataSourceConfig {

    public static final String DATABASE = "primary";
    public static final String DATASOURCE = "primaryDataSource";
    private static final String DATASOURCE_PROPERTIES = "primaryDataSourceProperties";
    private static final String DATASOURCE_PROPERTIES_PREFIX = "spring.datasource.primary";

    /**
     * 주 데이터 소스의 속성을 설정합니다.
     * 
     * <p>이 메소드는 'spring.datasource.primary' 접두사로 시작하는 설정을 읽어
     * DataSourceProperties 객체를 생성합니다.</p>
     * 
     * @return 설정된 DataSourceProperties 객체
     */
    @Primary
    @Bean(name = DATASOURCE_PROPERTIES)
    @ConfigurationProperties(prefix = DATASOURCE_PROPERTIES_PREFIX)
    DataSourceProperties dataSourceProperties() {
        return new DataSourceProperties();
    }
    
    /**
     * 주 데이터 소스를 생성합니다.
     * 
     * <p>이 메소드는 설정된 DataSourceProperties를 사용하여 HikariCP 데이터 소스를 생성합니다.</p>
     * 
     * @param properties 데이터 소스 속성
     * @return 생성된 DataSource 객체
     */
    @Primary
    @Bean(name = DATASOURCE)
    DataSource dataSource(@Qualifier(DATASOURCE_PROPERTIES) DataSourceProperties properties) {
        return new LazyConnectionDataSourceProxy( // 커넥션이 필요한 경우에만 datasource 에서 connection 을 반환
            properties.initializeDataSourceBuilder().type(HikariDataSource.class).build()
        );
    }

}
