package com.github.wz2cool.dynamic.mybatis.mapper.provider;

import com.github.wz2cool.dynamic.GroupedQuery;
import com.github.wz2cool.dynamic.mybatis.QueryHelper;
import com.github.wz2cool.dynamic.mybatis.mapper.helper.BaseEnhancedMapperTemplate;
import com.github.wz2cool.dynamic.mybatis.mapper.helper.GroupedQuerySqlHelper;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.mapping.MappedStatement;
import tk.mybatis.mapper.MapperException;
import tk.mybatis.mapper.mapperhelper.EntityHelper;
import tk.mybatis.mapper.mapperhelper.MapperHelper;
import tk.mybatis.mapper.mapperhelper.SqlHelper;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;

import static tk.mybatis.mapper.util.MsUtil.getMapperClass;

/**
 * @author Frank
 * @date 2020/11/28
 **/
public class GroupedQueryProvider extends BaseEnhancedMapperTemplate {
    private static final QueryHelper QUERY_HELPER = new QueryHelper();

    public GroupedQueryProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
        super(mapperClass, mapperHelper);
    }

    @Override
    protected String tableName(Class<?> entityClass) {
        String viewExpression = QUERY_HELPER.getViewExpression(entityClass);
        if (StringUtils.isNoneBlank(viewExpression)) {
            return viewExpression;
        } else {
            return super.tableName(entityClass);
        }
    }

    public String selectByGroupedQuery(MappedStatement ms) {
        Class<?> entityClass = getEntityClass(ms);
        setResultType(ms, getSelectClass(ms));
        StringBuilder sql = new StringBuilder();
        sql.append(GroupedQuerySqlHelper.getBindFilterParams(ms.getConfiguration().isMapUnderscoreToCamelCase()));
        sql.append("SELECT");
        //支持查询指定列
        sql.append(GroupedQuerySqlHelper.getSelectColumnsClause());
        sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));
        sql.append(GroupedQuerySqlHelper.getWhereClause());
        sql.append(GroupedQuerySqlHelper.getGroupByClause());
        sql.append(GroupedQuerySqlHelper.getHavingClause());
        sql.append(GroupedQuerySqlHelper.getSortClause());
        return sql.toString();
    }

    /// region for xml query

    public static Map<String, Object> getGroupedQueryParamInternal(
            final GroupedQuery groupedQuery,
            final boolean isMapUnderscoreToCamelCase) {
        return groupedQuery.toQueryParamMap(isMapUnderscoreToCamelCase);
    }
    // endregion

    /**
     * 获取返回值类型 - 实体类型
     *
     * @param ms
     * @return
     */
    public Class<?> getSelectClass(MappedStatement ms) {
        String msId = ms.getId();
        if (entityClassMap.containsKey(msId)) {
            return entityClassMap.get(msId);
        } else {
            Class<?> mapperClass = getMapperClass(msId);
            Type[] types = mapperClass.getGenericInterfaces();
            for (Type type : types) {
                if (type instanceof ParameterizedType) {
                    ParameterizedType t = (ParameterizedType) type;
                    if (t.getRawType() == this.mapperClass || this.mapperClass.isAssignableFrom((Class<?>) t.getRawType())) {
                        if (t.getActualTypeArguments().length > 1) {
                            Class<?> returnType = (Class<?>) t.getActualTypeArguments()[t.getActualTypeArguments().length - 1];
                            //获取该类型后，第一次对该类型进行初始化
                            EntityHelper.initEntityNameMap(returnType, mapperHelper.getConfig());
                            entityClassMap.put(msId, returnType);
                            return returnType;
                        }

                    }
                }
            }
        }
        throw new MapperException("无法获取 " + msId + " 方法的泛型信息!");
    }
}

@@ -1463,32 +1463,83 @@
 Statement ms) %7B%0A
+        Class%3C?%3E selectClass = getSelectClass(ms);%0A
         Class%3C?%3E
@@ -1599,20 +1599,17 @@
 ype(ms, 
-getS
+s
 electCla
@@ -1610,20 +1610,16 @@
 ectClass
-(ms)
 );%0A     
@@ -2713,16 +2713,33 @@
 .getId()
+ + %22_selectClass%22
 ;%0A      

fix unit test issue