package com.boman.web.core.mapper;

import com.alibaba.fastjson.JSONObject;
import com.boman.domain.VaccineInfoOperation;
import com.boman.web.core.utils.ColumnUtils;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.jdbc.SQL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.function.Consumer;

import static com.boman.common.core.utils.obj.ObjectUtils.*;
import static com.boman.domain.constant.FormDataConstant.*;

/**
 * @author shiqian
 * @description
 * @date 2021年03月22日 11:36
 **/
@Mapper
@Component
public interface StandardlyMapper {

    Logger LOGGER = LoggerFactory.getLogger(StandardlyMapper.class);

    /** {@link SqlProvider#moveData(java.util.Map)} */
    @UpdateProvider(type = SqlProvider.class,method = "moveData")
    int moveData(@Param("idCard") String idCard);

    @Select({"select 身份证 FROM ymjz limit #{limit}, #{offset}"})
    List<String> listIdCard(@Param("limit") int limit, @Param("offset") int offset);

    @Select({"select 受种者编码, 工作单位, 人群分类, 身份证 FROM ymjz limit #{limit}, #{offset}"})
    List<JSONObject> listInfo(@Param("limit") int limit, @Param("offset") int offset);

    /** {@link SqlProvider#updateById(java.util.Map)} */
    @UpdateProvider(type = SqlProvider.class, method = "updateById")
    int updateById(@Param("tableName") String var1, @Param("model") JSONObject var2
            , @Param("pkName") String pkName, @Param("ids") Long[] ids);

    @UpdateProvider(
            type = SqlProvider.class,
            method = "update"
    )
    int newUpdateById(@Param("tableName") String var1, @Param("model") long var2);


    @DeleteProvider(
            type = SqlProvider.class,
            method = "delete"
    )
    int deleteByIds(@Param("tableName") String var1, @Param("ids") Long[] var2, @Param("pkName") String pkName);

    @Delete({"DELETE FROM ${tableName} where ID = #{id}"})
    int deleteById(@Param("tableName") String tableName, @Param("pkName") String pkName, @Param("id") long var2);

    @Select({"select * FROM ${tableName} where ID = #{id}"})
    JSONObject getById(@Param("tableName") String var1, @Param("id") long var2);

    @Select({"select ${columns} FROM ${tableName} where ID = #{id}"})
    JSONObject getColumnsById(@Param("tableName") String var1, @Param("columns") String var2, @Param("id") long var3);

    @InsertProvider(
            type = SqlProvider.class,
            method = "insert"
    )
    int insert(@Param("tableName") String var1, @Param("model") JSONObject var2);

    @InsertProvider(
            type = SqlProvider.class,
            method = "inserts"
    )
    int inserts(@Param("tableName") String var1, @Param("models") JSONObject[] var2, @Param("processor") Consumer<JSONObject> var3);

    @Select({"select count(1) FROM ${tableName} where ${column} = #{value} limit 1"})
    boolean exists(@Param("tableName") String var1, @Param("column") String var2, @Param("value") Object var3);

    @Select({"select count(1) FROM ${tableName} where ID = #{id} limit 1"})
    boolean existsById(@Param("tableName") String var1, @Param("id") long var2);

    @Select({"select * from vaccination_statistic where is_del = 'N'"})
    List<JSONObject> list();

    @Select({"select * from vaccination_statistic where is_del = 'N' and xz = #{deptName}"})
    List<JSONObject> list1(@Param("deptName") String deptName);

    @Update({"update vaccination_statistic set is_del = 'Y' where create_by = #{username}"})
    int updateAll(@Param("username") String username);

    @Select("select * from ymjz20210923")
    List<JSONObject> selectAll();

    @Select("select * from vaccine_info")
    List<JSONObject> listVacc();

    @Select("select * from vaccine_info where id_card = #{idCard}")
    VaccineInfoOperation getByIdCard(@Param("idCard") String idCard);

    @Select("select dept_id deptId, id_card idCard, contraindication, suspend, other, progress " +
            "from vaccine_info where code = #{code} or (id_card like #{idCard} and user_name like #{userName} ) limit 1")
    VaccineInfoOperation getByCode(@Param("code") String code, @Param("idCard") String idCard, @Param("userName") String userName);

    @Select("select dept_id deptId, id_card idCard, contraindication, suspend, other, progress from vaccine_info where code = #{code} limit 1")
    VaccineInfoOperation getByIdCarUserName(@Param("idCard") String idCard, @Param("userName") String userName);

