package com.zm.order.tool.server.config;


import com.zm.order.tool.server.model.OrderSession;
import com.zm.order.tool.server.model.TraceIdentity;
import com.zm.order.tool.server.utils.IoUtils;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.shardingsphere.shardingjdbc.api.yaml.YamlShardingDataSourceFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.io.InputStream;
import java.util.Objects;
import java.util.UUID;

/**
 * @Description 数据源配置
 * @Author: ph
 * @Date: 2019/10/30 16:15
 */
@Configuration
@MapperScan(basePackages = {"com.zm.order.tool.server.dao"},
        sqlSessionTemplateRef = "sqlSessionTemplate")
public class DataSourceConfig {

    private static final Logger logger = LoggerFactory.getLogger(DataSourceConfig.class);

    @Bean(name = "defaultDataSource")
    @Primary
    public DataSource defaultDataSource() throws Exception {
        InputStream inputStream = new ClassPathResource("sharding.yml").getInputStream();
        DataSource dataSource = YamlShardingDataSourceFactory.createDataSource(IoUtils.toBytes(inputStream));
        logger.info("init default data source success");
        return dataSource;
    }

    @Bean("sqlSessionFactory")
    public SqlSessionFactory itemSqlSessionFactory(
            @Value("${mybatis.mapper-locations}") String mapperLocations,
            @Value("${mybatis.config-location}") String configLocation
    ) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(defaultDataSource());
        Resource[] mapperLocationsResource = new PathMatchingResourcePatternResolver().getResources(mapperLocations);
        sqlSessionFactoryBean.setMapperLocations(mapperLocationsResource);
        sqlSessionFactoryBean.setConfigLocation(
                new PathMatchingResourcePatternResolver().getResource(configLocation)
        );
        return sqlSessionFactoryBean.getObject();
    }

    @Bean("sqlSessionTemplate")
    public SqlSessionTemplate itemSqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory);
        return sqlSessionTemplate;
    }

    @Bean
    public PlatformTransactionManager itemTransactionManager(@Qualifier("defaultDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    /**
     * @Description 线程上下文 先搞一个字段试试 需要加字段就用对象
     * @Author: ph
     * @Date: 2019/11/11 20:10
     */
    public static class ThreadContext {

        private static ThreadLocal<OrderSession> context = new ThreadLocal<>();

        public static void setContext(OrderSession session) {
            context.set(session);
        }

        public static OrderSession getContext() {
            return context.get();
        }

        public static void removeContext() {
            context.remove();
        }

        public static void setDbSize(int dbSize) {
            OrderSession orderSession = context.get();
            if (Objects.isNull(orderSession)) {
                orderSession = new OrderSession();
            }
            orderSession.setDbSize(dbSize);
            context.set(orderSession);
        }

        public static void setBizType(Integer bizType) {
            OrderSession orderSession = context.get();
            if (Objects.isNull(orderSession)) {
                orderSession = new OrderSession();
            }
            orderSession.setBizType(bizType);
            context.set(orderSession);
        }

        public static Integer getBizType() {
            if (Objects.nonNull(context.get())) {
                return context.get().getBizType();
            }
            return null;
        }


        public static Integer getDbSize() {
            if (Objects.nonNull(context.get())) {
                return context.get().getDbSize();
            }
            return null;
        }

        public static void setRole(Integer role) {
            OrderSession orderSession = context.get();
            if (Objects.isNull(orderSession)) {
                orderSession = new OrderSession();
            }
            orderSession.setRole(role);
            context.set(orderSession);
        }

        public static Integer getRole() {
            if (Objects.nonNull(context.get())) {
                return context.get().getRole();
            }
            return null;
        }

        public static void setTraceIdentity(TraceIdentity traceIdentity) {
            OrderSession orderSession = context.get();
            if (Objects.isNull(orderSession)) {
                orderSession = new OrderSession();
            }
            orderSession.setTraceIdentity(traceIdentity);
            context.set(orderSession);
        }

        public static TraceIdentity getTraceIdentity() {
            if (Objects.isNull(context.get()) || Objects.isNull(context.get().getTraceIdentity())) {
                TraceIdentity traceIdentity = new TraceIdentity();
                traceIdentity.setTraceId("OC" + UUID.randomUUID().toString().replace("-", ""));
                traceIdentity.setTraceSpanId("0");
                return traceIdentity;
            }
            return context.get().getTraceIdentity();
        }
    }
}
