package com.cym.utils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import com.cym.bean.CreateTime;
import com.cym.bean.InitValue;
import com.cym.bean.Page;
import com.cym.bean.Sort;
import com.cym.bean.Update;
import com.cym.bean.UpdateTime;
import com.cym.reflection.ReflectionUtil;
import com.cym.reflection.SerializableFunction;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import jakarta.persistence.Id;

/**
 * sql操作器
 *
 */
@Service
public class JpaHelper {
	Logger logger = LoggerFactory.getLogger(this.getClass());

	@Autowired
	JdbcTemplate jdbcTemplate;

	@Value("${spring.datasource.url:}")
	String url;
	@Autowired
	SqlUtils sqlUtils;

	/**
	 * 获取主键
	 * 
	 * @param clazz
	 * @return
	 */
	public String getPrimalKey(Class<?> clazz) {

		Field[] fields = ReflectUtil.getFields(clazz);

		for (Field field : fields) {
			if (field.isAnnotationPresent(Id.class)) {
				return field.getName();
			}
		}

		return null;
	}

	/**
	 * 获取主键值
	 * 
	 * @param clazz
	 * @return
	 */
	public String getPrimalValue(Object object) {
		String key = getPrimalKey(object.getClass());

		if (StrUtil.isNotEmpty(key)) {
			Object obj = ReflectUtil.getFieldValue(object, key);
			return obj != null ? obj.toString() : null;
		}
		return null;
	}

	/**
	 * 累加某一个字段的数量,原子操作
	 * 
	 * @param object
	 */

	public <T, R> void addCountById(String id, SerializableFunction<T, R> property, Long count, Class<?> clazz) {
		addCountById(id, ReflectionUtil.getFieldName(property), count, clazz);
	}

	/**
	 * 累加某一个字段的数量,原子操作
	 * 
	 * @param object
	 */

	public void addCountById(String id, String property, Long count, Class<?> clazz) {
		String sql = "UPDATE `" + StrUtil.toUnderlineCase(clazz.getSimpleName()) + "` SET `" + StrUtil.toUnderlineCase(property) + "` = `" + StrUtil.toUnderlineCase(property)
				+ "` + ? WHERE `id` =  ?";
		Object[] params = new Object[] { count, id };
		sqlUtils.logQuery(sql, params);
		jdbcTemplate.update(buildSql(sql), params);
	}

	/**
	 * 累加某一个字段的数量,原子操作
	 * 
	 * @param object
	 */

	public <T, R> void addCountById(String id, SerializableFunction<T, R> property, Double count, Class<?> clazz) {
		addCountById(id, ReflectionUtil.getFieldName(property), count, clazz);
	}

	/**
	 * 累加某一个字段的数量,原子操作
	 * 
	 * @param object
	 */

	public void addCountById(String id, String property, Double count, Class<?> clazz) {
		String sql = "UPDATE `" + StrUtil.toUnderlineCase(clazz.getSimpleName()) + "` SET `" + StrUtil.toUnderlineCase(property) + "` = `" + StrUtil.toUnderlineCase(property)
				+ "` + ? WHERE `id` =  ?";
		Object[] params = new Object[] { count, id };
		sqlUtils.logQuery(sql, params);
		jdbcTemplate.update(buildSql(sql), params);
	}

	/**
	 * 插入或更新
	 * 
	 * @param object 对象 @throws
	 */