    @Select({"select count(1) FROM ${tableName} where id <> #{id} and ${column} = #{value} limit 1"})
    boolean existsWithoutId(@Param("tableName") String var1, @Param("id") long var2, @Param("column") String var4, @Param("value") Object var5);

    @UpdateProvider(
            type = SqlProvider.class,
            method = "updates"
    )
    int updates(@Param("tableName") String var1, @Param("models") Collection<Object> var2, @Param("processor") Consumer<JSONObject> var3);

    /** {@link SqlProvider#updateByIdList(Map)} */
    @UpdateProvider(type = SqlProvider.class, method = "updateByIdList")
    int updateByIdList(@Param("tableName") String tableName, @Param("pkName") String pkName
            , @Param("idList") List<Long> idList, @Param("model") JSONObject models);

    @Select("select id from ${tableName} where ${akColumnName} = #{akColumnValue}")
    Long selectIdByAkColumn(@Param("tableName") String tableName, @Param("akColumnName") String akColumnName, @Param("akColumnValue") String akColumnValue);

    @Select("select ifnull(max(${pkName}),0) from ${tableName}")
    int selectMaxId(@Param("tableName") String tableName, @Param("pkName") String pkName);

    /**
     * 功能描述: 根据id查所有
     *
     * @param tableName 表名
     * @param pkName    主键名称
     * @param id        主键值
     * @return com.alibaba.fastjson.JSONObject
     */
//    @Select("select * from ${tableName} where ${pkName} = #{id} limit 1")
    @SelectProvider(type = SqlProvider.class, method = "selectById")
    JSONObject selectById(@Param("tableName") String tableName
            , @Param("pkName") String pkName, @Param("id") Long id,  @Param("other") String other);

    @SelectProvider(type = SqlProvider.class, method = "selectCandidatorsById")
    List<JSONObject> selectCandidatorsById(@Param("tableName") String tableName
            , @Param("pkName") String pkName, @Param("ids") List<Long> ids, @Param("type") int type);

    /**
     * 功能描述: 根据id查所有
     * {@link SqlProvider#selectByIdList(Map)}
     *
     * @param tableName 表名
     * @param pkName    主键名称
     * @param idList    主键值
     * @param showData  需要展示的列
     * @return com.alibaba.fastjson.JSONObject
     */
    @SelectProvider(type = SqlProvider.class, method = "selectByIdList")
    List<JSONObject> selectByIdList(@Param("tableName") String tableName
            , @Param("pkName") String pkName, @Param("idList") List<Long> idList
            , @Param("showData") List<String> showData);

    /**
     * 功能描述: 自定义查询，需要查询的字段和value都在condition中
     * {@link SqlProvider#selectByCondition(Map)}
     *
     * @param tableName     tableName
     * @param condition     condition
     * @param packCondition 封装好的查询条件
     * @param showData      需要查询的列
     * @param orderBy       orderBy
     * @param limit         分页
     * @param offset        分页， 可以为null
     * @return java.util.List<com.alibaba.fastjson.JSONObject>
     */
    @SelectProvider(type = SqlProvider.class, method = "selectByCondition")
    List<JSONObject> selectByCondition(@Param("tableName") String tableName
            , @Param("condition") JSONObject condition
            , @Param("packCondition") JSONObject packCondition
            , @Param("showData") List<String> showData
            , @Param("orderBy") String orderBy
            , @Param("limit") int limit
            , @Param("offset") int offset);


    /**
     * 功能描述: 自定义查询，需要查询的字段和value都在condition中
     * {@link SqlProvider#countByCondition(Map)}
     *
     * @param tableName     tableName
     * @param condition     condition
     * @param packCondition 封装好的查询条件
     * @return int
     */
    @SelectProvider(type = SqlProvider.class, method = "countByCondition")
    int countByCondition(@Param("tableName") String tableName
            , @Param("condition") JSONObject condition
            , @Param("packCondition") JSONObject packCondition);

