package com.product.data.sync.util;

import cn.hutool.core.util.IdUtil;
import com.product.common.utils.spring.SpringUtils;
import com.product.core.entity.FieldSetEntity;
import com.product.core.exception.BaseException;
import com.product.core.spring.context.SpringMVCContextHolder;
import com.product.data.sync.config.SystemCode;
import com.product.util.BaseUtil;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.*;
import java.util.Date;

public class DataManipulationUtils {

    /**
     * 鑾峰彇jdbc杩炴帴
     *
     * @param diver jdbc杩炴帴绫诲瀷
     * @param jdbc  杩炴帴url
     * @param user  鐢ㄦ埛鍚�
     * @param pwd   瀵嗙爜
     * @return JDBC杩炴帴
     * @throws BaseException
     */
    public static Connection getConnection(String diver, String jdbc, String user, String pwd) throws ClassNotFoundException, SQLException {
        Class.forName(diver);
        Connection connection = DriverManager.getConnection(jdbc, user, pwd);
        return connection;
    }

    /**
     * 鍏抽棴鏁版嵁搴撶殑杩炴帴
     *
     * @param rs   缁撴灉闆�
     * @param stmt 鎵цsql鐨勭被
     * @param con  JDBC杩炴帴
     * @throws SQLException
     */
    public static void close(ResultSet rs, Statement stmt, Connection con) throws SQLException {
        if (rs != null)
            rs.close();
        if (stmt != null)
            stmt.close();
        if (con != null && !con.isClosed())
            con.close();
    }

    /**
     * 鏌ヨ鏁版嵁鎬绘潯鏁�
     * 涓昏閫氳繃map閲岄潰琛ㄥ悕鍜屾潯浠舵煡璇㈡潯鏁�
     *
     * @param com 杩炴帴
     * @param map 鍙傛暟map
     * @return 鏁版嵁鎬绘潯鏁�
     * @throws SQLException
     */
    public static Integer getResultSetRow(Connection com, Map<String, String> map) throws SQLException {
        StringBuffer sql = new StringBuffer();
        //婧愭暟鎹〃鍚�
        String dataOriginName = map.get("dataOriginName");
        //鏌ヨ鏉′欢
        String syncCondition = map.get("syncCondition");
        sql.append(" SELECT count(*) FROM ").append(dataOriginName);
        if (!BaseUtil.strIsNull(syncCondition)) {
            sql.append(" WHERE ").append(syncCondition);//鍙傛暟澶辫触  鏀逛负瀛楃涓叉嫾鎺�
        }
        PreparedStatement ps = com.prepareStatement(sql.toString());
        ResultSet rs = ps.executeQuery();
        while (rs.next()) {
            return rs.getInt(1);
        }
        return 0;
    }

    /**
     * 鏌ヨ鏁版嵁
     *
     * @param com JDBC杩炴帴
     * @param map 鏌ヨ蹇呭鐨凪ap
     * @return
     * @throws SQLException
     */
    public static ResultSet getResultSet(Connection com, Map<String, String> map) throws SQLException {
        String type = map.get("databaseType");
        if ("mysql".equals(type)) {
            return DataManipulationUtils.getMysqlResultSet(com, map);
        } else if ("oracle".equals(type)) {
            return DataManipulationUtils.getOracleResultSet(com, map);
        } else if ("sqlserver".equals(type)) {
            return DataManipulationUtils.getSqlServerResultSet(com, map);
        } else if ("informix".equals(type)) {
            return DataManipulationUtils.getInforMixResultSet(com, map);
        } else {
            throw new SQLException(SystemCode.SYSTEM_UNKNOWN_DATABASE_TYPE.getValue(), SystemCode.SYSTEM_UNKNOWN_DATABASE_TYPE.getText());
        }
    }

    public static void main(String[] args) {
        long l = System.currentTimeMillis();
        Set<String> uuids = new HashSet<>();
        int data = 1;
        for (int i = 0; i < 10000; i++) {
            String s = IdUtil.randomUUID();
            uuids.add(s);
            data++;
            if (data % 1000 == 0) {
                System.out.println(System.currentTimeMillis() - l);
                l = System.currentTimeMillis();
            }
        }
        System.out.println(uuids.size());
    }

