package cn.datax.service.data.metadata.service.impl;

import cn.datax.common.core.DataConstant;
import cn.datax.common.database.DataSourceFactory;
import cn.datax.common.database.DbQuery;
import cn.datax.common.database.constants.DbQueryProperty;
import cn.datax.common.database.core.DbColumn;
import cn.datax.common.database.core.DbTable;
import cn.datax.common.exception.DataException;
import cn.datax.service.data.factory.api.dto.DbSchema;
import cn.datax.service.data.factory.api.entity.DataSourceEntity;
import cn.datax.service.data.factory.api.feign.DataSourceServiceFeign;
import cn.datax.service.data.metadata.api.entity.DataMetadataColumnEntity;
import cn.datax.service.data.metadata.api.entity.DataMetadataTableEntity;
import cn.datax.service.data.metadata.dao.DataMetadataColumnDao;
import cn.datax.service.data.metadata.dao.DataMetadataTableDao;
import cn.datax.service.data.metadata.service.DataMetadataService;
import cn.hutool.core.collection.CollUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class DataMetadataServiceImpl implements DataMetadataService {

    @Autowired
    private DataSourceFactory dataSourceFactory;

    @Autowired
    private DataSourceServiceFeign dataSourceServiceFeign;

    @Autowired
    private DataMetadataTableDao dataMetadataTableDao;

    @Autowired
    private DataMetadataColumnDao dataMetadataColumnDao;

    @Override
    public void syncMetadata(String id) {
        DataSourceEntity dataSourceEntity = dataSourceServiceFeign.getDataSourceById(id);
        if (dataSourceServiceFeign == null) {
            throw new DataException("未找到数据源");
        }
        if (Integer.valueOf(DataConstant.TrueOrFalse.TRUE.getKey()).equals(dataSourceEntity.getSourceSync())) {
            throw new DataException("元数据已同步");
        }
        // 异步执行同步任务
        syncTask(dataSourceEntity);
    }

    @Async
    public void syncTask(DataSourceEntity dataSource) {
        long start = System.currentTimeMillis();
        DbSchema dbSchema = dataSource.getDbSchema();
        DbQueryProperty dbQueryProperty = new DbQueryProperty(dataSource.getDbType(), dbSchema.getHost(),
                dbSchema.getUsername(), dbSchema.getPassword(), dbSchema.getPort(), dbSchema.getDbName(), dbSchema.getSid());
        DbQuery dbQuery = dataSourceFactory.createDbQuery(dbQueryProperty);
        List<DbTable> tables = dbQuery.getTables(dbSchema.getDbName());
        if (CollUtil.isNotEmpty(tables)) {
            List<DataMetadataTableEntity> metadataTableEntityList = tables.stream().map(table -> {
                DataMetadataTableEntity metadataTable = new DataMetadataTableEntity();
                metadataTable.setSourceId(dataSource.getId());
                metadataTable.setTableName(table.getTableName());
                return metadataTable;
            }).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(metadataTableEntityList)) {
                metadataTableEntityList.stream().forEach(table -> {
                    dataMetadataTableDao.insert(table);
                    List<DbColumn> columns = dbQuery.getTableColumns(dbSchema.getDbName(), table.getTableName());
                    if (CollUtil.isNotEmpty(columns)) {
                        List<DataMetadataColumnEntity> metadataColumnEntityList = columns.stream().map(column -> {
                            DataMetadataColumnEntity metadataColumn = new DataMetadataColumnEntity();
                            metadataColumn.setSourceId(dataSource.getId());
                            metadataColumn.setTableId(table.getId());
                            metadataColumn.setColumnName(column.getColName());
                            metadataColumn.setColumnComment(column.getColComment());
                            metadataColumn.setColumnKey(column.getColKey() ? "1" : "0");
                            metadataColumn.setColumnNullable(column.getNullable() ? "1" : "0");
                            metadataColumn.setColumnPosition(column.getColPosition().toString());
                            metadataColumn.setDataType(column.getDataType());
                            metadataColumn.setDataLength(column.getDataLength().toString());
                            metadataColumn.setDataPrecision(column.getDataPrecision().toString());
                            metadataColumn.setDataScale(column.getDataScale().toString());
                            metadataColumn.setDataDefault(column.getDataDefault());
                            return metadataColumn;
                        }).collect(Collectors.toList());
                        if (CollUtil.isNotEmpty(metadataColumnEntityList)) {
                            metadataColumnEntityList.stream().forEach(column -> dataMetadataColumnDao.insert(column));
                        }
                    }
                });
            }
        }
        log.info("异步任务执行完成！耗时{}秒", (System.currentTimeMillis() - start  / 1000));
    }
}
