package com.eactive.eai.rms.data.config;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.hibernate.cfg.AvailableSettings;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
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.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.eactive.eai.data.jpa.BaseRepositoryImpl;
import com.eactive.eai.rms.data.EMSDataSource;
import com.eactive.kakao.rolling.TableSuffixResolver;

@Configuration
@EnableScheduling
@EnableTransactionManagement
@EnableJpaAuditing(auditorAwareRef = "EMSAuditorAware")
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactory", transactionManagerRef = "transactionManager", basePackages = {
		"com.eactive.eai", }, repositoryBaseClass = BaseRepositoryImpl.class, excludeFilters = {
				@Filter(classes = EMSDataSource.class)
				,
//				@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = { DataLoaderRepository.class }) 
				})
public class MultitenantConfiguration {

	@Bean("entityManagerFactory")
	@Primary
	public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
			@Qualifier("hibernateProperties") Properties hibernateProperties) {
		LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
		bean.setDataSource(dataSource);
		bean.setPackagesToScan("com.eactive.eai.data", "com.eactive.eai.rms.data");
		bean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());

		bean.setJpaProperties(hibernateProperties);

		Map<String, Object> settings = new HashMap<>();
		settings.put(AvailableSettings.MULTI_TENANT, "SCHEMA");
		settings.put(AvailableSettings.MULTI_TENANT_CONNECTION_PROVIDER, configurableMultiTenantConnectionProvider());
		settings.put(AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER, tenantIdentifierResolver());

		bean.setJpaPropertyMap(settings);

		return bean;
	}

	@Bean("transactionManager")
	@Primary
	public TransactionManager transactionManager(DataSource dataSource, EntityManagerFactory entityManagerFactory) {
		JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
		jpaTransactionManager.setDataSource(dataSource);
		jpaTransactionManager.setEntityManagerFactory(entityManagerFactory);
		return jpaTransactionManager;
	}

	@Bean
	public ConfigurableMultiTenantConnectionProvider configurableMultiTenantConnectionProvider() {
		return new ConfigurableMultiTenantConnectionProvider();
	}

	@Bean
	public TenantIdentifierResolver tenantIdentifierResolver() {
		return new TenantIdentifierResolver();
	}

	@Bean
	public TableSuffixResolver tableSuffixResolver() {
		return () -> "";
	}

}