    /**
     * 功能描述: 根据tableName和map(属性名和属性值)进行查查
     * {@link SqlProvider#getByMap(java.util.Map)}
     *
     * @param tableName     tableName
     * @param condition     属性名和属性值
     * @param packCondition 属性名和属性值 条件
     * @param limitOne      true sql加上limit 1,   false 则不加
     * @return java.util.List<com.alibaba.fastjson.JSONObject>
     */
    @SelectProvider(type = SqlProvider.class, method = "getByMap")
    List<JSONObject> getByMap(@Param("tableName") String tableName
            , @Param("condition") JSONObject condition
            , @Param("packCondition") JSONObject packCondition
            , @Param("limitOne") boolean limitOne);

    /**
     * 功能描述: 获取最新的一条数据 create desc
     *
     * @param tableName tableName
     * @return jcom.alibaba.fastjson.JSONObject
     */
    @Select("select * from ${tableName} order by create_time desc limit 1")
    JSONObject getNewest(@Param("tableName") String tableName);

    /**
     * 按月统计人员考勤信息
     * @param date
     * @return
     */
    @Select("<script>" +
            "SELECT\n" +
            "t.attendance_table_username as userName,\n" +
            "t.user_id,\n" +
            "d.dept_name as deptName,\n" +
            "sum(if(attendance_table_leave_or = 'Y','1','0')) as attendanceTableLeaveOrSum,\n" +
            "sum(if(attendance_table_late = 'Y','1','0')) as attendanceTableLateSum,\n" +
            "sum(if(attendance_table_leave = 'Y','1','0')) as attendanceTableLeaveSum,\n" +
            "DATE_FORMAT(t.create_time,'%Y-%m') as date\n" +
            "FROM attendance_table t\n" +
            "LEFT JOIN sys_dept d ON d.id = t.dept_id \n" +
            "<where>" +
            "1=1 " +
            "<if SysRegion=\"name != null and name != ''\">and ( d.dept_name like concat('%', #{name}, '%') or t.attendance_table_username like concat('%', #{name}, '%'))</if>"+
            "<if SysRegion='date!=null'>and DATE_FORMAT(t.create_time,'%Y-%m') = #{date} </if>"+
            "</where>" +
            "GROUP BY\n" +
            " d.dept_name,t.attendance_table_username,t.user_id,DATE_FORMAT( t.create_time, '%Y-%m' )\n" +
            "limit #{pageNo}, #{pageSize}" +
            "</script>")
    List<JSONObject> statisticsByMonth(@Param("date") String date, @Param("name") String name
            , @Param("pageNo") int pageNo, @Param("pageSize") int pageSize);

    /**
     * 查询用户某月的上班打卡时间
     * @param date
     * @param userId
     * @return
     */

    @Select("SELECT\n" +
            "\tDATE_FORMAT(attendance_table_work,'%Y-%m-%d %H:%i:%s') as attendanceTableWork,\n" +
            "\tDATE_FORMAT(attendance_table_offwork,'%Y-%m-%d %H:%i:%s') AS attendanceTableOffWork,\n" +
            "\tDATE_FORMAT(attendance_table_work_pm,'%Y-%m-%d %H:%i:%s') AS attendanceTableWorkPm,\n" +
            "\tDATE_FORMAT(attendance_table_offwork_pm,'%Y-%m-%d %H:%i:%s') as  attendanceTableOffWorkPm\n" +
            "FROM\n" +
            "\tattendance_table \n" +
            "WHERE\n" +
            "\tDATE_FORMAT( create_time, '%Y-%m' ) = #{date} \n" +
            "\tAND user_id = #{userId}")
    List<JSONObject> findDate(@Param("date")String date, @Param("userId")Long userId);

    /**
     * 功能描述: 通用修改  {@link SqlProvider#update(java.util.Map)}
     *
     * @param tableName      tableName
     * @param packCommitData packCommitData
     * @param condition      condition
     * @return int
     */
    @UpdateProvider(type = SqlProvider.class, method = "update")
    int update(@Param("tableName") String tableName, @Param("packCommitData") JSONObject packCommitData
            , @Param("packColCondition") JSONObject packColCondition, @Param("condition") JSONObject condition);

    /******************************************************  临时请假当月的总时长 ******************************************************/
    /** {@link SqlProvider#sumBeforeTempLeaveTime(java.util.Map)}**/
    @SelectProvider(type = SqlProvider.class, method = "sumBeforeTempLeaveTime")
    String sumBeforeTempLeaveTime(@Param("username") String username, @Param("startTime") String startTime
            , @Param("endTime") String endTime, @Param("idList") List<Long> idList);

