package weaver.interfaces.htsc.util;

import org.apache.commons.lang3.StringUtils;
import weaver.conn.RecordSet;
import weaver.general.GCONST;
import weaver.general.Util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * sql工具类，辅助生成插入、更新、分页等sql
 * @author wanxq
 */
public class SqlUtil {

    private String tableName;
    private List<String> insertColumnNameList;
    private List<Object> insertColumnValueList;

    private Map<String,Object> updateKV;
    private Map<String,Object> conditionKV;
    private String conditionSql;


    /**
     * 无参构造函数
     */
    public SqlUtil(){

    }

    /**
     * 带有sql表名的构造函数
     * @param tableName(表名)
     */
    public SqlUtil(String tableName) {
        this.tableName = tableName.toUpperCase();
        this.insertColumnNameList = new ArrayList<String>();
        this.insertColumnValueList = new ArrayList<Object>();
        this.updateKV = new HashMap<String,Object>();
        this.conditionKV = new HashMap<String,Object>();
    }

    /**
     * 获取表名
     * @return 表名
     */
    public String getTableName() {
        return tableName;
    }

    /**
     * 返回插入列名
     * @return 插入的列名
     */
    public List<String> getInsertColumnNameList() {
        return insertColumnNameList;
    }

    /**
     * 返回插入列值
     * @return 插入列值
     */
    public List<Object> getInsertColumnValueList() {
        return insertColumnValueList;
    }

    /**
     * 返回更新字段键值对
     * @return 更新字段的键值对
     */
    public Map<String, Object> getUpdateKV() {
        return updateKV;
    }

    /**
     * 返回条件键值对
     * @return 条件键值对
     */
    public Map<String, Object> getConditionKV() {
        return conditionKV;
    }

    /**
     * 返回更新语句的条件sql
     * @return 条件sql
     */
    public String getConditionSql() {
        return conditionSql;
    }

    /**
     * 添加插入列和值
     * @param columnName 插入列名
     * @param columnValue 插入列值
     * @return 当前对象
     */
    public SqlUtil addInsertKV(String columnName, Object columnValue) {
        this.insertColumnNameList.add(columnName);
        this.insertColumnValueList.add(columnValue);
        return this;

    }

    /**
     * 添加更新列和值
     * @param columnName 更新列名
     * @param columnValue 更新列值
     * @return 当前对象
     */
    public SqlUtil addUpdateKV(String columnName, Object columnValue){
        this.updateKV.put(columnName,columnValue);
        return this;
    }

    /**
     * 添加更新的条件字段和值
     * @param columnName 列名
     * @param columnValue 列值
     * @return 当前对象
     */
    public SqlUtil addConditionKV(String columnName, Object columnValue){
        this.conditionKV.put(columnName,columnValue);
        return this;
    }


    /**
     * 添加自定义更新条件
     * @param conditionSql 条件sql
     * @return 当前对象
     */
    public SqlUtil addConditionSql(String conditionSql){
        this.conditionSql = conditionSql;
        return this;
    }


    /**
     * 返回插入的列名
     * @return 插入列名
     */
    public String getInsertColumns(){
        return this.insertColumnNameList.stream()
                .map(String::toUpperCase)
                .collect(Collectors.joining(","));
    }


    /**
     * 返回插入的值
     * @param isTemplate 是否返回预编译sql
     * @return 插入列值
     */
    private String getInsertValues(boolean isTemplate){
        String values = this.insertColumnValueList.stream().map(Object-> {
            if(isTemplate){
                return "?";
            }else{
                if (Object instanceof String) {
                    return "'"+Object.toString()+"'";
                }else{
                    return Object+"";
                }
            }

        }).collect(Collectors.joining(","));
        return values;
    }


    /**
     * 构建插入sql，字符串拼接
     * @return 插入sql
     */
    public String getInsertSql() {
        return getInsertSql(false);
    }


    /**
     * 构建插入sql，生产插入sql预编译模板
     * @param isTemplate 是否返回预编译sql
     * @return 插入sql
     */
    public String getInsertSql(boolean isTemplate) {
        String cloumns = getInsertColumns();
        String values = getInsertValues(isTemplate);

        StringBuffer sb = new StringBuffer();
        sb.append(" INSERT INTO ");
        sb.append(this.tableName);
        sb.append("(");
        sb.append(cloumns);
        sb.append(") VALUES(");
        sb.append(values);
        sb.append(") ");
        return sb.toString();
    }




    /**
     * 构建更新sql
     * @return 更新sql
     */
    public String getUpdateSql() {
        return getUpdateSql(false);
    }


