package com.artfess.base.manager;

import com.artfess.base.query.*;
import com.artfess.base.util.BeanUtils;
import com.artfess.base.util.FieldConvertUtil;
import com.artfess.base.util.SQLUtil;
import com.artfess.base.util.StringUtil;
import com.artfess.base.util.time.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.util.Assert;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;


/**
 * QueryFilter转为Wrapper的帮助接口
 *
 * @company 阿特菲斯信息技术有限公司
 * @author heyifan
 * @email heyf@jee-soft.cn
 * @date 2020年4月9日
 */
public interface QueryFilterHelper<T> {

	public static final String INJECTION_REGEX = "[A-Za-z0-9\\_\\-\\+\\.]+";

	/**
	 * 条件SQL的KEY
	 */
	public static final String WHERE_SQL_TAG = "whereSql";
	/**
	 * 排序SQL的KEY
	 */
	public static final String ORDER_SQL_TAG = "orderBySql";

	// PageBean转换为IPage
	default IPage<T> convert2IPage(PageBean pageBean) {
		return pageBean == null ? new Page<>()
				: new Page<T>(pageBean.getPage(), pageBean.getPageSize(), pageBean.showTotal());
	}

	/**
	 * 将分组查询条件转换到wrapper里
	 */
	default void addConditionToWapper(String group, Map<String, String> groupTree, QueryWrapper<T> queryWrapper,
									  Map<String, List<QueryField>> groupQueryField, Class<T> currentModelClass) {
		List<QueryField> fields = groupQueryField.get(group);
		if (BeanUtils.isNotEmpty(fields)) {
			fields.forEach(l -> convertQueryField(queryWrapper, l, currentModelClass));
			FieldRelation groupRelation = fields.get(0).getRelation();
			if (FieldRelation.OR.equals(groupRelation)) {
				queryWrapper.or();
			}
			// 添加子分组查询条件
			groupTree.forEach((groupChild, parentGroup) -> {
				if (StringUtil.isNotEmpty(parentGroup) && parentGroup.equals(group)) {
					queryWrapper.nested(BeanUtils.isNotEmpty(groupQueryField.get(groupChild)), w -> {
						addConditionToWapper(groupChild, groupTree, w, groupQueryField, currentModelClass);
					});
				}
			});
		}
	}

	default QueryWrapper<T> convert2Wrapper(QueryFilter<?> queryFilter, Class<T> currentModelClass) {
		QueryWrapper<T> queryWrapper = new QueryWrapper<T>();
		// 1.处理QueryField（querys）列表
		Map<String, List<QueryField>> groupQueryField = queryFilter.groupQueryField();
		Map<String, String> groupTree = queryFilter.getGroupTree();
		List<String> roots = queryFilter.getRootGroup(groupTree);
		FieldRelation groupRelation = queryFilter.getGroupRelation();
		roots.forEach((group) -> {
			if (FieldRelation.OR.equals(groupRelation)) {
				queryWrapper.or();
			}
			// 删除property为空的条件
			List<QueryField> fields = null == groupQueryField.get(group) ? new ArrayList<>() : groupQueryField.get(group);
			Iterator<QueryField> i = fields.listIterator();
			while (i.hasNext()){
				QueryField field = i.next();
				if(StringUtil.isEmpty(field.getProperty()) || BeanUtils.isEmpty(field.getValue())){
					i.remove();
				}
			}
			queryWrapper.nested(BeanUtils.isNotEmpty(fields), w -> {
				addConditionToWapper(group, groupTree, w, groupQueryField, currentModelClass);
			});
		});

		// 2.处理排序字段
		Map<Direction, List<FieldSort>> groupFieldSort = queryFilter.groupFieldSort();
		groupFieldSort.forEach((d, l) -> {
			// 删除property为空的条件
			Iterator<FieldSort> i = l.listIterator();
			while (i.hasNext()){
				if(StringUtil.isEmpty(i.next().getProperty())){
					i.remove();
				}
			}
			if (Direction.DESC.equals(d)) {
				queryWrapper.orderByDesc(convertSortFieldList(l, currentModelClass));
			} else {
				queryWrapper.orderByAsc(convertSortFieldList(l, currentModelClass));
			}
		});

		// 3.处理自定义参数（使用时在sql中通过ew.paramNameValuePairs.{mapKey}的方式使用）
		Map<String, Object> params = queryFilter.getParams();
		if(params!=null && params.size() > 0) {
			Map<String, Object> paramNameValuePairs = queryWrapper.getParamNameValuePairs();
			paramNameValuePairs.putAll(params);
		}
		return queryWrapper;
	}

	// 将SortField列表转换为数据库字段数组
	default String[] convertSortFieldList(List<FieldSort> list, Class<T> currentModelClass) {
		if (list == null) {
			return null;
		}
		String[] ary = new String[list.size()];
		for (int i = 0; i < list.size(); i++) {
			if (currentModelClass != null) {
				ary[i] = FieldConvertUtil.property2Field(list.get(i).getProperty(), currentModelClass);
			} else {
				ary[i] = list.get(i).getProperty();
			}
		}
		return ary;
	}