    @SuppressWarnings("unchecked")
    class SqlProvider {
        static final String[] READONLY_COLUMNS = new String[]{"OWNERID", "OWNERNAME", "OWNERENAME", "CREATIONDATE", "ID"};

        public SqlProvider() {
        }

        private static boolean isReadOnly(String column) {
            String[] var1 = READONLY_COLUMNS;
            int var2 = var1.length;

            for (int var3 = 0; var3 < var2; ++var3) {
                String readonlyColumn = var1[var3];
                if (readonlyColumn.equals(column)) {
                    return true;
                }
            }

            return false;
        }

        private static boolean isNullOrEmpty(String str) {
            return str == null || str.length() == 0 || str.trim().length() == 0;
        }

        private static boolean isNullOrEmpty(JSONObject json) {
            return json == null || json.isEmpty();
        }

        private static void keyToUpper(JSONObject json) {
            String[] keys = new String[json.size()];
            json.keySet().toArray(keys);
            String[] var2 = keys;
            int var3 = keys.length;

            for (int var4 = 0; var4 < var3; ++var4) {
                String key = var2[var4];
                if (!key.equals(key.toUpperCase())) {
                    json.put(key.toUpperCase(), json.get(key));
                    json.remove(key);
                }
            }

        }

        public String update(Map<String, Object> para) {
            String tableName = (String) para.get("tableName");
            JSONObject packCommitData = (JSONObject) para.get("packCommitData");
            JSONObject packColCondition = (JSONObject) para.get("packColCondition");

            StringBuilder wholeSql = new StringBuilder();
            wholeSql.append("update ").append(tableName).append(" set ");

            for (Map.Entry<String, Object> entry : packCommitData.entrySet()) {
                String key = entry.getKey();
                Object valueObj = entry.getValue();
                List<String> types = ((List<String>) valueObj);
                /** {@link com.boman.web.core.utils.ColumnUtils.packColCondition} 这里是拼参数的地方 **/
                Object value = types.get(0);
                String queryType = types.get(1);
                String columnType = types.get(2);
                wholeSql.append(key).append(covert(queryType, columnType, key, value)).append(" , ");
            }

            wholeSql = new StringBuilder(StringUtils.substringBeforeLast(wholeSql.toString(), " , "));
            packCondition(packColCondition, wholeSql);

            String sqlStr = wholeSql.toString();
            LOGGER.info("通用的更新sql语句为: {} \r\n 提交的数据为: {} \r\n 条件为: {}", sqlStr, packCommitData, packColCondition);
            return sqlStr;
        }

        public String moveData(Map<String, Object> para) {
            String idCard = (String) para.get("idCard");
            return "UPDATE vaccine_info set " +
                    "code = (SELECT 受种者编码 from ymjz where 身份证 = '" + idCard + "' limit 1)" +
                    ", work_unit = (SELECT 工作单位 from ymjz where 身份证 = '" + idCard + "' limit 1)" +
                    ", crowd_classification = (SELECT 人群分类 from ymjz where 身份证 = '" + idCard + "' limit 1) " +
                    "where id_card = '" + idCard + "'\n";
        }

        public String updateById(Map<String, Object> para) {
            String tableName = (String) para.get("tableName");
            JSONObject model = (JSONObject) para.get("model");
            String pkName = (String) para.get("pkName");
            Long[] ids = (Long[]) para.get("ids");
            if (StringUtils.isBlank(tableName)) {
                throw new IllegalArgumentException("tableName 无效");
            } else if (!model.isEmpty()) {
                keyToUpper(model);
                SQL sql = new SQL();
                sql.UPDATE(tableName);

                // 拼装set
                model.forEach((key, value)->{
                    if (!isReadOnly(key)) {
                        // 此处需要对value加一个""
                        sql.SET(key + " = \"" + value + "\"");
                    }
                });

                // 拼装in
                StringBuilder inSql = new StringBuilder();
                for (int i = 0; i < ids.length; ++i) {
                    inSql.append(String.format("#{ids[%d]}", i));
                    inSql.append(",");
                }

                sql.WHERE(pkName + " in (" + inSql.toString());
                String wholeSql = StringUtils.substringBeforeLast(sql.toString(), ",") + "))";
                LOGGER.info("更改的sql语句为: {}, \r\n 更改的数据为: {}", wholeSql, model);
                return wholeSql;
            } else {
                throw new IllegalArgumentException("model 无效");
            }
        }

