/*
 * File: src/main/java/reports/config/ProductDbConfig.java
 * Description: This configuration class sets up the data source, entity manager,
 * and transaction manager for the product database in the ERP application.
 * It uses HikariCP as the connection pool and configures JPA repositories
 * for managing product-related entities.
 *
 * Key Components:
 *
 * - **@Configuration**: Indicates that this class contains Spring configuration.
 *
 * - **@EnableJpaRepositories**: Enables JPA repositories in the specified package
 *   (com.nebula.erp.reports.repository.product) and associates them with the
 *   product entity manager and transaction manager.
 *
 * - **DataSource**: A bean method (`productDataSource`) initializes a HikariDataSource
 *   with properties prefixed with "spring.database.product", allowing configuration
 *   through application properties.
 *
 * - **LocalContainerEntityManagerFactoryBean**: The `productEntityManager` method
 *   configures the entity manager for product-related entities, setting the data source
 *   and specifying the package where entity classes are located (com.nebula.erp.reports.model.product).
 *
 * - **PlatformTransactionManager**: The `productTransactionManager` method creates a
 *   JPA transaction manager using the product entity manager, enabling transaction
 *   management for product-related database operations.
 *
 * This configuration is essential for ensuring that all product-related
 * database operations are handled through the specified data source and
 * transaction manager, maintaining separation from other database contexts in the application.
*/

package com.nebula.erp.reports.config;

import org.springframework.beans.factory.annotation.Qualifier;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

@Configuration
@EnableJpaRepositories(
        basePackages = "com.nebula.erp.reports.repository.product",  // Package to scan for JPA repositories
        entityManagerFactoryRef = "productEntityManager",  // Reference to the entity manager factory bean
        transactionManagerRef = "productTransactionManager"  // Reference to the transaction manager bean
)
public class ProductDbConfig {

    /*
     * Component: DataSource
     * This method initializes a HikariDataSource for managing connections to the product database.
     */
    @Bean(name = "productDataSource")  // Defines a bean named 'productDataSource'
    @ConfigurationProperties(prefix = "spring.database.product")
    public DataSource productDataSource() {
        return new HikariDataSource();
    }

    /*
     * Component: Entity Manager
     * This method configures the entity manager for product entities, linking it with the data source.
     */
    @Bean(name = "productEntityManager")  // Defines a bean named 'productEntityManager'
    public LocalContainerEntityManagerFactoryBean productEntityManager(
            @Qualifier("productDataSource") DataSource dataSource) {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource);
        em.setPackagesToScan("com.nebula.erp.reports.model.product");
        em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        return em;
    }

    /*
     * Component: Transaction Manager
     * This method creates a transaction manager for managing transactions associated with product operations.
     */
    @Bean(name = "productTransactionManager")  // Defines a bean named 'productTransactionManager'
    public PlatformTransactionManager productTransactionManager(
            @Qualifier("productEntityManager") LocalContainerEntityManagerFactoryBean productEntityManager) {
        return new JpaTransactionManager(productEntityManager.getObject());
    }
}
