package cn.datax.service.data.quality.schedule.task;

import cn.datax.common.database.DataSourceFactory;
import cn.datax.common.database.DbQuery;
import cn.datax.common.database.constants.DbQueryProperty;
import cn.datax.common.exception.DataException;
import cn.datax.service.data.metadata.api.dto.DbSchema;
import cn.datax.service.data.metadata.api.entity.MetadataSourceEntity;
import cn.datax.service.data.metadata.api.feign.MetadataSourceServiceFeign;
import cn.datax.service.data.quality.api.entity.CheckReportEntity;
import cn.datax.service.data.quality.api.entity.CheckRuleEntity;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

public class TaskHander implements Runnable {

    private MetadataSourceServiceFeign metadataSourceServiceFeign;

    private DataSourceFactory dataSourceFactory;

    private CheckRuleEntity checkRuleEntity;

    private List<CheckReportEntity> list;

    public TaskHander(MetadataSourceServiceFeign metadataSourceServiceFeign, DataSourceFactory dataSourceFactory, CheckRuleEntity checkRuleEntity, List<CheckReportEntity> list) {
        super();
        this.metadataSourceServiceFeign = metadataSourceServiceFeign;
        this.dataSourceFactory = dataSourceFactory;
        this.checkRuleEntity = checkRuleEntity;
        this.list = list;
    }

    @Override
    public void run() {
        CheckReportEntity checkReportEntity = new CheckReportEntity();
        checkReportEntity.setCheckRuleId(checkRuleEntity.getId());
        checkReportEntity.setCheckDate(LocalDateTime.now());
        MetadataSourceEntity dataSource = null;
        Optional<MetadataSourceEntity> dataSourceOptional = Optional.ofNullable(metadataSourceServiceFeign.getMetadataSourceById(checkRuleEntity.getRuleSourceId()));
        if (dataSourceOptional.isPresent()) {
            dataSource = dataSourceOptional.get();
        } else {
            checkReportEntity.setCheckResult("获取数据源接口出错");
            list.add(checkReportEntity);
            dataSourceOptional.orElseThrow(DataException::new);
        }
        DbSchema dbSchema = dataSource.getDbSchema();
        DbQueryProperty dbQueryProperty = new DbQueryProperty(dataSource.getDbType(), dbSchema.getHost(),
                dbSchema.getUsername(), dbSchema.getPassword(), dbSchema.getPort(), dbSchema.getDbName(), dbSchema.getSid());
        DbQuery dbQuery = null;
        Optional<DbQuery> dbQueryOptional = Optional.ofNullable(dataSourceFactory.createDbQuery(dbQueryProperty));
        if (dbQueryOptional.isPresent()) {
            dbQuery = dbQueryOptional.get();
        } else {
            checkReportEntity.setCheckResult("创建数据查询接口出错");
            list.add(checkReportEntity);
            dbQueryOptional.orElseThrow(DataException::new);
        }
        Connection conn = dbQuery.getConnection();
        Statement stmt = null;
        ResultSet rs = null;
        try {
            stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
            rs = stmt.executeQuery(checkRuleEntity.getRuleSql());
            while (rs.next()) {
            }
            list.add(checkReportEntity);
        } catch (Exception e) {
            checkReportEntity.setCheckResult(e.getMessage());
            list.add(checkReportEntity);
            throw new DataException(e);
        } finally {
            try {
                if(rs != null){
                    rs.close();
                }
                if (stmt != null) {
                    stmt.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                checkReportEntity.setCheckResult("释放数据库连接出错");
                list.add(checkReportEntity);
                throw new DataException("释放数据库连接出错");
            }
        }
    }
}