        public String inserts(Map<String, Object> para) {
            String tableName = (String) para.get("tableName");
            JSONObject[] models = (JSONObject[]) ((JSONObject[]) para.get("models"));
            Consumer<JSONObject> processor = (Consumer) para.get("processor");
            if (isNullOrEmpty(tableName)) {
                throw new IllegalArgumentException("tableName 无效");
            } else if (models != null && models.length != 0) {
                Set<String> columns = new HashSet();

                for (int i = 0; i < models.length; ++i) {
                    JSONObject model = models[i];
                    if (model == null) {
                        models[i] = model = new JSONObject();
                    }

                    if (processor != null) {
                        processor.accept(model);
                    }

                    keyToUpper(model);
                    columns.addAll(model.keySet());
                }

                StringBuffer sql = new StringBuffer();
                sql.append("INSERT INTO ");
                sql.append(tableName);
                sql.append("(");
                sql.append(String.join(",", columns));
                sql.append(") VALUES");

                for (int i = 0; i < models.length; ++i) {
                    sql.append("(");

                    for (Iterator var8 = columns.iterator(); var8.hasNext(); sql.append(",")) {
                        String column = (String) var8.next();
                        if (models[i].containsKey(column)) {
                            sql.append(String.format("#{models[%d].%s}", i, column));
                        } else {
                            sql.append("default");
                        }
                    }

                    sql.setCharAt(sql.length() - 1, ')');
                    sql.append(",");
                }

                sql.deleteCharAt(sql.length() - 1);
                return sql.toString();
            } else {
                throw new IllegalArgumentException("model 无效");
            }
        }

        public String insert(Map<String, Object> para) {
            JSONObject model = (JSONObject) para.get("model");
            String tableName = (String) para.get("tableName");
            if (isNullOrEmpty(tableName)) {
                throw new IllegalArgumentException("tableName 无效");
            } else if (isNullOrEmpty(model)) {
                throw new IllegalArgumentException("model 无效");
            } else {
                SQL sql = new SQL();
                Set<String> keySet = model.keySet();
                sql.INSERT_INTO(tableName);

                for (int i = 0; i < model.size(); ++i) {
                    String key = (String) keySet.toArray()[i];
                    sql.VALUES(key, "#{model." + key + "}");
                }

                String sqlStr = sql.toString();
                LOGGER.info("新增的sql语句为: {}, \r\n 新增的数据为: {}", sqlStr, model);
                return sqlStr;
            }
        }


        public String updateByIdList(Map<String, Object> para) {
            String tableName = (String) para.get("tableName");
            String pkName = (String) para.get("pkName");
            List<Long> idList = (List<Long>) para.get("idList");
            JSONObject models = (JSONObject) para.get("model");

            StringBuilder wholeSql = new StringBuilder();
            wholeSql.append("update ").append(tableName).append(" set ");
            for (Map.Entry<String, Object> entry : models.entrySet()) {
                String key = entry.getKey();
                Object value = entry.getValue();
                wholeSql.append(key).append(" = ").append(value).append(" , ");
            }

            wholeSql = new StringBuilder(StringUtils.substringBeforeLast(wholeSql.toString(), ","));
            wholeSql.append(" where ").append(pkName).append(" in ( ");

            for (int i = 0; i < idList.size(); ++i) {
                wholeSql.append(String.format("#{idList[%d]}", i));
                wholeSql.append(",");
            }

            wholeSql.setCharAt(wholeSql.length() - 1, ')');
            String sqlStr = wholeSql.toString();
            LOGGER.info("批量更新的sql语句为: {}, \r\n 更改的数据为: {}, \r\n idList: {}", sqlStr, models, idList);
            return sqlStr;

        }

        public String delete(Map<String, Object> para) {
            Long[] ids = (Long[]) para.get("ids");
            String tableName = (String) para.get("tableName");
            String pkName = (String) para.get("pkName");
            if (isNullOrEmpty(tableName)) {
                throw new IllegalArgumentException("tableName 无效");
            } else if (ids == null) {
                throw new IllegalArgumentException("ids 无效");
            } else if (ids.length == 0) {
                return "";
            } else if (ids.length == 1) {
                return "DELETE FROM " + tableName + " where " + pkName + " = #{ids[0]}";
            } else {
                StringBuffer sql = new StringBuffer();
                sql.append("DELETE FROM ");
                sql.append(tableName);
                sql.append(" WHERE ");
                sql.append(pkName + " in (");

                for (int i = 0; i < ids.length; ++i) {
                    sql.append(String.format("#{ids[%d]}", i));
                    sql.append(",");
                }

                sql.setCharAt(sql.length() - 1, ')');
                String sqlStr = sql.toString();
                LOGGER.info("删除的sql语句为: {}, \r\n idList: {}", sqlStr, ids);
                return sqlStr;
            }
        }