    /**
     * 构建更新sql模板
     * @param isTemplate 是否返回预编译sql
     * @return 更新sql
     */
    public String getUpdateSql(boolean isTemplate) {
        StringBuffer sb = new StringBuffer();
        sb.append(" UPDATE ");
        sb.append(this.tableName);
        sb.append(" SET ");
        List<String> updateKVArr = new ArrayList();
        for (Map.Entry<String, Object> entry : updateKV.entrySet()) {
            String key = Util.null2String(entry.getKey()).toUpperCase();
            Object value = entry.getValue();
            String kvStr = "";
            if(isTemplate){
                kvStr = key+"=?";
            }else{
                if(value instanceof String){
                    kvStr = key+"='"+value+"'";
                }else{
                    kvStr = key+"="+value+"";
                }

            }
            updateKVArr.add(kvStr);
        }
        sb.append(StringUtils.join(updateKVArr.toArray(), " , "));


        List<String> conditionKVArr = new ArrayList();
        for (Map.Entry<String, Object> entry : conditionKV.entrySet()) {
            String key = Util.null2String(entry.getKey()).toUpperCase();
            Object value = entry.getValue();
            String conditionKvStr = "";
            if(isTemplate){
                conditionKvStr = key+"=?";
            }else{
                if(value instanceof String){
                    conditionKvStr = key+"='"+value+"'";
                }else{
                    conditionKvStr = key+"="+value;
                }

            }
            conditionKVArr.add(conditionKvStr);
        }

        if(!(conditionKVArr.size()==0 && (conditionSql==null || "".equals(conditionSql)))){
            sb.append(" WHERE ");
            sb.append(StringUtils.join(conditionKVArr.toArray(), " AND "));
            if(conditionSql!=null && !"".equals(conditionSql)){
                if(conditionKVArr.size()>0){
                    sb.append(" AND ");
                }
                sb.append(conditionSql);
            }

        }


        return sb.toString();
    }


    /**
     * 将查询数据转为list(无参)
     * @param sql 查询sql
     * @return list查询结果
     */
    public static List queryDataToList(String sql){
        return queryDataToList(sql,null);
    }

    /**
     * 将查询数据转为list
     * @param sql 查询sql
     * @param params sql参数
     * @return list查询结果
     */
    public static List queryDataToList(String sql,Object params){
        RecordSet rs = new RecordSet();
        List<Map<String,Object> > data = new ArrayList<Map<String,Object>>();
        if(params==null){
            rs.execute(sql);
        }else{
            rs.executeQuery(sql,params);
        }
        while(rs.next()){
            Map<String,Object> map = new HashMap<String,Object>();
            String[] colnums = rs.getColumnName();
            for (String colnum : colnums) {
                map.put(colnum.toLowerCase(),rs.getString(colnum));
            }
            data.add(map);
        }
        return data;
    }


    /**
     * 查询结果转为Map
     * @param sql 查询sql
     * @param params sql参数
     * @return map查询结果
     */
    public static Map<String, String> queryDataToMap(String sql,Object params){
        Map<String, String> resultMap = new HashMap<String, String>();
        RecordSet rs = new RecordSet();
        if(params==null){
            rs.execute(sql);
        }else{
            rs.executeQuery(sql,params);
        }
        String[] columnNames = rs.getColumnName();
        if(rs.next()){
            for(String columnName : columnNames){
                resultMap.put(columnName.toLowerCase(), rs.getString(columnName));
            }
        }
        return resultMap;
    }


    /**
     * 返回单个字段的查询结果，默认返回第一个字段
     * @param sql 查询sql
     * @return 查询结果第一个字段
     */
    public static String querySingleField(String sql) {
        RecordSet rs = new RecordSet();
        rs.execute(sql);
        rs.next();
        return Util.null2String(rs.getString(1));
    }

    /**
     * 返回单个字段的查询结果
     * @param sql 查询sql
     * @param params sql参数
     * @return 查询结果第一个字段
     */
    public static String querySingleField(String sql,Object params) {
        RecordSet rs = new RecordSet();
        if(params==null){
            rs.execute(sql);
        }else{
            rs.writeLog("有参数==="+params);
            rs.executeQuery(sql,params);
        }
        rs.next();
        return Util.null2String(rs.getString(1));
    }

    /**
     * 返回单个字段的查询结果
     * @param sql 查询sql
     * @param column 指定返回的字段
     * @param params 查询sql参数
     * @return 单个字段的查询结果
     */
    public static String querySingleField(String sql,String column,Object params) {
        RecordSet rs = new RecordSet();
        if(params==null){
            rs.execute(sql);
        }else{
            rs.executeQuery(sql,params);
        }
        rs.next();
        return Util.null2String(rs.getString(column));
    }



    /**
     * 返回HSQL数据库分页语句
     * @param sql 需要分页的sql
     * @param start 开始记录
     * @param end 结束记录
     * @return 分页SQL
     */
    public static String getHSQLPagedSql(String sql,int start, int end) {
        return new StringBuffer().append(sql).insert(
                sql.toLowerCase().indexOf("select") + 6, " limit "+start+" "+(end-start))
                .toString();
    }


    /**
     * 返回Mysql数据库分页语句
     * @param sql 需要分页的sql
     * @param start 开始记录
     * @param end 结束记录
     * @return 分页SQL
     */
    public static  String getMysqlPagedSql(String sql,int start, int end) {
        return new StringBuffer().append(sql).append(
                " LIMIT "+start+","+(end-start)).toString();
    }