	// 解析通用查询条件，通过QueryWrapper构建对应的查询命令
	default void convertQueryField(QueryWrapper<T> queryWrapper, QueryField queryField, Class<T> currentModelClass) {
		FieldRelation r = queryField.getRelation();
		if (FieldRelation.OR.equals(r)) {
			queryWrapper.or();
		}
		String field = queryField.getProperty();
		if (currentModelClass != null) {
			field = FieldConvertUtil.property2Field(field, currentModelClass);
		}
		QueryOP operation = queryField.getOperation();
		switch (operation) {
		case EQUAL:
		case EQUAL_IGNORE_CASE:
			queryWrapper.eq(field, queryField.getValue());
			break;
		case NOT_EQUAL:
			queryWrapper.ne(field, queryField.getValue());
			break;
		case LESS:
			queryWrapper.lt(field, queryField.getValue());
			break;
		case GREAT:
			queryWrapper.gt(field, queryField.getValue());
			break;
		case LESS_EQUAL:
			queryWrapper.le(field, queryField.getValue());
			break;
		case GREAT_EQUAL:
			queryWrapper.ge(field, queryField.getValue());
			break;
		case LIKE:
			queryWrapper.like(field, queryField.getValue());
			break;
		case LEFT_LIKE:
			queryWrapper.likeLeft(field, queryField.getValue());
			break;
		case RIGHT_LIKE:
			queryWrapper.likeRight(field, queryField.getValue());
			break;
		case IS_NULL:
			queryWrapper.isNull(field);
			break;
		case NOTNULL:
			queryWrapper.isNotNull(field);
			break;
		case IN:
			queryWrapper.in(field, convert2ObjectArray(queryField.getValue()));
			break;
        case NOT_IN:
            queryWrapper.notIn(field, convert2ObjectArray(queryField.getValue()));
            break;
		case BETWEEN:
			Object[] objs = convert2ObjectArray(queryField.getValue());
			Assert.notNull(objs, String.format("查询条件：%s的查询值为空", field));
			Assert.isTrue(objs.length == 2, String.format("查询条件为between时，查询值必须为两个，但是传入的查询值为：%s", objs));
 			String dbType = SQLUtil.getDbType();
			if ("oracle".equals(dbType) || "postgresql".equals(dbType)){
				Date[] dates = new Date[2];
				if (objs[0] instanceof String) {
					dates[0] = convertStringToDate(String.valueOf(objs[0]), DateUtil.isRqFormat(String.valueOf(objs[0]))?"yyyy-MM-dd":"yyyy-MM-dd HH:mm:ss") ;//" to_date('"+objs[0]+"','yyyy-mm-dd hh24:mi:ss') ";
				}
				if (objs[1] instanceof String) {
					dates[1] =  convertStringToDate(String.valueOf(objs[1]),DateUtil.isRqFormat(String.valueOf(objs[1]))?"yyyy-MM-dd":"yyyy-MM-dd HH:mm:ss") ;//" to_date('"+objs[1]+"','yyyy-mm-dd hh24:mi:ss') ";
				}
				queryWrapper.between(field, BeanUtils.isNotEmpty(dates[0])?dates[0]:objs[0], BeanUtils.isNotEmpty(dates[1])?dates[1]:objs[1]);
			}else {
				queryWrapper.between(field, objs[0], objs[1]);
			}
			break;
		}
	}

	default Date convertStringToDate(String str, String type) {
		DateFormat dd = new SimpleDateFormat(type);
		Date result = null;
		try {
			result = dd.parse(str);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 将传入的Object类型解析为对象数组型
	 *
	 * <pre>
	 * 1.以List格式提供的数据；
	 * 2.以逗号分割的字符串提供的数据；
	 * 3.以Object数组提供的数据。
	 * </pre>
	 *
	 * @param obj
	 * @return
	 */
	@SuppressWarnings("unchecked")
	default Object[] convert2ObjectArray(Object obj) {
		if (BeanUtils.isEmpty(obj)) {
			return new Object[] {"''"};
		}
		if (obj instanceof String) {
			// 字符串形式，通过逗号分隔
			String str = obj.toString();
			String[] split = str.split(",");
			for(int i=0;i<split.length;i++) {
				split[i] = handleQuotation(split[i]);
			}
			return split;

		} else if (obj instanceof List) {
			// 列表形式
			List<Object> objList = (List<Object>) obj;
			return objList.toArray();
		} else if (obj instanceof Object[]) {
			// 数组形式
			return (Object[]) obj;
		} else if (obj instanceof Object) {
			// 单个对象
			return new Object[] { obj };
		}
		return null;
	}

	/**
	 * 处理用单引号包起来的字符串
	 * @param str
	 * @return
	 */
	default String handleQuotation(String str) {
		String ResultString = str;
		try {
			Pattern regex = Pattern.compile("^'(.*)'$");
			Matcher regexMatcher = regex.matcher(str);
			if (regexMatcher.find()) {
				ResultString = regexMatcher.group(1);
			}
		} catch (PatternSyntaxException ex) {}
		return ResultString;
	}

	/**
	 * 將QueryFilter中的querys放入params
	 * <pre>
	 * 1.只把QueryField的property為key，value為value放入params；
	 * 2.在params中已經有該key存在時，不會使用QueryField來覆蓋。
	 * </pre>
	 * @param queryFilter
	 */
	default void copyQuerysInParams(QueryFilter queryFilter){
		List<QueryField> querys = queryFilter.getQuerys();
		Map<String, Object> params = queryFilter.getParams();
		if(BeanUtils.isNotEmpty(querys)){
			querys.forEach(i -> {
				if(!params.containsKey(i.getProperty())){
					params.put(i.getProperty(), i.getValue());
				}
			});
		}
	}

}
