package com.org.hktshop.base;

import com.org.hktshop.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.org.hktshop.entity.Page;
import com.org.hktshop.utils.ExecSqlLib;
import com.org.hktshop.utils.MathUtil;
import com.org.hktshop.utils.ObjectMapper;

import java.sql.*;
import java.util.*;

/***
 * JDBC 基类接口
 * @author mxk
 *
 */
@Component
public class BaseDaoJdbc<T extends BaseModel> implements IBaseDaoJdbc<T> {


    /***
     * 獲得鏈接
     * @return
     */
    public Connection getConnection() {
        Connection conn = null;
        try {
            conn = MySQLPool.getInstance().getConnection();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return conn;
    }

    /**
     * @param conn
     * @param stat
     * @param rs
     * @throws SQLException 关闭数据库资源
     */
    @Override
    public void closeDataBaseResource(Connection conn, Statement stat, ResultSet rs) {
        try {
            if (rs != null) {
                rs.close();
                rs = null;
            }
        } catch (Exception e) {

        }

        try {
            if (stat != null) {
                stat.close();
                stat = null;
            }
        } catch (Exception e) {

        }

        try {
            if (conn != null) {
                MySQLPool.getInstance().releaseConnection(conn);
                conn = null;
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    /***
     * 取货该实体对应表的自增长id 下一个值
     * @param clazz
     * @return
     * @throws Exception
     */
    @Override
    public int getAutoId(T clazz) throws Exception {
        String tablename = ExecSqlLib.getTableName(clazz);
        if (tablename.contains(".")) tablename = tablename.substring(tablename.indexOf(".") + 1);
        //自增长id查询
        String sql = String.format("select auto_increment as count from information_schema.tables where table_name='%s'", tablename);
        return selectCount(sql);
    }

    /***
     * 执行查询方法，返回实体对象
     * @param sql 需要执行的SQL语句,带查询字段和where条件
     * @param clazz    需要转换的实体
     * @return
     */
    @Override
    public T query(String sql, T clazz) {
        // TODO Auto-generated method stub
        Connection connection = null;
        Statement st = null;
        ResultSet set = null;

        T obj = null;
        try {
            connection = getConnection();
            st = connection.createStatement();
            set = st.executeQuery(sql);


            List<T> values = new ObjectMapper<T>(clazz).ResultSetToObject(set);
            if (!values.isEmpty()) obj = values.get(0);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeDataBaseResource(connection, st, set);
        }
        return obj;
    }

    /***
     * 根據sql查詢返回MAP
     * 單挑數據，字段為KEY
     * @param sql
     * @return
     */
    @Override
    public Map<String, Object> query(String sql) {
        // TODO Auto-generated method stub
        Connection connection = null;
        Statement st = null;
        ResultSet set = null;

        Map<String, Object> map = null;
        try {
            connection = getConnection();
            st = connection.createStatement();
            set = st.executeQuery(sql);

            map = new ObjectMapper<T>().ResultSetToMap(set);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeDataBaseResource(connection, st, set);
        }
        return map;
    }

    /***
     * 执行查询方法，返回数组
     * @param sql 需要执行的SQL语句,带查询字段和where条件
     * @return
     */
//    @Override
//    public Object[] queryForArray(String sql) {
//        // TODO Auto-generated method stub
//        Connection connection = null;
//        Statement st = null;
//        ResultSet set = null;
//
//        Object[] obj = null;
//        try {
//            connection = getConnection();
//            st = connection.createStatement();
//            set = st.executeQuery(sql);
//
//
//            obj = new ObjectMapper<T>().ResultSetToArray(set);
//        } catch (Exception e) {
//            e.printStackTrace();
//        } finally {
//            closeDataBaseResource(connection, st, set);
//        }
//        return obj;
//    }

    /***
     * /***
     * 查询某一页数据
     * @param sql 帶參數的SQL 必須包含排序
     * @param pageNum    當前頁數
     * @param pageSize    頁面行數
     * @return
     */
//    @Override
//    public Page<T> queryPageArray(String sql, int pageNum, int pageSize) {
//        // TODO Auto-generated method stub
//        Connection connection = null;
//        PreparedStatement st = null;
//        ResultSet set = null;
//
//        Object[] obj = null;
//        Page<T> page = null;
//        try {
//            page = getPageInfo(sql, pageSize);
//            if (page.getTotal() > 0) {
//                connection = getConnection();
//                sql += " LIMIT ?,?";
//
//                st = connection.prepareStatement(sql);
//                st.setInt(1, (pageNum - 1) * pageSize);
//                st.setInt(2, pageSize);
//
//                set = st.executeQuery();
//
//                obj = new ObjectMapper<T>().ResultSetToArray(set);
////                page.setRecordArray(obj);
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        } finally {
//            closeDataBaseResource(connection, st, set);
//        }
//        return page;
//    }

    /***
     * /***
     * 查询某一页数据
     * @param sql 帶參數的SQL 必須包含排序
     * @param sql
     * @param clazz
     * @return
     */
    @Override
    public Page<T> queryPage(String sql, T clazz) {
        // TODO Auto-generated method stub
        // TODO Auto-generated method stub
        Connection connection = null;
        PreparedStatement st = null;
        ResultSet set = null;

        List<T> objs = null;
        Page<T> page = null;
        try {
            page = getPageInfo(sql, clazz.getPageSize());
            if (page.getTotal() > 0) {
                connection = getConnection();
                sql += " LIMIT ?,?";

                st = connection.prepareStatement(sql);
                st.setInt(1, (clazz.getPageNum() - 1) * clazz.getPageSize());
                st.setInt(2, clazz.getPageSize());

                set = st.executeQuery();

                objs = new ObjectMapper<T>(clazz).ResultSetToObject(set);
                page.setRecords(objs);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeDataBaseResource(connection, st, set);
        }
        return page;
    }

    @Override
    public Page<T> queryPage(String sql, String sql2,T clazz) {
        // TODO Auto-generated method stub
        // TODO Auto-generated method stub
        Connection connection = null;
        PreparedStatement st = null;
        ResultSet set = null;

        List<T> objs = null;
        Page<T> page = null;
        try {
            page = getPageInfo1(sql2,clazz.getPageSize());
            if (page.getTotal() > 0) {
                connection = getConnection();
                sql += " LIMIT ?,?";

                st = connection.prepareStatement(sql);
                st.setInt(1, (clazz.getPageNum() - 1) * clazz.getPageSize());
                st.setInt(2, clazz.getPageSize());

                set = st.executeQuery();

                objs = new ObjectMapper<T>(clazz).ResultSetToObject(set);
                page.setRecords(objs);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeDataBaseResource(connection, st, set);
        }
        return page;
    }

    /***
     * 翻页信息
     * @param sql
     * @param pageSize
     * @return
     */
    private Page<T> getPageInfo(String sql, int pageSize) throws Exception {
        Page<T> page = new Page<T>();
        try {
            int count = selectCount(ExecSqlLib.GetCountSql(sql));

            if (count > 0) {
                page.setTotal(count);
                page.setPageSize(pageSize);
                Double p = MathUtil.divide(count, pageSize);

                int pages = 0;
                if (p < 1 && p > 0) {
                    pages = 1;
                } else {
                    //向上取整
                    pages = (int) Math.ceil(p);
                }
                page.setPages(pages);
            }
        } catch (Exception e) {
            throw e;
        }
        return page;
    }


    private Page<T> getPageInfo1(String sql,int pageSize) throws Exception {
        Page<T> page = new Page<T>();
        try {
            int count = selectCount(sql);
            if (count > 0) {
                page.setTotal(count);
                page.setPageSize(pageSize);
                Double p = MathUtil.divide(count, pageSize);

                int pages = 0;
                if (p < 1 && p > 0) {
                    pages = 1;
                } else {
                    //向上取整
                    pages = (int) Math.ceil(p);
                }
                page.setPages(pages);
            }
        } catch (Exception e) {
            throw e;
        }
        return page;
    }
    /***
     * 执行查询方法，返回集合,需要进行数据操作。
     * 如果是页面查询,直接返回数组 queryForArray方法
     * @param sql
     * @param clazz
     * @return
     */
    @Override
    public List<T> queryList(String sql, T clazz) {
        // TODO Auto-generated method stub
        Connection connection = null;
        Statement st = null;
        ResultSet set = null;

        List<T> objs = null;
        try {
            connection = getConnection();
            st = connection.createStatement();

            set = st.executeQuery(sql);
            objs = new ObjectMapper<T>(clazz).ResultSetToObject(set);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeDataBaseResource(connection, st, set);
        }
        return objs;
    }

    /***
     * 查询数据条目
     * @param sql
     * @return
     */
    @Override
    public int selectCount(String sql) throws Exception {
        // TODO Auto-generated method stub
        Connection connection = null;
        Statement st = null;
        ResultSet set = null;
        int count = 0;
        try {
            connection = getConnection();
            st = connection.createStatement();

            set = st.executeQuery(sql);
            if (set.next()) {
                count = set.getInt("count");
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeDataBaseResource(connection, st, set);
        }
        return count;
    }

    /***
     * 获取单个值
     * @param sql
     * @return
     */
    @Override
    public Object queryForObject(String sql) {
        Connection connection = null;
        Statement st = null;
        ResultSet set = null;
        Object obj = null;
        try {
            connection = getConnection();
            st = connection.createStatement();

            set = st.executeQuery(sql);
            if (set.next()) {
                obj = set.getObject(1);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeDataBaseResource(connection, st, set);
        }
        return obj;
    }

    /***
     * 执行单条数据，更新或者插入
     * @param sql
     * @return
     */
    @Override
    public boolean execute(String sql) {
        // TODO Auto-generated method stub
        boolean b = true;
        Connection connection = null;
        Statement st = null;
        try {
            connection = getConnection();
            st = connection.createStatement();

            st.execute(sql);
        } catch (Exception e) {
            e.printStackTrace();
            b = false;
        } finally {
            closeDataBaseResource(connection, st, null);
        }
        return b;
    }

    /***
     * 批量更新或者插入数据
     * @param listSql
     * @return
     */
    @Override
    public boolean execute(List<String> listSql) {
        // TODO Auto-generated method stub

        boolean b = true;
        Connection connection = null;
        Statement st = null;
        try {
            connection = getConnection();
            st = connection.createStatement();
            for (String sql : listSql) {
                st.addBatch(sql);
            }
            st.executeBatch();
        } catch (Exception e) {
            e.printStackTrace();
            b = false;
        } finally {
            closeDataBaseResource(connection, st, null);
        }

        return b;
    }

    /***
     * 批量更新或者插入数据，并带事务。
     * @param listSql
     * @return
     */
    @Override
    public boolean executeTransaction(List<String> listSql) {
        // TODO Auto-generated method stub

        boolean b = true;
        Connection connection = null;
        Statement st = null;
        try {
            connection = getConnection();
            connection.setAutoCommit(false);
            st = connection.createStatement();
            for (String sql : listSql) {
                st.addBatch(sql);
            }
            st.executeBatch();
            connection.commit();
        } catch (Exception e) {

            b = false;
            try {
                connection.rollback();
            } catch (SQLException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

        } finally {
            closeDataBaseResource(connection, st, null);
        }

        return b;
    }


//    @Override
//    public Set<String> executeByKsn(String filed) {
//        // TODO Auto-generated method stub
//        Connection connection = null;
//        Statement st = null;
//        Set<String> set = new HashSet<>();
//        try {
//            connection = getConnection();
//            st = connection.createStatement();
//            String sql = "select " + filed + " from hkt_goods";
//            ResultSet resultSet = st.executeQuery(sql);
//            while (resultSet.next()) {
//                set.add(resultSet.getString(filed));
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        } finally {
//            closeDataBaseResource(connection, st, null);
//        }
//        return set;
//    }
//
//    @Override
//    public int executeCountByWhere(String sql) {
//        Connection connection = null;
//        Statement st = null;
//        int count = 0;
//        try {
//            connection = getConnection();
//            st = connection.createStatement();
//
//            ResultSet resultSet = st.executeQuery(sql);
//            while (resultSet.next()) {
//                count = 1;
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        } finally {
//            closeDataBaseResource(connection, st, null);
//        }
//        return count;
//    }

    @Override
    public List<Map<String, String>> executeForMap(String sql) {
        Connection connection = null;
        Statement st = null;
        List<Map<String, String>> list = new ArrayList<>();
        try {
            connection = getConnection();
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            ResultSet resultSet = preparedStatement.executeQuery();
            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            while (resultSet.next()) {
                Map<String, String> rowData = new HashMap();
                for (int i = 1; i <= columnCount; i++) {
                    String[] split = metaData.getColumnLabel(i).split("_");
                    String key = split[0].toLowerCase();
                    for (int j = 0; j < split.length - 1; j++) {
                        String s = split[j + 1].substring(0, 1).toUpperCase() + split[j + 1].substring(1).toLowerCase();
                        key += s;
                    }
                    rowData.put(key, resultSet.getString(i));
                }
                list.add(rowData);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeDataBaseResource(connection, st, null);
        }
        return list;
    }


//    @Override
//    public String executeInserte(String sql) {
//        Connection conn = null;
//        Statement st = null;
//        String num ="";
//        try {
//            conn = getConnection();
//            st = conn.createStatement();
//
//            ResultSet resultSet = st.executeQuery(sql);
//            while (resultSet.next()) {
//                num = resultSet.getString(1);
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        } finally {
//            closeDataBaseResource(conn, st, null);
//        }
//        return num;
//    }
}