	public String insertOrUpdate(Object object) {
		Long time = System.currentTimeMillis();
		String id = getPrimalValue(object);
		if (StrUtil.isEmpty(id)) {
			// 插入
			// 设置插入时间
			setCreateTime(object, time);
			// 设置更新时间
			setUpdateTime(object, time);
			// 设置默认值
			setDefaultVaule(object);
			// 设置id
			ReflectUtil.setFieldValue(object, getPrimalKey(object.getClass()), SnowFlakeUtils.nextId());

			List<String> fieldsPart = new ArrayList<String>();
			List<String> placeHolder = new ArrayList<String>();
			List<Object> paramValues = new ArrayList<Object>();

			List<Field> fields = getFields(object.getClass());
			for (Field field : fields) {
				fieldsPart.add("`" + StrUtil.toUnderlineCase(field.getName()) + "`");
				placeHolder.add("?");
				paramValues.add(ReflectUtil.getFieldValue(object, field));
			}

			String sql = "INSERT INTO `" + StrUtil.toUnderlineCase(object.getClass().getSimpleName()) + "` (" + StrUtil.join(",", fieldsPart) + ") VALUES (" + StrUtil.join(",", placeHolder) + ")";
			sqlUtils.logQuery(sql, paramValues.toArray());
			jdbcTemplate.update(buildSql(sql), paramValues.toArray());

		} else {
			// 更新
			updateById(object);
		}

		// 返回id
		return getPrimalValue(object);
	}

	/**
	 * 插入
	 * 
	 * @param object 对象
	 */

	public String insert(Object object) {
		// 去除主键id
		ReflectUtil.setFieldValue(object, getPrimalKey(object.getClass()), null);

		// 插入数据库
		insertOrUpdate(object);

		// 返回id
		return getPrimalValue(object);
	}

	/**
	 * 插入全部字段
	 * 
	 * @param object 对象
	 */
	public String insertAllColumn(Object object) {
		// 没有id生成id
		String id = (String) ReflectUtil.getFieldValue(object, getPrimalKey(object.getClass()));
		if (StrUtil.isEmpty(id)) {
			id = SnowFlakeUtils.nextId().toString();
			ReflectUtil.setFieldValue(object, getPrimalKey(object.getClass()), id);
		}

		String sql = "";
		List<String> fieldsPart = new ArrayList<String>();
		List<String> placeHolder = new ArrayList<String>();
		List<Object> paramValues = new ArrayList<Object>();

		List<Field> fields = getFields(object.getClass());
		for (Field field : fields) {
			fieldsPart.add("`" + StrUtil.toUnderlineCase(field.getName()) + "`");
			placeHolder.add("?");
			paramValues.add(ReflectUtil.getFieldValue(object, field));
		}

		sql = "INSERT INTO `" + StrUtil.toUnderlineCase(object.getClass().getSimpleName()) + "` (" + StrUtil.join(",", fieldsPart) + ") VALUES (" + StrUtil.join(",", placeHolder) + ")";
		sqlUtils.logQuery(sql, paramValues.toArray());
		jdbcTemplate.update(buildSql(sql), paramValues.toArray());

		// 返回id
		return getPrimalValue(object);
	}

	/**
	 * 批量插入
	 * 
	 * @param object 对象
	 */
	public List<String> insertBatch(List<?> objectList) {
		if (objectList == null || objectList.size() == 0) {
			return new ArrayList<>();
		}
		Long time = System.currentTimeMillis();
		List<String> ids = new ArrayList<>();
		List<Object[]> paramValues = new ArrayList<Object[]>();

		String sql = null;
		for (Object object : objectList) {
			// 设置插入时间
			setCreateTime(object, time);
			// 设置更新时间
			setUpdateTime(object, time);
			// 设置默认值
			setDefaultVaule(object);

			// 没有id生成id
			String id = (String) ReflectUtil.getFieldValue(object, getPrimalKey(object.getClass()));
			if (StrUtil.isEmpty(id)) {
				id = SnowFlakeUtils.nextId().toString();
				ReflectUtil.setFieldValue(object, getPrimalKey(object.getClass()), id);
			}
			ids.add(id);

			List<String> fieldsPart = new ArrayList<String>();
			List<String> placeHolder = new ArrayList<String>();
			List<Object> objs = new ArrayList<>();

			List<Field> fields = getFields(object.getClass());
			for (Field field : fields) {
				fieldsPart.add("`" + StrUtil.toUnderlineCase(field.getName()) + "`");
				placeHolder.add("?");
				objs.add(ReflectUtil.getFieldValue(object, field));
			}
			paramValues.add(objs.toArray());

			if (sql == null) {
				sql = "INSERT INTO `" + StrUtil.toUnderlineCase(object.getClass().getSimpleName()) + "` (" + StrUtil.join(",", fieldsPart) + ") VALUES (" + StrUtil.join(",", placeHolder) + ")";
			}

			sqlUtils.logQuery(sql, objs.toArray());
		}

		jdbcTemplate.batchUpdate(buildSql(sql), paramValues);
		// 返回id
		return ids;
	}

