package com.tofly.feesapi.common.dbhelper;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tofly.feesapi.common.mapper.CommonMapper;
import com.tofly.feesapi.common.model.CollectionData;
import com.tofly.feesapi.common.model.DataSourceInfo;
import com.tofly.feesapi.common.model.PageLink;
import com.tofly.feesapi.common.model.ProcParamModel;
import com.tofly.feesapi.common.util.SpringContextHolder;
import org.springframework.context.annotation.DependsOn;

import java.sql.*;
import java.text.MessageFormat;
import java.util.*;
import java.util.stream.Collectors;


@DependsOn("SpringContextHolder")
public class DbHelper {

    private static String URL = "";
    private static String USER = "";
    private static String PASSWORD = "";
    private static Connection connection = null;
    private static Statement statement = null;
    private static DbHelper helper = null;
    private final CommonMapper commonMapper = SpringContextHolder.getBean("commonMapper");

    static {
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    private DbHelper() throws Exception {
        DataSourceInfo sourceInfo = SpringContextHolder.getBean("dataSourceInfo");
        URL = sourceInfo.getUrl();
        USER = sourceInfo.getUsername();
        PASSWORD = sourceInfo.getPassword();

        connection = DriverManager.getConnection(URL, USER, PASSWORD);
        statement = connection.createStatement();
    }

    /**
     * 返回单例模式的数据库辅助对象
     */
    public static DbHelper getDbHelper() throws Exception {
        if (helper == null || connection == null || connection.isClosed())
            helper = new DbHelper();

        return helper;
    }

    /**
     * 执行SQL语句
     */
    public Boolean execute(String sql) throws Exception {
        if (statement != null) {
            return statement.execute(sql);
        }
        throw new Exception("数据库未正常连接");
    }

    /**
     * 执行查询
     */
    public ResultSet executeQuery(String sql) throws Exception {
        if (statement != null) {
            return statement.executeQuery(sql);
        }

        throw new Exception("数据库未正常连接");
    }

    /**
     * 执行查询
     *
     * @param sql  要执行的带参数的SQL语句
     * @param args SQL语句中的参数值
     * @return 查询的结果集对象
     * @throws Exception
     */
    public ResultSet executeQuery(String sql, Object... args) throws Exception {
        if (connection == null || connection.isClosed()) {
            DbHelper.close();
            throw new Exception("数据库未正常连接");
        }
        PreparedStatement ps = connection.prepareStatement(sql);
        int index = 1;
        for (Object arg : args) {
            ps.setObject(index, arg);
            index++;
        }

        return ps.executeQuery();
    }


    /**
     * 执行更新
     *
     * @param sql 要执行的SQL语句
     * @return 受影响的记录条数
     * @throws Exception
     */
    public int executeCmd(String sql) throws Exception {
        if (statement != null) {
            return statement.executeUpdate(sql);
        }
        throw new Exception("数据库未正常连接");
    }

    /**
     * 执行更新
     *
     * @param sql  要执行的SQL语句
     * @param args SQL语句中的参数
     * @return 受影响的记录条数
     * @throws Exception
     */
    public int executeCmd(String sql, Object... args) throws Exception {
        if (connection == null || connection.isClosed()) {
            DbHelper.close();
            throw new Exception("数据库未正常连接");
        }
        PreparedStatement ps = connection.prepareStatement(sql);
        int index = 1;
        for (Object arg : args) {
            ps.setObject(index, arg);
            index++;
        }
        return ps.executeUpdate();
    }

    /**
     * 获取预编译的语句对象
     *
     * @param sql 预编译的语句
     * @return 预编译的语句对象
     * @throws Exception
     */
    public PreparedStatement prepareStatement(String sql) throws Exception {
        return connection.prepareStatement(sql);
    }

    /**
     * 关闭对象，同时将关闭连接
     */
    public static void close() {
        try {
            if (statement != null)
                statement.close();
            if (connection != null)
                connection.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            helper = null;
        }
    }

    List<String> lstSql = new ArrayList<>();

    /**
     * 执行事务
     */
    public boolean executeTransaction() {
        boolean isSuccess = false;
        try {
            connection.setAutoCommit(false);
            Statement stmt = connection.createStatement();
            if (lstSql != null && lstSql.size() > 0) {
                Iterator iter = lstSql.iterator();
                while (iter.hasNext()) {
                    String strSql = (String) iter.next();
                    stmt.executeUpdate(strSql);
                }
            }
            connection.commit();
            isSuccess = true;
        } catch (SQLException e) {
            isSuccess = false;
            // 回滚事务
            try {
                if (connection != null) {
                    connection.rollback();
                }
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            // 关闭连接
            try {
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return isSuccess;
    }

    public void addTransactionSql(String strSql) {
        if (lstSql != null)
            lstSql.add(strSql);
    }

    public void clearTransactionSql() {
        if (lstSql != null)
            lstSql.clear();
    }

    /**
     * @MethodName getPage
     * @Description 分页查询
     * @Author xb
     * @Date 14:20 2023-07-05
     */
    public Object getPage(PageLink pageLink, String sql, String framework) {

        try {
            if (framework.toLowerCase() == "mybatis") {
                Page<Map<String, Object>> page = new Page<>(pageLink.getPage(), pageLink.getPageSize());
                /*
                 *page
                 * */
                Page<Map<String, Object>> newPage = commonMapper.queryForPage(page, sql);

//                return new CollectionData(newPage.getRecords().stream().map(e -> {
//                    Map<String, Object> newMap = new LinkedHashMap<>();
//                    e.forEach((k, v) -> newMap.put(k.toLowerCase(), v));
//                    return newMap;
//                }).collect(Collectors.toList()), newPage.getTotal());

                return new CollectionData(newPage.getRecords().stream().collect(Collectors.toList()), newPage.getTotal());
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        try {

            if (framework.toLowerCase() == "sql") {

            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return null;
    }

    /**
     * @MethodName getList
     * @Description easy版获取列表不分页
     * @Author xb
     * @Date 14:19 2023-07-05
     */
    public Object getList(String sql, String framework) {

        try {
            if (framework.toLowerCase() == "mybatis") {
                List<HashMap<String, Object>> newPage = commonMapper.query(sql);
                return new CollectionData(newPage, newPage.size());
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        try {

            if (framework.toLowerCase() == "sql") {

            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return null;
    }

    /**
     * @MethodName procurdeCmd
     * @Description 执行存储过程
     * @Author xb
     * @Date 14:19 2023-07-05
     */
    public Map procurdeCmd(String procurdeName, Map<String, Object> objectHashMap, String framework) {
        try {
            if (framework.toLowerCase() == "mybatis") {

//                StringBuilder sb=new StringBuilder();
//                sb.append(String.format("{call %s(",procurdeName));
//
//                if(!objectHashMap.isEmpty()){
//                    for (Map.Entry<String, Object> entry : objectHashMap.entrySet()) {
//                        sb.append(String.format("",procurdeName));
//                    }
//                }
//                sb.append(")}");

                if (!procurdeName.contains("map.")) {
                    procurdeName = procurdeName.replace("#{", "#{map.");
                }
                if (procurdeName.contains("CURSOR")
                        && !procurdeName.contains("resultMap")) {
                    procurdeName = procurdeName.replace("CURSOR", "CURSOR,resultMap=mapCus");
                }
                commonMapper.procedureCmd(procurdeName, objectHashMap);
                return objectHashMap;
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        try {

            if (framework.toLowerCase() == "sql") {

            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return null;
    }


    /**
     * 执行存储过程
     *
     * @param procedureName 存储过程名称
     * @param list          参数对象
     * @return Map对象
     */
    public Map executeProcedure(String procedureName, List<ProcParamModel> list) {
        try {
            Map<String, Object> objectHashMap = new HashMap<>();
            StringBuilder sbProc = new StringBuilder();
            sbProc.append(String.format("{call %s", procedureName));
            //判断是否有参数，有则进行赋值处理
            if (list != null && list.size() > 0) {
                sbProc.append("(");
                String strJdbcType = "";
                for (ProcParamModel paramModel : list) {
                    //判断是否为游标类型
                    if (paramModel.getJdbcType().equals(JDBCType.REF_CURSOR)) {
                        strJdbcType = "CURSOR,resultMap=mapCus";
                        objectHashMap.put(paramModel.getName(), new ArrayList<>());
                    } else {
                        strJdbcType = paramModel.getJdbcType().toString();
                        objectHashMap.put(paramModel.getName(), paramModel.getValue());
                    }
                    sbProc.append(MessageFormat.format("{0}map.{1},mode={2},jdbcType={3}},"
                            , "#{", paramModel.getName(), paramModel.getMode(), strJdbcType));
                }
                //去掉最后的逗号
                sbProc.delete(sbProc.length() - 1, sbProc.length());
                sbProc.append(")");
            }
            sbProc.append("}");
            commonMapper.procedureCmd(sbProc.toString(), objectHashMap);
            return objectHashMap;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取单个查询的值
     *
     * @param sql 查询语句
     * @return 返回第一条记录的第一列的第一个字段值，不存在或异常时返回空字符或null
     */
    public String getValue(String sql) {
        String strResult = "";
        try {
            List<HashMap<String, Object>> newPage = commonMapper.query(sql);
            //判断是不是Clob类型
            if (newPage.get(0).entrySet().iterator().next().getValue() instanceof Clob) {
                Clob clob = (Clob) newPage.get(0).entrySet().iterator().next().getValue();

                strResult = clob.getSubString(1, (int) clob.length());

            } else {
                strResult = newPage.get(0).entrySet().iterator().next().getValue().toString();
            }
        } catch (Exception e) {
            strResult = null;
        }
        return strResult;
    }

    /**
     * 获取List的HashMap集
     *
     * @param sql 查询语句
     * @return
     */
    public List<HashMap<String, Object>> getList(String sql) {
        try {
            List<HashMap<String, Object>> hashMapList = commonMapper.query(sql);
            return hashMapList;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}