    /**
     * 返回PostgreSQL数据库分页语句
     * @param sql 需要分页的sql
     * @param start 开始记录
     * @param end 结束记录
     * @return 分页SQL
     */
    public static  String getPostgreSQLPagedSql(String sql,int start, int end) {
        return new StringBuffer(sql.length() + 20).append(sql).append(
                " LIMIT ? OFFSET ?").toString();
    }


    /**
     * 返回SqlServer数据库分页语句
     * @param sqlstr 需要分页的sql
     * @param start 开始记录
     * @param end 结束记录
     * @return 分页SQL
     */
    public static  String getSqlServerPageSql(String sqlstr, int start,int end) {
        String sql = sqlstr;
        String PK = "id";
        String con1 = "select";
        String con2 = "from";
        String con3 = "where";
        String con4 = "group by";
        String con5=" order ";
        int i1 = sql.indexOf(con1);
        int i2 = sql.indexOf(con2);
        int i3 = sql.indexOf(con3);
        int i4 = sql.indexOf(con4);
        int i5=sql.indexOf(con5);
        String strgroupby="";
        if(i4!=-1){
            if(i5!=-1){
                strgroupby=sql.substring(i4,i5);
            }else{
                strgroupby=sql.substring(i4,sql.length());
            }
        }
        String selectitem = "";
        String tablename = "";
        String cond = "";
        String orders = "";

        selectitem = sql.substring(i1 + 6, i2);

        if (i3 != -1) {
            tablename = sql.substring(i2 + 4, i3);
            if(i4!=-1){
                cond=sql.substring(i3 + 5, i4);
                if(i5!=-1){
                    orders=sql.substring(i5 + 6, sql.length());
                }
            }else{
                if(i5!=-1){
                    cond = sql.substring(i3 + 5, i5);
                    orders=sql.substring(i5+6,sql.length());
                }else{
                    cond=sql.substring(i3+5,sql.length());
                }
            }
        } else {
            if (i4 != -1) {
                tablename = sql.substring(i2 + 4, i4);
                if(i5!=-1){
                    orders = sql.substring(i5 + 6, sql.length());
                }
            } else {
                if(i5!=-1){
                    tablename = sql.substring(i2 + 4, i5);
                    orders = sql.substring(i5 + 6, sql.length());
                }else{
                    tablename = sql.substring(i2 + 4, sql.length());
                }
            }
        }

        String maintb = tablename;//主表名称和别名

        if(tablename.contains(",")){
            maintb = tablename.split(",")[0];
        }

        String[] sqls = maintb.split(" ");
        String tabel = "";
        for(int i=0; i<sqls.length; i++){
            if(!sqls[i].trim().equals("")){
                tabel = sqls[i];
            }
        }
        PK = tabel +".id";
        if(tabel.contains("=")){   //当表连接时，（如tabel最后为fi.id=fl.pid PK就取fi.id）
            PK=tabel.substring(0,tabel.indexOf("="));
        }
        String _orders = "";
        if (i5 != -1) {
            _orders = " order " + orders;
        }

        String distin ="";
        if(selectitem.toLowerCase().contains("distinct")){
            distin = "distinct";
            selectitem = selectitem.substring(selectitem.indexOf("distinct")+8);
        }
        sql = "select " + distin +  " Top " + (end-start) + " " + selectitem + " from " + tablename + " where ";
        if (i3 != -1) {
            sql += "(" + cond + ") and ";
        }
        sql += PK + " NOT IN (select Top " + start + " " + PK
                + " from " + tablename + " ";
        if (i3 != -1) {
            sql += " where " + cond;
        }

        if(i4!=-1){
            int index=strgroupby.indexOf("group by");
            String groupby=strgroupby.substring(0, index+8);
            String keys=strgroupby.substring(index+8, strgroupby.length());
            sql+=" "+groupby+" "+PK+","+keys;
        }

        sql += _orders + " ) ";

        if(i4!=-1){
            sql +=" "+strgroupby;
        }
        sql +=_orders;

        return sql;
    }

    /**
     * 返回Oracle数据库分页语句
     * @param sql 需要分页的sql
     * @param start 开始记录
     * @param end 结束记录
     * @return 分页SQL
     */
    public static  String getOraclePagedSql(String sql,int start, int end) {
        StringBuffer pagingSelect = new StringBuffer(sql.length() + 100);
        pagingSelect
                .append("SELECT * FROM ( SELECT ROW_.*, ROWNUM ROWNUM_ FROM ( ");
        pagingSelect.append(sql);
        pagingSelect.append(" ) ROW_ WHERE ROWNUM <=").append(end).append(") WHERE ROWNUM_ >").append(start);
        return pagingSelect.toString();
    }



    public static void main(String args[]) {
        GCONST.setRootPath("./");
        GCONST.setServerName("ecology");

        String tablename = WfUtil.getTableNameByRequestID("3820833");
        System.out.println(tablename);
    }
}
