package com.bcxin.backend.configs;

import com.bcxin.event.entities.EventSourceEntity;
import com.bcxin.event.repositories.EventSourceRepository;
import com.bcxin.runtime.domain.metas.repositories.ApplicationMetaRepository;
import com.bcxin.runtime.domain.metas.repositories.FormSyncMetaRepository;
import com.bcxin.runtime.domain.metas.repositories.FormSyncTargetMetaRepository;
import com.bcxin.runtime.domain.metas.repositories.TaskMetaRepository;
import com.bcxin.runtime.domain.metas.services.ApplicationMetaService;
import com.bcxin.runtime.domain.metas.services.FormSyncMetaService;
import com.bcxin.runtime.domain.metas.services.TaskMetaService;
import com.bcxin.runtime.domain.metas.services.impls.ApplicationMetaServiceImpl;
import com.bcxin.runtime.domain.metas.services.impls.FormSyncMetaServiceImpl;
import com.bcxin.runtime.domain.metas.services.impls.TaskMetaServiceImpl;
import com.bcxin.saas.core.components.JsonProvider;
import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl;
import org.hibernate.cfg.AvailableSettings;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration("com.bcxin.backend.configs.FormMetaSetupConfig")
@EnableJpaRepositories(
        basePackages = {"com.bcxin.runtime.domain.repositories.metas.repositories",
                        "com.bcxin.event.repositories"},
        entityManagerFactoryRef = "formMeta.entityManagerFactory",
        transactionManagerRef = "formMeta.transactionManager")
public class FormMetaSetupConfig {
    @Bean
    public ApplicationMetaService applicationMetaService(ApplicationMetaRepository applicationMetaRepository) {
        return new ApplicationMetaServiceImpl(applicationMetaRepository);
    }

    @Bean
    public FormSyncMetaService formSyncMetaService(ApplicationMetaRepository applicationMetaRepository,
                                                   FormSyncMetaRepository formSyncMetaRepository,
                                                   FormSyncTargetMetaRepository formSyncTargetMetaRepository,
                                                   JsonProvider jsonProvider) {
        return new FormSyncMetaServiceImpl(formSyncMetaRepository, applicationMetaRepository, jsonProvider,formSyncTargetMetaRepository);
    }

    @Bean
    public TaskMetaService taskMetaService(TaskMetaRepository taskMetaRepository,
                                           JsonProvider jsonProvider,
                                           ApplicationMetaRepository applicationMetaRepository) {
        return new TaskMetaServiceImpl(taskMetaRepository, jsonProvider, applicationMetaRepository);
    }

    /**
     * 注意, 这边使用.packages的方式来注册EntityScan,
     * 因此如果该Configuration使用@EntityScan的话，则不起作用
     *
     * @param dataSource
     * @param builder
     * @return
     */
    @Primary
    @Bean("formMeta.entityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(
            @Qualifier("dataSource")
                    DataSource dataSource,
            JpaProperties jpaProperties,
            EntityManagerFactoryBuilder builder) {
        Map<String, Object> properties = new HashMap();


        properties.put("hibernate.hbm2ddl.auto", "none");
        properties.put(AvailableSettings.PHYSICAL_NAMING_STRATEGY, PhysicalNamingStrategyStandardImpl.INSTANCE);
        properties.put(AvailableSettings.IMPLICIT_NAMING_STRATEGY, SpringImplicitNamingStrategy.INSTANCE);
        properties.put(AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS, true);

        return builder
                .dataSource(dataSource)
                .properties(properties)
                .packages(
                        com.bcxin.runtime.domain.metas.entities.ApplicationMetaEntity.class,
                        EventSourceEntity.class
                        /*
                        com.bcxin.runtime.domain.metas.entities.ApplicationMetaEntity.class,
                        com.bcxin.runtime.domain.imports.entities.DataQueueEntity.class
                         */
                )
                .build();
    }

    @Primary
    @Bean("formMeta.transactionManager")
    public PlatformTransactionManager transactionManager(
            final @Qualifier("formMeta.entityManagerFactory")
                    LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
        return new JpaTransactionManager(entityManagerFactoryBean.getObject());
    }
}