        public String updates(Map<String, Object> para) {
            String tableName = (String) para.get("tableName");
            Collection<Object> models = (Collection) para.get("models");
            Consumer<JSONObject> processor = (Consumer) para.get("processor");
            Boolean first = true;
            if (isNullOrEmpty(tableName)) {
                throw new IllegalArgumentException("tableName 无效");
            } else if (models != null && models.size() != 0) {
                JSONObject columnall = new JSONObject(true);
                Iterator var7 = models.iterator();

                while (var7.hasNext()) {
                    Object obj = var7.next();
                    JSONObject columnpart = (JSONObject) obj;
                    if (columnpart == null) {
                        columnpart = new JSONObject(true);
                    }

                    if (processor != null) {
                        processor.accept(columnpart);
                    }

                    keyToUpper(columnpart);
                    columnall.putAll(columnpart);
                }

                JSONObject clonekeyobj = (JSONObject) columnall.clone();
                Set<String> keys = columnall.keySet();
                Iterator var19 = keys.iterator();

                while (var19.hasNext()) {
                    String column = (String) var19.next();
                    if (isReadOnly(column)) {
                        clonekeyobj.remove(column);
                    }
                }

                Set<String> firstkeys = clonekeyobj.keySet();
                StringBuffer sql = new StringBuffer("");
                sql.append("UPDATE ").append(tableName).append(" a");
                sql.append(" right join (");
                int i = -1;
                Iterator var12 = models.iterator();

                while (true) {
                    while (var12.hasNext()) {
                        Object obj = var12.next();
                        ++i;
                        JSONObject model = (JSONObject) obj;
                        Iterator var15;
                        String key;
                        if (first.booleanValue()) {
                            sql.append(" SELECT #{models[0].ID} `ID`,");
                            var15 = firstkeys.iterator();

                            while (var15.hasNext()) {
                                key = (String) var15.next();
                                if (model.get(key) == null) {
                                    model.put(key, (Object) null);
                                }

                                sql.append(String.format("#{models[%d].%s} ", i, key));
                                sql.append("`").append(key).append("`").append(",");
                            }

                            sql.deleteCharAt(sql.length() - 1);
                            if (models.size() > 0) {
                                sql.append(" union all");
                            }

                            first = false;
                        } else {
                            sql.append(" SELECT ");
                            sql.append(String.format("#{models[%d].%s} ", i, "ID")).append(",");
                            var15 = firstkeys.iterator();

                            while (var15.hasNext()) {
                                key = (String) var15.next();
                                if (model.get(key) == null) {
                                    model.put(key, (Object) null);
                                }

                                sql.append(String.format("#{models[%d].%s} ", i, key));
                                sql.append(",");
                            }

                            sql.deleteCharAt(sql.length() - 1);
                            if (i < models.size() - 1) {
                                sql.append(" union all");
                            }
                        }
                    }

                    sql.append(") b on a.ID=b.ID ");
                    sql.append(" SET ");
                    var12 = firstkeys.iterator();

                    while (var12.hasNext()) {
                        String value = (String) var12.next();
                        sql.append(" a.").append(value).append("=").append("IFNULL(b.").append(value).append(",").append("a.").append(value).append(")").append(",");
                    }

                    sql.deleteCharAt(sql.length() - 1);
                    String sqlStr = sql.toString();
                    LOGGER.info("更新的sql语句为: {}", sqlStr);
                    return sqlStr;
                }
            } else {
                throw new IllegalArgumentException("model 无效");
            }
        }

