package com.usoftchina.bi.server.service.dataSource;

import com.usoftchina.bi.core.base.BaseContextHolder;
import com.usoftchina.bi.core.exception.MyException;
import com.usoftchina.bi.core.utils.ContextUtil;
import com.usoftchina.bi.core.utils.GetTokenDataUtil;
import com.usoftchina.bi.server.dao.dataSource.DataConnectorMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.github.pagehelper.PageInfo;
import com.usoftchina.bi.server.model.po.ColumnToShow;
import com.usoftchina.bi.server.model.po.DataConnector;
import com.usoftchina.bi.server.model.po.Databases;
import com.usoftchina.bi.core.base.RepCode;
import com.usoftchina.bi.core.base.RepEntity;
import com.usoftchina.bi.core.base.TestPage;
import com.usoftchina.bi.server.model.vo.configVo.ColumnRenameInfo;
import com.usoftchina.bi.server.model.vo.configVo.DatabasesInfo;
import com.usoftchina.bi.server.service.chart.GetChartsDataUtilService;
import com.usoftchina.bi.core.jdbc.DynamicDataSource;
import com.usoftchina.bi.core.jdbc.DynamicDataSourceContextHolder;
import com.usoftchina.bi.core.jdbc.DynamicDataSourceRegister;
import com.usoftchina.bi.server.service.common.MessageLogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.*;

@Service
public class DataBasesService {
    @Autowired
    DataConnectorMapper dataConnectorMapper;
    @Autowired
    ObjectMapper objectMapper;
    @Autowired
    private DynamicDataSourceRegister dataSourceRegister;
    @Autowired
    GetChartsDataUtilService getChartsDataUtilService;
    @Autowired
    private ImplementSqlService implementSqlService;
    @Autowired
    private MessageLogService messageLogService;

    private static final Logger LOGGER = LoggerFactory.getLogger(DataBasesService.class);
    /*
   保存数据库链接
    */
    public RepEntity inputDatabases(DatabasesInfo databasesInfo){
        if (databasesInfo == null || "".equals(databasesInfo)){
            return new RepEntity(RepCode.Null);
        }
        Databases databases = new Databases();
        BeanUtils.copyProperties(databasesInfo, databases);
        //校验此数据链接是否已存在
        validExists(databases);
        //校验此链接是否可用
        implementSqlService.connectTest(databases);

        String note = databases.getNote();
        if (note == null || "".equals(note)){
            note = "";
            databases.setNote(note);
        }
        dataConnectorMapper.inputDataBases(databases);
        int id = databases.getId();
        databasesInfo.setId(id);
        //添加数据源可切换
        addDataSource(databasesInfo);

        return new RepEntity(RepCode.success,id);
    }

    /**
     * 校验此数据链接是否已存在
     * @param databases
     */
    private void validExists(Databases databases){
        int count = dataConnectorMapper.countDataBasesName(databases.getName());
        if (count > 0) {
            throw new MyException("已存在连接名为 " + databases.getName() + " 的数据连接");
        }
        count = dataConnectorMapper.countDataBases(databases);
        if (count > 0) {
            throw new MyException("已存在用户名为 " + databases.getUserName() + " 的数据连接!");
        }
    }

    /*
   查看数据库配置列表
    */
    public RepEntity getListDatabases(TestPage testPage){
        List<Databases> databasesList = dataConnectorMapper.getDatabasesList(testPage.enablePaging());
        List<Databases> databases = new ArrayList<>();
        Iterator isList = databasesList.iterator();
        while (isList.hasNext()){
            Databases databases1 = (Databases) isList.next();
            databases1.setPassWord("");
            databases.add(databases1);
        }
        PageInfo<Databases> pageInfo = new PageInfo<>(databases);
        return new RepEntity(RepCode.success, pageInfo);
    }

    /*
    删除数据库配置
     */
    public RepEntity delDatabases(Long id){
        String username = BaseContextHolder.getUserName();
        int count = dataConnectorMapper.countDataConnectorById(id);
        if (count > 0) {
            throw new MyException(RepCode.DATACONNECTOR_USED_DATASOURCE);
        }
        String databaseName = dataConnectorMapper.getDatabases(id.intValue()).getName();
        dataConnectorMapper.deleteDatabases(id);
        messageLogService.delete("数据链接", databaseName, username, null);
        return new RepEntity(RepCode.success);
    }

    /*
    修改数据库配置
     */
    public RepEntity updatabases(DatabasesInfo databasesInfo){
        Databases databases = new Databases();
        BeanUtils.copyProperties(databasesInfo, databases);
        if (databases.getPassWord() == null || "".equals(databases.getPassWord())){
            databases.setPassWord(null);
        }
        //校验此链接是否可用
        implementSqlService.connectTest(databases);
        //更新
        dataConnectorMapper.updatabases(databases);
        DatabasesInfo databasesInfo1 = dataConnectorMapper.getDatabases(databasesInfo.getId());
        addDataSource(databasesInfo1);
        return new RepEntity(RepCode.success);
    }

