package com.app.framework.core.utils.db;

import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils;

import java.sql.*;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 数据库工具类
 */
public class DBUtil {

    private SqlSession session;
    private Connection conn = null;
    private PreparedStatement ps = null;
    private ResultSet rs = null;

    private String driver = "com.mysql.jdbc.Driver";
    private String url;
    private String username;
    private String password;

    public DBUtil(SqlSessionFactory sqlSessionFactory) {
        session = SqlSessionUtils.getSqlSession(sqlSessionFactory);
    }

    public DBUtil(String url, String username, String password) {
        this.url = url;
        this.username = username;
        this.password = password;
    }

    public DBUtil(String driver, String url, String username, String password) {
        this.driver = driver;
        this.url = url;
        this.username = username;
        this.password = password;
    }

    public SqlSession getSqlSession() {
        return this.session;
    }

    public Connection getConnection() throws Exception {
        if (conn == null || conn.isClosed()) {
            if (this.session != null) {
                conn = this.session.getConnection();
            } else if (StringUtils.isNotBlank(url) && StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)) {
                Class.forName(driver);
                conn = DriverManager.getConnection(url, username, password);
            }
        }
        return conn;
    }

    /**
     * 根据SQL更新
     *
     * @param sql    SQL语句
     * @param params 参数数组
     * @return 更新行数
     */
    public int executeUpdate(String sql, Object[] params) {
        int rows = 0;
        try {
            conn = this.getConnection();
            ps = conn.prepareStatement(sql);
            if (params != null && params.length > 0) {
                for (int i = 0; i < params.length; i++) {
                    ps.setObject(i + 1, params[i]);
                }
            }
            rows = ps.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            this.close();
        }
        return rows;
    }

    /**
     * 根据SQL查询
     *
     * @param sql SQL语句
     * @return List<Map < 字段名, 值>>
     */
    public List<Map<String, String>> executeQuery(String sql) {
        return this.executeQuery(sql, null);
    }

    /**
     * 根据SQL查询
     *
     * @param sql SQL语句
	 * @param params 参数数组
     * @return List<Map < 字段名, 值>>
     */
    public List<Map<String, String>> executeQuery(String sql, Object[] params) {
        List<Map<String, String>> list = new ArrayList<>();
        try {
            conn = this.getConnection();
            ps = conn.prepareStatement(sql);
            if (params != null && params.length > 0) {
                for (int i = 0; i < params.length; i++) {
                    ps.setObject(i + 1, params[i]);
                }
            }
            rs = ps.executeQuery();
            ResultSetMetaData rsmd = rs.getMetaData();
            int columnCount = rsmd.getColumnCount();
            while (rs.next()) {
                Map<String, String> map = new LinkedHashMap<>();
                for (int i = 0; i < columnCount; i++) {
                    int index = i + 1;
                    map.put(rsmd.getColumnName(index).toLowerCase(), rs.getString(index));
                }
                list.add(map);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            this.close();
        }
        return list;
    }

    public void close() {
        try {
            if (rs != null) rs.close();
            if (ps != null) ps.close();
            if (conn != null) conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