	/**
	 * 根据id更新
	 * 
	 * @param object 对象
	 */

	public void updateById(Object object) {
		if (StrUtil.isEmpty(getPrimalValue(object))) {
			return;
		}
		// 设置更新时间
		setUpdateTime(object, System.currentTimeMillis());

		List<Field> fields = getFields(object.getClass());

		List<String> fieldsPart = new ArrayList<String>();
		List<Object> paramValues = new ArrayList<Object>();

		for (Field field : fields) {
			if (!field.getName().equals(getPrimalKey(object.getClass())) && ReflectUtil.getFieldValue(object, field) != null) {
				fieldsPart.add("`" + StrUtil.toUnderlineCase(field.getName()) + "`=?");
				paramValues.add(ReflectUtil.getFieldValue(object, field));
			}
		}
		paramValues.add(getPrimalValue(object));
		if (fieldsPart.size() == 0) {
			return;
		}
		String sql = "UPDATE `" + StrUtil.toUnderlineCase(object.getClass().getSimpleName()) + "` SET " + StrUtil.join(",", fieldsPart) + " WHERE id = ?";
		sqlUtils.logQuery(sql, paramValues.toArray());
		jdbcTemplate.update(buildSql(sql), paramValues.toArray());
	}

	/**
	 * 根据id更新全部字段
	 * 
	 * @param object 对象
	 */

	public void updateAllColumnById(Object object) {
		if (StrUtil.isEmpty(getPrimalValue(object))) {
			return;
		}

		List<Field> fields = getFields(object.getClass());

		List<String> fieldsPart = new ArrayList<String>();
		List<Object> paramValues = new ArrayList<Object>();

		for (Field field : fields) {
			if (!field.getName().equals(getPrimalKey(object.getClass()))) {
				fieldsPart.add("`" + StrUtil.toUnderlineCase(field.getName()) + "`=?");
				paramValues.add(ReflectUtil.getFieldValue(object, field));
			}
		}
		paramValues.add(getPrimalValue(object));

		String sql = "UPDATE `" + StrUtil.toUnderlineCase(object.getClass().getSimpleName()) + "` SET " + StrUtil.join(",", fieldsPart) + " WHERE id = ?";
		sqlUtils.logQuery(sql, paramValues.toArray());
		jdbcTemplate.update(buildSql(sql), paramValues.toArray());
	}

	/**
	 * 条件更新
	 * 
	 * @param conditionAndWrapper
	 * @param update
	 * @param clazz
	 */

	public void updateByQuery(ConditionWrapper conditionWrapper, Update update, Class<?> clazz) {
		if (update == null || update.getSets().size() == 0) {
			return;
		}

		List<String> fieldsPart = new ArrayList<String>();
		List<Object> values = new ArrayList<Object>();
		for (Entry<String, Object> entry : update.getSets().entrySet()) {
			fieldsPart.add("`" + StrUtil.toUnderlineCase(entry.getKey()) + "`=?");
			values.add(entry.getValue());
		}

		String sql = "UPDATE `" + StrUtil.toUnderlineCase(clazz.getSimpleName()) + "` SET " + StrUtil.join(",", fieldsPart);
		if (conditionWrapper != null && conditionWrapper.notEmpty()) {
			sql += " WHERE " + conditionWrapper.build(values);
		}
		sqlUtils.logQuery(sql, values.toArray());
		jdbcTemplate.update(buildSql(sql), values.toArray());
	}