    /*
    查询列数据
     */
    public RepEntity getColumnData(int id){
        DataConnector dataConnector = new DataConnector();
        dataConnector = dataConnectorMapper.getColumnData(id);
        if (dataConnector == null || "".equals(dataConnector)){
            return new RepEntity(RepCode.Null);
        }
        String columnData = dataConnector.getColumnConfig();

        List<ColumnRenameInfo> configList = new ArrayList<>();
        if (!StringUtils.isEmpty(columnData)){
            try {
                CollectionType javaType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, ColumnRenameInfo.class);
                configList =  objectMapper.readValue(columnData, javaType);   //这里不需要强制转换
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        List<ColumnToShow> toShows = new ArrayList<>();


        for (int i = 0; i < configList.size(); i++ ){
            ColumnRenameInfo columnRenameInfo = new ColumnRenameInfo();
            ColumnToShow columnToShow = new ColumnToShow();
            columnRenameInfo = configList.get(i);
            if ("1".equals(columnRenameInfo.getIsOpen())) {
                columnToShow.setColumnName(columnRenameInfo.getColumnName());
                columnToShow.setColumnRaname(columnRenameInfo.getColumnLable());
                columnToShow.setColumnType(columnRenameInfo.getColumnType());
                columnToShow.setIsGroup(columnRenameInfo.getIsGroup());
                columnToShow.setIsSubsection(columnRenameInfo.getIsSubsection());
                columnToShow.setIsFilter(columnRenameInfo.getIsFilter());
                toShows.add(columnToShow);
            }
        }
        return new RepEntity(RepCode.success,toShows);
    }

    /*
    查询列数据通过图表ID
     */
    public RepEntity getColumnByChartId(int id){
        DataConnector dataConnector = new DataConnector();
        int ConnectId = getChartsDataUtilService.getConnectId(id);
        dataConnector = dataConnectorMapper.getColumnData(ConnectId);
        if (dataConnector == null || "".equals(dataConnector)){
            return new RepEntity(RepCode.Null);
        }
        String columnData = dataConnector.getColumnConfig();

        List<ColumnRenameInfo> configList = new ArrayList<>();
        if (columnData != null || (!"".equals(columnData))){
            try {
                CollectionType javaType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, ColumnRenameInfo.class);
                configList =  objectMapper.readValue(columnData, javaType);   //这里不需要强制转换
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        List<ColumnToShow> toShows = new ArrayList<>();


        for (int i = 0; i < configList.size(); i++ ){
            ColumnRenameInfo columnRenameInfo = new ColumnRenameInfo();
            ColumnToShow columnToShow = new ColumnToShow();
            columnRenameInfo = configList.get(i);
            if ("1".equals(columnRenameInfo.getIsOpen())) {
                columnToShow.setColumnName(columnRenameInfo.getColumnName());
                columnToShow.setColumnRaname(columnRenameInfo.getColumnLable());
                columnToShow.setColumnType(columnRenameInfo.getColumnType());
                columnToShow.setIsGroup(columnRenameInfo.getIsGroup());
                columnToShow.setIsSubsection(columnRenameInfo.getIsSubsection());
                toShows.add(columnToShow);
            }
        }
        return new RepEntity(RepCode.success,toShows);
    }

    //添加数据源
    public void addDataSource(DatabasesInfo databasesInfo) {
        //额外的数据源
        Map<String, Object> dsMap = new HashMap<>();
        dsMap.put("driver", "oracle.jdbc.driver.OracleDriver");
        dsMap.put("url", "jdbc:oracle:thin:@" + databasesInfo.getAddrass() +":" + databasesInfo.getPort() + ":" + databasesInfo.getDataName());
        dsMap.put("username", databasesInfo.getUserName());
        dsMap.put("password", databasesInfo.getPassWord());
        Map<Object, Object> target = dataSourceRegister.getTargetDataSources();
        if (target.size() == 0) {
            target.putAll(dataSourceRegister.getSlaveDataSources());
        }
        if (!target.containsKey(String.valueOf(databasesInfo.getId()))) {
            target.put(databasesInfo.getId(), dataSourceRegister.buildDataSource(dsMap));

            DynamicDataSource datasource = (DynamicDataSource) ContextUtil.getBean("dataSource");

            datasource.setTargetDataSources(target);
            datasource.afterPropertiesSet();

            Set<Object> dataSourceIds = DynamicDataSourceContextHolder.getDataSourceIds();

            dataSourceIds.add(databasesInfo.getId());

            DynamicDataSourceContextHolder.setDataSourceIds(dataSourceIds);
        }
    }

}
