package com.muyu.cloud.common.many.datasource;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
import com.muyu.cloud.common.many.datasource.domain.model.DataSourceInfo;
import com.muyu.cloud.common.many.datasource.factory.DruidDataSourceFactory;
import com.muyu.cloud.common.many.datasource.role.DynamicDataSource;
import com.muyu.cloud.common.saas.domain.model.EntInfo;
import com.muyu.cloud.common.saas.exception.SaaSException;
import com.muyu.common.core.constant.SecurityConstants;
import com.muyu.common.core.domain.Result;
import com.muyu.common.core.utils.SpringUtils;
import com.muyu.common.system.domain.SysFirmDatasource;
import com.muyu.common.system.remote.RemoteUserService;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.*;

/**
 * @Author: DongZeLiang
 * @date: 2024/6/3
 * @Description: 多数据源
 * @Version: 1.0
 */
@Log4j2
@Configuration
@AutoConfiguration(before = MybatisPlusAutoConfiguration.class)
public class ManyDataSource implements ApplicationRunner {


    private List<EntInfo> dataSourceInfoList(){
        RemoteUserService RemoteUserService = SpringUtils.getBean(RemoteUserService.class);
        Result<List<SysFirmDatasource>> listResult = RemoteUserService.selectFirmDatabaseList(SecurityConstants.INNER);
        if (listResult==null){
            throw new SaaSException("saas远调数据源错误");
        }
        List<SysFirmDatasource> data = listResult.getData();
        if (listResult.getCode() ==Result.SUCCESS && data !=null){
            List<EntInfo> list = new ArrayList<>();
            for (SysFirmDatasource row : data) {
                list.add(
                        EntInfo.builder()
                                .entCode(row.getDatabaseName())
                                .ip(row.getIp())
                                .port(row.getPort())
                                .userName(row.getUsername())
                                .password(row.getPassword())
                                .build()
                );
            }
            return list;
        }else {
            log.error("远调数据源错误,远调数据为：{}", JSON.toJSONString(data));
            throw new RuntimeException("远调数据源错误,远调--》 firmList ");
        }
    }

    @Bean
    public DynamicDataSource dynamicDataSource() {
        // 企业列表 企业CODE，端口，IP
        Map<Object, Object> dataSourceMap = new HashMap<>();
        dataSourceInfoList()
                .stream()
                .map(entInfo -> DataSourceInfo.hostAndPortBuild(
                        entInfo.getEntCode(),
                        entInfo.getIp(),
                        entInfo.getPort(),
                        entInfo.getUserName(),
                        entInfo.getPassword()))
                .map(DruidDataSourceFactory::create)
                .filter(Objects::nonNull)
                .forEach(druidDataSource -> {
                    dataSourceMap.put(druidDataSource.getName(), druidDataSource);
                });
        //设置动态数据源
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
//        dynamicDataSource.setDefaultTargetDataSource(masterDataSource());
        dynamicDataSource.setTargetDataSources(dataSourceMap);
        //将数据源信息备份在defineTargetDataSources中
        dynamicDataSource.setDefineTargetDataSources(dataSourceMap);
        return dynamicDataSource;
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        DynamicDataSource dynamicDataSource = SpringUtils.getBean(DynamicDataSource.class);
        dataSourceInfoList()
                .stream()
                .map(entInfo -> DataSourceInfo.hostAndPortBuild(
                        entInfo.getEntCode(),
                        entInfo.getIp(),
                        entInfo.getPort(),
                        entInfo.getUserName(),
                        entInfo.getPassword()))
                .map(DruidDataSourceFactory::create)
                .filter(Objects::nonNull)
                .forEach(druidDataSource -> {
                    dynamicDataSource.put(druidDataSource.getName(), druidDataSource);
                });
    }
}