	/**
	 * 根据id删除
	 * 
	 * @param id    对象
	 * @param clazz 类
	 */

	public void deleteById(String id, Class<?> clazz) {
		if (StrUtil.isEmpty(id)) {
			return;
		}

		deleteByQuery(new ConditionAndWrapper().eq(getPrimalKey(clazz), id), clazz);
	}

	/**
	 * 根据id删除
	 * 
	 * @param id    对象
	 * @param clazz 类
	 */

	public void deleteByIds(Collection<String> ids, Class<?> clazz) {
		if (ids == null || ids.size() == 0) {
			return;
		}
		deleteByQuery(new ConditionAndWrapper().in(getPrimalKey(clazz), ids), clazz);
	}

	/**
	 * 根据id删除
	 * 
	 * @param id    对象
	 * @param clazz 类
	 */

	public void deleteByIds(String[] ids, Class<?> clazz) {
		deleteByQuery(new ConditionAndWrapper().in(getPrimalKey(clazz), ids), clazz);
	}

	/**
	 * 根据条件删除
	 * 
	 * @param query 查询
	 * @param clazz 类
	 */

	public void deleteByQuery(ConditionWrapper conditionWrapper, Class<?> clazz) {

		List<Object> values = new ArrayList<Object>();
		String sql = "DELETE FROM `" + StrUtil.toUnderlineCase(clazz.getSimpleName()) + "`";
		if (conditionWrapper != null && conditionWrapper.notEmpty()) {
			sql += " WHERE " + conditionWrapper.build(values);
		}
		sqlUtils.logQuery(sql, values.toArray());
		jdbcTemplate.update(buildSql(sql), values.toArray());
	}

	/**
	 * 设置默认值
	 * 
	 * @param object 对象
	 */
	public void setDefaultVaule(Object object) {
		List<Field> fields = getFields(object.getClass());
		for (Field field : fields) {
			// 获取注解
			if (field.isAnnotationPresent(InitValue.class)) {
				InitValue defaultValue = field.getAnnotation(InitValue.class);

				String value = defaultValue.value();

				if (ReflectUtil.getFieldValue(object, field) == null) {
					// 获取字段类型
					Class<?> type = field.getType();
					if (type.equals(String.class)) {
						ReflectUtil.setFieldValue(object, field, value);
					}
					if (type.equals(Short.class)) {
						ReflectUtil.setFieldValue(object, field, Short.parseShort(value));
					}
					if (type.equals(Integer.class)) {
						ReflectUtil.setFieldValue(object, field, Integer.parseInt(value));
					}
					if (type.equals(Long.class)) {
						ReflectUtil.setFieldValue(object, field, Long.parseLong(value));
					}
					if (type.equals(Float.class)) {
						ReflectUtil.setFieldValue(object, field, Float.parseFloat(value));
					}
					if (type.equals(Double.class)) {
						ReflectUtil.setFieldValue(object, field, Double.parseDouble(value));
					}
					if (type.equals(Boolean.class)) {
						ReflectUtil.setFieldValue(object, field, Boolean.parseBoolean(value));
					}
				}
			}
		}
	}

	/**
	 * 设置更新时间
	 * 
	 * @param object 对象
	 */
	public void setUpdateTime(Object object, Long time) {
		List<Field> fields = getFields(object.getClass());
		for (Field field : fields) {
			// 获取注解
			if (field.isAnnotationPresent(UpdateTime.class) && field.getType().equals(Long.class)) {
				ReflectUtil.setFieldValue(object, field, time);
			}
		}
	}

	/**
	 * 设置创建时间
	 * 
	 * @param object 对象
	 */
	public void setCreateTime(Object object, Long time) {
		List<Field> fields = getFields(object.getClass());
		for (Field field : fields) {
			// 获取注解
			if (field.isAnnotationPresent(CreateTime.class) && field.getType().equals(Long.class)) {
				ReflectUtil.setFieldValue(object, field, time);
			}
		}
	}

