package cn.reghao.tnb.content.app.config.shard;

import com.zaxxer.hikari.HikariDataSource;
import org.apache.shardingsphere.driver.api.ShardingSphereDataSourceFactory;
import org.apache.shardingsphere.infra.algorithm.core.config.AlgorithmConfiguration;
import org.apache.shardingsphere.infra.config.mode.ModeConfiguration;
import org.apache.shardingsphere.infra.config.props.ConfigurationPropertyKey;
import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
import org.apache.shardingsphere.mode.repository.standalone.StandalonePersistRepositoryConfiguration;
import org.apache.shardingsphere.readwritesplitting.config.ReadwriteSplittingRuleConfiguration;
import org.apache.shardingsphere.readwritesplitting.config.rule.ReadwriteSplittingDataSourceGroupRuleConfiguration;
import org.apache.shardingsphere.single.config.SingleRuleConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.*;

/**
 * resources/sharding.yml 配置文件的 Java API 版本
 *
 * @author reghao
 * @date 2025-10-28 15:11:37
 */
//@Configuration
public class ShardingSphereConfig {
    @Bean
    public DataSource getShardingDataSource() throws SQLException {
        String databaseName = "readwrite_ds";
        ModeConfiguration modeConfig = new ModeConfiguration("Standalone", new StandalonePersistRepositoryConfiguration("JDBC", new Properties()));
        Map<String, DataSource> dataSourceMap = createDataSourceMap();

        Collection<RuleConfiguration> ruleConfigs = new ArrayList<>();
        SingleRuleConfiguration ruleConfig = new SingleRuleConfiguration();
        ruleConfig.setTables(List.of("*.*"));
        ruleConfigs.add(ruleConfig);

        ReadwriteSplittingRuleConfiguration ruleConfig1 = getRuleConfig();
        ruleConfigs.add(ruleConfig1);

        Properties props = new Properties();
        props.put(ConfigurationPropertyKey.SQL_SHOW.getKey(), false);
        return ShardingSphereDataSourceFactory.createDataSource(databaseName, modeConfig, dataSourceMap, ruleConfigs, props);
    }

    public ReadwriteSplittingRuleConfiguration getRuleConfig() {
        ReadwriteSplittingDataSourceGroupRuleConfiguration dataSourceConfig =
                new ReadwriteSplittingDataSourceGroupRuleConfiguration(
                        "demo_read_query_ds",
                        "write_ds",
                        Arrays.asList("read_ds_0"),
                        "demo_weight_lb");

        Collection<ReadwriteSplittingDataSourceGroupRuleConfiguration> dataSourceGroups = new ArrayList<>();
        dataSourceGroups.add(dataSourceConfig);

        Properties algorithmProps = new Properties();
        algorithmProps.setProperty("read_ds_0", "2");
        //algorithmProps.setProperty("demo_read_ds_1", "1");
        Map<String, AlgorithmConfiguration> loadBalancers = new HashMap<>(1);
        loadBalancers.put("demo_weight_lb", new AlgorithmConfiguration("WEIGHT", algorithmProps));

        ReadwriteSplittingRuleConfiguration ruleConfig = new ReadwriteSplittingRuleConfiguration(dataSourceGroups, loadBalancers);
        return ruleConfig;
    }

    private Map<String, DataSource> createDataSourceMap() {
        String jdbcUrl1 = "jdbc:mysql://localhost:3306/tnb_content_rdb?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8&allowPublicKeyRetrieval=true";
        String jdbcUrl2 = "jdbc:mysql://localhost:3306/tnb_content_rdb?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8&allowPublicKeyRetrieval=true";

        Map<String, DataSource> dataSourceMap = new HashMap<>();
        // 配置第 1 个数据源
        HikariDataSource dataSource1 = new HikariDataSource();
        dataSource1.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource1.setJdbcUrl(jdbcUrl1);
        dataSource1.setUsername("dev");
        dataSource1.setPassword("Test_123456");
        dataSourceMap.put("write_ds", dataSource1);

        // 配置第 2 个数据源
        HikariDataSource dataSource2 = new HikariDataSource();
        dataSource2.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource2.setJdbcUrl(jdbcUrl2);
        dataSource2.setUsername("dev");
        dataSource2.setPassword("Test_123456");
        dataSourceMap.put("read_ds_0", dataSource2);
        return dataSourceMap;
    }
}