    /**
     * MySql鏌ヨ鏁版嵁
     *
     * @param con 杩炴帴
     * @param map 琛ㄥ悕闆嗗弬鏁�
     * @return 鏁版嵁闆�
     * @throws SQLException
     */
    public static ResultSet getMysqlResultSet(Connection con, Map<String, String> map) throws SQLException {
        String sql = map.get("sql");
        Integer currentPage = Integer.parseInt(map.get("currentPage"));
        Integer pageSize = Integer.parseInt(map.get("pageSize"));
        Integer start = (currentPage - 1) * pageSize;
        sql = sql.replaceFirst("[?]", map.get("fileName"));
        sql = sql.replaceFirst("[?]", map.get("dataOriginName"));
        sql = sql.replaceFirst("[?]", String.valueOf(start));
        sql = sql.replaceFirst("[?]", String.valueOf(pageSize));
        SpringMVCContextHolder.getSystemLogger().info(sql);
        PreparedStatement ps = con.prepareStatement(sql);
        ResultSet resultSet = ps.executeQuery();
        return resultSet;
    }

    /**
     * SqlServer鏌ヨ鏁版嵁
     *
     * @param con 杩炴帴
     * @param map 琛ㄥ悕闆嗗弬鏁�
     * @return 鏁版嵁闆�
     * @throws SQLException
     */
    public static ResultSet getSqlServerResultSet(Connection con, Map<String, String> map) throws SQLException {
        String sql = map.get("sql");
        Integer currentPage = Integer.parseInt(map.get("currentPage"));
        Integer pageSize = Integer.parseInt(map.get("pageSize"));
        Integer start = (currentPage - 1) * pageSize;
        sql = sql.replaceFirst("[?]", String.valueOf(pageSize));
        sql = sql.replaceFirst("[?]", map.get("fileName"));
        sql = sql.replaceFirst("[?]", map.get("dataOriginName"));

        sql = sql.replaceFirst("[?]", String.valueOf(start));
        sql = sql.replaceFirst("[?]", map.get("dataOriginName"));
        SpringMVCContextHolder.getSystemLogger().info(sql);
        PreparedStatement ps = con.prepareStatement(sql);
        return ps.executeQuery();
    }

    /**
     * InforMix鏌ヨ鏁版嵁
     *
     * @param con 杩炴帴
     * @param map 琛ㄥ悕闆嗗弬鏁�
     * @return 鏁版嵁闆�
     * @throws SQLException
     */
    public static ResultSet getInforMixResultSet(Connection con, Map<String, String> map) throws SQLException {
        String sql = map.get("sql");
        Integer currentPage = Integer.parseInt(map.get("currentPage"));
        Integer pageSize = Integer.parseInt(map.get("pageSize"));
        Integer start = (currentPage - 1) * pageSize;
        sql = sql.replaceFirst("[?]", String.valueOf(start));
        sql = sql.replaceFirst("[?]", String.valueOf(pageSize));
        sql = sql.replaceFirst("[?]", map.get("fileName"));
        sql = sql.replaceFirst("[?]", map.get("dataOriginName"));
        SpringMVCContextHolder.getSystemLogger().info(sql);
        PreparedStatement ps = con.prepareStatement(sql);
        return ps.executeQuery();
    }

    /**
     * Oracle鏌ヨ鏁版嵁
     *
     * @param con 杩炴帴
     * @param map 琛ㄥ悕闆嗗弬鏁�
     * @return 鏁版嵁闆�
     * @throws SQLException
     */
    public static ResultSet getOracleResultSet(Connection con, Map<String, String> map) throws SQLException {
        String sql = map.get("sql");
        Integer currentPage = Integer.parseInt(map.get("currentPage"));
        Integer pageSize = Integer.parseInt(map.get("pageSize"));
        Integer start = (currentPage - 1) * pageSize;
        Integer end = currentPage * pageSize;
        sql = sql.replaceFirst("[?]", map.get("fileName"));
        sql = sql.replaceFirst("[?]", map.get("dataOriginName"));
        sql = sql.replaceFirst("[?]", String.valueOf(end));
        sql = sql.replaceFirst("[?]", String.valueOf(start));
        SpringMVCContextHolder.getSystemLogger().info(sql);
        PreparedStatement ps = con.prepareStatement(sql);
        return ps.executeQuery();
    }

    //浜嬩欢鍓嶆柟娉�

    /**
     * 鍙嶅皠璋冪敤鏂规硶
     *
     * @param invokeTarget 璋冪敤Bean鐨勬柟娉�  bean.fun
     * @param fse          浼犲叆鐨� FieldSetEntity
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    public static void codeCalls(String invokeTarget, FieldSetEntity fse) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //鑾峰彇bean
        String beanName = StringUtils.substringBeforeLast(invokeTarget, ".");
        Object bean = SpringUtils.getBean(beanName);
        //鑾峰彇鏂规硶鍚�
        String methodName = StringUtils.substringAfterLast(invokeTarget, ".");
        Method method = bean.getClass().getDeclaredMethod(methodName, FieldSetEntity.class);
        method.invoke(bean, fse);
    }
}