	/**
	 * 按查询条件获取Page
	 * 
	 * @param query 查询
	 * @param page  分页
	 * @param clazz 类
	 * @return Page 分页
	 */
	public <T> Page<T> findPageByQuery(ConditionWrapper conditionWrapper, Sort sort, Page page, Class<T> clazz) {
		List<Object> values = new ArrayList<Object>();
		// 查询出一共的条数
		Long count = findCountByQuery(conditionWrapper, clazz);

		String sql = "SELECT * FROM `" + StrUtil.toUnderlineCase(clazz.getSimpleName()) + "`";
		if (conditionWrapper != null && conditionWrapper.notEmpty()) {
			sql += " WHERE " + conditionWrapper.build(values);
		}
		if (sort != null && sort.getOrderList().size() > 0) {
			sql += " " + sort.toString();
		} else {
			sql += " ORDER BY " + getPrimalKey(clazz) + " DESC";
		}

		sql += buildLimit(page);

		Page<T> pageResp = new Page<>();
		pageResp.setPageSize(page.getPageSize());
		pageResp.setPageNum(page.getPageNum());
		pageResp.setTotal(count);

		pageResp.setStartRow((page.getPageNum() - 1) * page.getPageNum() + 1);
		pageResp.setEndRow(pageResp.getStartRow() + page.getPageSize() - 1);
		pageResp.setPages((count.intValue() + page.getPageSize() - 1) / page.getPageSize());

		sqlUtils.logQuery(sql, values.toArray());
		pageResp.setList(buildObjects(jdbcTemplate.queryForList(buildSql(sql), values.toArray()), clazz));

		return pageResp;
	}

	/**
	 * 按查询条件获取Page
	 * 
	 * @param query 查询
	 * @param page  分页
	 * @param clazz 类
	 * @return Page 分页
	 */
	public <T> Page<T> findPageByQuery(Sort sort, Page page, Class<T> clazz) {
		return findPageByQuery(null, sort, page, clazz);
	}

	/**
	 * 按查询条件获取Page
	 * 
	 * @param <T>
	 * 
	 * @param query 查询
	 * @param page  分页
	 * @param clazz 类
	 * @return Page 分页
	 */
	public <T> Page<T> findPageByQuery(ConditionWrapper conditionWrapper, Page page, Class<T> clazz) {
		return findPageByQuery(conditionWrapper, null, page, clazz);
	}

	/**
	 * 按查询条件获取Page
	 * 
	 * @param query 查询
	 * @param page  分页
	 * @param clazz 类
	 * @return Page 分页
	 */
	public <T> Page<T> findPageByQuery(Page page, Class<T> clazz) {
		return findPageByQuery(null, null, page, clazz);
	}

	/**
	 * 根据id查找
	 * 
	 * @param id    id
	 * @param clazz 类
	 * @return T 对象
	 */
	public <T> T findById(String id, Class<T> clazz) {
		if (StrUtil.isEmpty(id)) {
			return null;
		}

		return findOneByQuery(new ConditionAndWrapper().eq(getPrimalKey(clazz), id), clazz);

	}

	/**
	 * 根据条件查找单个
	 * 
	 * @param query 查询
	 * @param clazz 类
	 * @return T 对象
	 */
	public <T> T findOneByQuery(ConditionWrapper conditionWrapper, Sort sort, Class<T> clazz) {

		Page page = new Page();
		page.setPageSize(1);
		page.setPageNum(1);
		Page<T> pageResp = findPageByQuery(conditionWrapper, sort, page, clazz);

		if (pageResp.getList().size() > 0) {
			return pageResp.getList().get(0);

		}
		return null;
	}

	/**
	 * 根据条件查找单个
	 * 
	 * @param query 查询
	 * @param clazz 类
	 * @return T 对象
	 */
	public <T> T findOneByQuery(Sort sort, Class<T> clazz) {
		return findOneByQuery(null, sort, clazz);
	}