        public String selectByCondition(Map<String, Object> para) {
            JSONObject condition = (JSONObject) para.get("condition");
            JSONObject packCondition = (JSONObject) para.get("packCondition");
            String tableName = (String) para.get("tableName");
            String orderBy = (String) para.get("orderBy");
            int limit = (int) para.get("limit");
            int offset = (int) para.get("offset");
            List<String> showData = (List<String>) para.get("showData");

            StringBuilder wholeSql = new StringBuilder();
            wholeSql.append("select ");
            // showData
            StringBuilder showDataSql = new StringBuilder();
            // 调用之前进行了判空，showData肯定不为空
            for (Object columnObj : showData) {
                String columnName = (String) columnObj;
                showDataSql.append(columnName).append(", ");
            }
            wholeSql.append(StringUtils.substringBeforeLast(showDataSql.toString(), ","));
//
            wholeSql.append(" from ").append(tableName);
            // 条件
            packCondition(packCondition, wholeSql);

            wholeSql.append(" order by ").append(orderBy).append(" limit ").append(limit);
            if (isNotEmpty(offset)) {
                wholeSql.append(", ").append(offset);
            }

            String result = wholeSql.toString();
            LOGGER.info("查询拼出的sql语句为：{}, \r\n selectByCondition 查询条件: {}", result, packCondition);
            return result;
        }

        public String getByMap(Map<String, Object> para) {
            JSONObject condition = (JSONObject) para.get("condition");
            JSONObject packCondition = (JSONObject) para.get("packCondition");
            String tableName = (String) para.get("tableName");
            boolean limitOne = (boolean) para.get("limitOne");

            String result;
            StringBuilder wholeSql = new StringBuilder();
            wholeSql.append("select * from ").append(tableName);
            if (isEmpty(condition)) {
                result = wholeSql.toString();
            } else {
                // 条件
                packCondition(packCondition, wholeSql);
                result = wholeSql.toString();
            }

            result = limitOne ? result + " limit 1" : result;
            LOGGER.info("查询拼出的sql语句为：{}, \r\n getByMap 查询条件: {}", result, condition);
            return result;
        }

        public String selectByIdList(Map<String, Object> para) {
            String tableName = (String) para.get("tableName");
            String pkName = (String) para.get("pkName");
            List<Long> idList = (List<Long>) para.get(ID_LIST);
            List<String> showData = (List<String>) para.get("showData");

            StringBuilder wholeSql = new StringBuilder();
            wholeSql.append("select ");
            // showData
            StringBuilder showDataSql = new StringBuilder();
            if (isNotEmpty(showData)) {
                for (String columnName : showData) {
                    showDataSql.append(columnName).append(", ");
                }
                wholeSql.append(StringUtils.substringBeforeLast(showDataSql.toString(), ","));
            } else {
                showDataSql.append(" * ");
            }

            wholeSql.append(" from ").append(tableName).append(" where ").append(pkName).append(" in ( ");

            for (int i = 0; i < idList.size(); ++i) {
                wholeSql.append(String.format("#{idList[%d]}", i));
                wholeSql.append(",");
            }

            wholeSql.setCharAt(wholeSql.length() - 1, ')');
            String sqlStr = wholeSql.toString();
            LOGGER.info("查询拼出的sql语句为：{}, \r\n selectByIdList idList: {}", sqlStr, idList);
            return sqlStr;
        }

        public String countByCondition(Map<String, Object> para) {
            JSONObject condition = (JSONObject) para.get("condition");
            JSONObject packCondition = (JSONObject) para.get("packCondition");
            String tableName = (String) para.get("tableName");

            StringBuilder wholeSql = new StringBuilder();
            wholeSql.append("select count(1)");
            wholeSql.append(" from ").append(tableName);
            // 条件
            packCondition(packCondition, wholeSql);

            String result = wholeSql.toString();
            LOGGER.info("查询count拼出的sql语句为：{}, \r\n countByCondition 查询条件: {}", result, packCondition);
            return result;
        }

        public String selectById(Map<String, Object> params) {
            String tableName = (String) params.get("tableName");
            String pkName = (String) params.get("pkName");
            Long id = (Long) params.get("id");
            String other = (String)params.get("other");
            StringBuilder sqlBuilder = new StringBuilder();
            if(StringUtils.isEmpty(other)) {
                sqlBuilder.append("select * from ")
                        .append(tableName).append(" where ")
                        .append(pkName).append(" = ")
                        .append(""+ id +"").append(" limit 1");
            }else if(other.equals("leave")) {
                sqlBuilder.append("select t.*,u.nick_name  from ")
                        .append(tableName).append(" t ").append(" JOIN sys_user u ON u.user_name = t.leavefrom_user_name ")
                        .append(" where ")
                        .append("t.").append(pkName).append(" = ").append(""+ id +"").append(" limit 1");
            }
            return sqlBuilder.toString();
        }