	/**
	 * 根据条件查找单个
	 * 
	 * @param <T>       类型
	 * @param condition
	 * @param clazz     类
	 * @return T 对象
	 */
	public <T> T findOneByQuery(ConditionWrapper conditionWrapper, Class<T> clazz) {
		return findOneByQuery(conditionWrapper, null, clazz);

	}

	/**
	 * 根据条件查找List
	 * 
	 * @param <T>   类型
	 * @param query 查询
	 * @param clazz 类
	 * @return List 列表
	 */
	public <T> List<T> findListByQuery(ConditionWrapper conditionWrapper, Sort sort, Class<T> clazz) {
		List<Object> values = new ArrayList<Object>();

		String sql = "SELECT * FROM `" + StrUtil.toUnderlineCase(clazz.getSimpleName()) + "`";
		if (conditionWrapper != null && conditionWrapper.notEmpty()) {
			sql += " WHERE " + conditionWrapper.build(values);
		}
		if (sort != null) {
			sql += " " + sort.toString();
		} else {
			sql += " ORDER BY `" + getPrimalKey(clazz) + "` DESC";
		}
		sqlUtils.logQuery(sql, values.toArray());
		return buildObjects(jdbcTemplate.queryForList(buildSql(sql), values.toArray()), clazz);
	}

	/**
	 * 根据条件查找List
	 * 
	 * @param <T>       类型
	 * @param condition 查询
	 * @param clazz     类
	 * @return List 列表
	 */
	public <T> List<T> findListByQuery(ConditionWrapper conditionWrapper, Class<T> clazz) {
		return (List<T>) findListByQuery(conditionWrapper, null, clazz);
	}

	/**
	 * 根据条件查找List
	 * 
	 * @param <T>       类型
	 * @param condition 查询
	 * @param clazz     类
	 * @return List 列表
	 */
	public <T> List<T> findListByQuery(Sort sort, Class<T> clazz) {
		return (List<T>) findListByQuery(null, sort, clazz);
	}

	/**
	 * 根据条件查找某个属性
	 * 
	 * @param <T>           类型
	 * @param query         查询
	 * @param clazz         类
	 * @param property      属性
	 * @param propertyClass 属性类
	 * @return List 列表
	 */
	public <T> List<T> findPropertiesByQuery(ConditionWrapper conditionWrapper, Class<?> clazz, String property, Class<T> propertyClass) {
		List<?> list = findListByQuery(conditionWrapper, clazz);
		List<T> propertyList = extractProperty(list, property, propertyClass);

		return propertyList;
	}

	/**
	 * 根据条件查找某个属性
	 * 
	 * @param <T>           类型
	 * @param query         查询
	 * @param clazz         类
	 * @param property      属性
	 * @param propertyClass 属性类
	 * @return List 列表
	 */
	public <T, R> List<T> findPropertiesByQuery(ConditionWrapper conditionWrapper, Class<?> clazz, SerializableFunction<T, R> property, Class<T> propertyClass) {
		return findPropertiesByQuery(conditionWrapper, clazz, ReflectionUtil.getFieldName(property), propertyClass);
	}

	/**
	 * 根据条件查找某个属性
	 * 
	 * @param <T>       类型
	 * @param condition 查询
	 * @param clazz     类
	 * @param property  属性
	 * @return List 列表
	 */
	public List<String> findPropertiesByQuery(ConditionWrapper conditionWrapper, Class<?> clazz, String property) {
		return findPropertiesByQuery(conditionWrapper, clazz, property, String.class);
	}

	/**
	 * 根据条件查找某个属性
	 * 
	 * @param <T>       类型
	 * @param condition 查询
	 * @param clazz     类
	 * @param property  属性
	 * @return List 列表
	 */
	public <T, R> List<String> findPropertiesByQuery(ConditionWrapper conditionWrapper, Class<?> clazz, SerializableFunction<T, R> property) {
		return findPropertiesByQuery(conditionWrapper, clazz, ReflectionUtil.getFieldName(property), String.class);
	}

	/**
	 * 根据id查找某个属性
	 * 
	 * @param <T>       类型
	 * @param condition 查询
	 * @param clazz     类
	 * @param property  属性
	 * @return List 列表
	 */
	public List<String> findPropertiesByIds(Collection<String> ids, Class<?> clazz, String property) {
		if (ids == null || ids.size() == 0) {
			return new ArrayList<String>();
		}

		ConditionAndWrapper ConditionAndWrapper = new ConditionAndWrapper();
		ConditionAndWrapper.in(getPrimalKey(clazz), ids);

		return findPropertiesByQuery(ConditionAndWrapper, clazz, property, String.class);
	}

	/**
	 * 根据id查找某个属性
	 * 
	 * @param <T>       类型
	 * @param condition 查询
	 * @param clazz     类
	 * @param property  属性
	 * @return List 列表
	 */
	public <T, R> List<String> findPropertiesByIds(Collection<String> ids, Class<?> clazz, SerializableFunction<T, R> property) {
		return findPropertiesByIds(ids, clazz, ReflectionUtil.getFieldName(property));
	}

	/**
	 * 根据id查找某个属性
	 * 
	 * @param <T>       类型
	 * @param condition 查询
	 * @param clazz     类
	 * @param property  属性
	 * @return List 列表
	 */
	public List<String> findPropertiesByIds(String[] ids, Class<?> clazz, String property) {
		return findPropertiesByIds(Arrays.asList(ids), clazz, property);
	}

	/**
	 * 根据id查找某个属性
	 * 
	 * @param <T>       类型
	 * @param condition 查询
	 * @param clazz     类
	 * @param property  属性
	 * @return List 列表
	 */
	public <T, R> List<String> findPropertiesByIds(String[] ids, Class<?> clazz, SerializableFunction<T, R> property) {
		return findPropertiesByIds(Arrays.asList(ids), clazz, ReflectionUtil.getFieldName(property));
	}

	/**
	 * 根据条件查找id
	 * 
	 * @param query 查询
	 * @param clazz 类
	 * @return List 列表
	 */
	public List<String> findIdsByQuery(ConditionWrapper conditionWrapper, Class<?> clazz) {

		return findPropertiesByQuery(conditionWrapper, clazz, getPrimalKey(clazz));
	}

	/**
	 * 根据id集合查找
	 * 
	 * @param List  ids id集合
	 * @param clazz 类
	 * @return List 列表
	 */
	public <T> List<T> findListByIds(Collection<String> ids, Class<T> clazz) {
		return findListByIds(ids, null, clazz);
	}

	/**
	 * 根据id集合查找
	 * 
	 * @param List  ids id集合
	 * @param clazz 类
	 * @return List 列表
	 */
	public <T> List<T> findListByIds(String[] ids, Class<T> clazz) {
		return findListByIds(Arrays.asList(ids), null, clazz);
	}

	/**
	 * 根据id集合查找
	 * 
	 * @param List  ids id集合
	 * @param clazz 类
	 * @return List 列表
	 */
	public <T> List<T> findListByIds(Collection<String> ids, Sort sort, Class<T> clazz) {
		if (ids == null || ids.size() == 0) {
			return new ArrayList<T>();
		}

		ConditionAndWrapper ConditionAndWrapper = new ConditionAndWrapper();
		ConditionAndWrapper.in(getPrimalKey(clazz), ids);

		return findListByQuery(ConditionAndWrapper, sort, clazz);
	}

	/**
	 * 根据id集合查找
	 * 
	 * @param List  ids id集合
	 * @param clazz 类
	 * @return List 列表
	 */
	public <T> List<T> findListByIds(String[] ids, Sort sort, Class<T> clazz) {
		return findListByIds(Arrays.asList(ids), sort, clazz);
	}

	/**
	 * 查询全部
	 * 
	 * @param <T>   类型
	 * @param clazz 类
	 * @return List 列表
	 */
	public <T> List<T> findAll(Class<T> clazz) {
		return findAll(null, clazz);
	}