        public String selectCandidatorsById(Map<String, Object> params) {
            String tableName = (String) params.get("tableName");
            String pkName = (String) params.get("pkName");
            List<Long> ids = (List<Long>) params.get("ids");
            int type = (Integer) params.get("type");

            // TODO 部门暂未定
            StringBuilder sqlBuilder = new StringBuilder();
            sqlBuilder.append("select id,user_name as name, ").append(type).append(" as type ").append(" from ")
                    .append(tableName).append(" t ")
                    .append(" where ")
                    .append("t.").append(pkName).append(" in ").append("(");

            for(int i = 0;i < ids.size();i++) {
                if(i < ids.size() - 1) {
                    sqlBuilder.append(ids.get(i)).append(",");
                }else {
                    sqlBuilder.append(ids.get(i));
                }
            }

            sqlBuilder.append(")");
            return sqlBuilder.toString();
        }

        public String sumBeforeTempLeaveTime(Map<String, Object> params) {
            String username = (String) params.get("username");
            String startTime = (String) params.get("startTime");
            String endTime = (String) params.get("endTime");
            List<Long> idList = (List<Long>) params.get("idList");

            String sql = String.format("select sum(leavefrom_time) from boman_temp_leaveform where leavefrom_user_name = '%s' and " +
                            "leavefrom_start_time >= '%s' and leave_status = 'Y' and leavefrom_end_time <= '%s' and id not in (%s)"
                    , username, startTime, endTime, ColumnUtils.joinList1(idList));
            LOGGER.info("查找总销假时长sql：{}", sql);
            return sql;
        }

        /**
         * 功能描述: 判断传过来的值是否需要转义
         *
         * @param packCondition 封装的条件
         * @param wholeSql      sql
         */
        private void packCondition(JSONObject packCondition, StringBuilder wholeSql) {
            if (isEmpty(packCondition)) {
                return;
            }

            wholeSql.append(" where ");
            StringBuilder conditionSql = new StringBuilder();
            for (Map.Entry<String, Object> entry : packCondition.entrySet()) {
                String key = entry.getKey();
                Object valueObj = entry.getValue();
                List<String> types = ((List<String>) valueObj);
                /** {@link com.boman.web.core.utils.ColumnUtils.packColCondition} 这里是拼参数的地方 **/
                Object value = types.get(0);
                String queryType = types.get(1);
                String columnType = types.get(2);
                conditionSql.append(key).append(covert(queryType, columnType, key, value)).append(" and ");
            }

            wholeSql.append(StringUtils.substringBeforeLast(conditionSql.toString(), " and"));
        }

        /**
         * 功能描述: 仅此用来拼装查询条件，不做他用
         *
         * @param queryType  like > < =
         * @param columnType varchar char textarea timestamp
         * @param key        key
         * @param valueObj   valueObj
         * @return java.lang.String
         */
        private String covert(String queryType, String columnType, String key, Object valueObj) {
            // false 不需要转义
            boolean needEscape = columnType.contains(VARCHAR) || columnType.contains(CHAR)
                    || columnType.contains(DATETIME) || columnType.contains(TIMESTAMP)|| columnType.contains(DATE);
            Object value;
            switch (queryType) {
                case EQ:
                    value = needEscape ? escapeStr(String.valueOf(valueObj)) : valueObj;
                    return " = " + value;
                case LIKE:
                    return " like concat('%', #{condition." + key + "}, '%')";
                case NE:
                    value = needEscape ? escapeStr(String.valueOf(valueObj)) : valueObj;
                    return " != " + value;
                case GT:
                    value = needEscape ? escapeStr(String.valueOf(valueObj)) : valueObj;
                    return " > " + value;
                case GTE:
                    value = needEscape ? escapeStr(String.valueOf(valueObj)) : valueObj;
                    return " >= " + value;
                case LT:
                    value = needEscape ? escapeStr(String.valueOf(valueObj)) : valueObj;
                    return " < " + value;
                case LTE:
                    value = needEscape ? escapeStr(String.valueOf(valueObj)) : valueObj;
                    return " <= " + value;
                default:
                    // in
                    List<Object> list = valueObj instanceof List ? ((List<Object>) valueObj) : Lists.newArrayList(valueObj);
                    return  " in (" + ColumnUtils.joinList(list) + ")";
            }
        }
    }
}