	/**
	 * 查询全部
	 * 
	 * @param <T>   类型
	 * @param clazz 类
	 * @return List 列表
	 */
	public <T> List<T> findAll(Sort sort, Class<T> clazz) {
		return findListByQuery(null, sort, clazz);
	}

	/**
	 * 查找全部的id
	 * 
	 * @param clazz 类
	 * @return List 列表
	 */
	public List<String> findAllIds(Class<?> clazz) {
		return findIdsByQuery(null, clazz);
	}

	/**
	 * 查找数量
	 * 
	 * @param condition 查询
	 * @param clazz     类
	 * @return Long 数量
	 */
	public Long findCountByQuery(ConditionWrapper conditionWrapper, Class<?> clazz) {
		List<Object> values = new ArrayList<Object>();
		String sql = "SELECT COUNT(*) FROM `" + StrUtil.toUnderlineCase(clazz.getSimpleName()) + "`";
		if (conditionWrapper != null && conditionWrapper.notEmpty()) {
			sql += " WHERE " + conditionWrapper.build(values);
		}
		sqlUtils.logQuery(sql, values.toArray());
		return jdbcTemplate.queryForObject(buildSql(sql), Long.class, values.toArray());
	}

	/**
	 * 查找全部数量
	 * 
	 * @param clazz 类
	 * @return Long 数量
	 */
	public Long findAllCount(Class<?> clazz) {
		return findCountByQuery(null, clazz);
	}

	/**
	 * 获取list中对象某个属性,组成新的list
	 * 
	 * @param list     列表
	 * @param clazz    类
	 * @param property 属性
	 * @return List<T> 列表
	 */
	public <T> List<T> extractProperty(List<?> list, String property, Class<T> clazz) {
		Set<T> rs = new HashSet<T>();
		for (Object object : list) {
			Object value = ReflectUtil.getFieldValue(object, property);
			if (value != null && value.getClass().equals(clazz)) {
				rs.add((T) value);
			}
		}

		return new ArrayList<T>(rs);
	}

	/**
	 * Map转Bean
	 * 
	 * @param <T>
	 * @param queryForList
	 * @param clazz
	 * @return
	 */
	public <T> List<T> buildObjects(List<Map<String, Object>> queryForList, Class<T> clazz) {
		List<T> list = new ArrayList<T>();
		try {
			Field[] fields = ReflectUtil.getFields(clazz);

			for (Map<String, Object> map : queryForList) {
				Object obj = clazz.getDeclaredConstructor().newInstance();

				for (Map.Entry<String, Object> entry : map.entrySet()) {
					String mapKey = entry.getKey();
					Object mapValue = entry.getValue();

					for (Field field : fields) {
						if (StrUtil.toUnderlineCase(field.getName()).equals(mapKey)) {
							ReflectUtil.setFieldValue(obj, field.getName(), mapValue);
							break;
						}
					}

				}

				list.add((T) obj);
			}

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

		return list;
	}

	public String buildSql(String sql) {
		if (StrUtil.isEmpty(sql)) {
			return "";
		}

		if (!url.contains("mysql")) {
			sql = sql.replace("`", "\"");
		}

		return sql;
	}

	public String buildLimit(Page page) {
		if (url.contains("mysql") || url.contains("sqlite")) {
			return " LIMIT " + (page.getPageNum() - 1) * page.getPageSize() + "," + page.getPageSize();
		} else {
			return " LIMIT " + page.getPageSize() + " OFFSET " + (page.getPageNum() - 1) * page.getPageSize();
		}
	}

	public List<Field> getFields(Class<? extends Object> clazz) {

		Field[] fields = ReflectUtil.getFields(clazz);
		List<Field> list = new ArrayList<>();
		for (Field field : fields) {
			if (!field.toString().contains("static") && !field.toString().contains("final")) {
				list.add(field);
			}
		}

		return list;
	}

}
