package cn.stylefeng.team.meta.db;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Entity;
import cn.stylefeng.team.meta.db.pojo.DatabaseConfig;
import cn.stylefeng.team.meta.db.pojo.JsonDataInfo;
import cn.stylefeng.team.meta.db.pojo.query.Group;
import cn.stylefeng.team.meta.db.querybuilder.QueryConditionBuilder;

import java.util.HashMap;
import java.util.List;

public class MysqlDataCollector extends BaseDataCollector {

    private static final String PAGE_QUERY = "SELECT * FROM {tableName} LIMIT {limitStart},{limitEnd}";

    private static final String PAGE_QUERY_WITH_CONDITION = "SELECT * FROM {tableName} where {condition} LIMIT {limitStart},{limitEnd}";

    private static final String QUERY_TOTAL = "SELECT * FROM {tableName}";

    private static final String QUERY_TOTAL_COUNT = "SELECT COUNT(1) as totalCount FROM {tableName}";

    private static final String QUERY_TOTAL_COUNT_WITH_CONDITION = "SELECT COUNT(1) as totalCount FROM {tableName} where {condition}";

    public MysqlDataCollector(DatabaseConfig databaseConfig) {
        super(databaseConfig);
    }

    @Override
    public List<Entity> queryTotal(String tableName) {
        HashMap<String, Object> stringStringHashMap = new HashMap<>();
        stringStringHashMap.put("tableName", tableName);
        return this.queryDataList(StrUtil.format(QUERY_TOTAL, stringStringHashMap));
    }

    @Override
    public Long queryTotalCount(String tableName) {
        HashMap<String, Object> stringStringHashMap = new HashMap<>();
        stringStringHashMap.put("tableName", tableName);
        return commonQueryTotal(stringStringHashMap, QUERY_TOTAL_COUNT);
    }

    @Override
    public Long queryTotalCount(String tableName, Group queryCondition) {
        if (ObjectUtil.isEmpty(queryCondition) || ObjectUtil.isEmpty(queryCondition.getFilters())) {
            return queryTotalCount(tableName);
        }

        String whereSql = new QueryConditionBuilder().build(queryCondition);

        HashMap<String, Object> stringStringHashMap = new HashMap<>();
        stringStringHashMap.put("tableName", tableName);
        stringStringHashMap.put("condition", whereSql);
        return commonQueryTotal(stringStringHashMap, QUERY_TOTAL_COUNT_WITH_CONDITION);
    }

    @Override
    public List<JsonDataInfo> queryTotalToJson(String tableName) {
        List<Entity> entities = this.queryTotal(tableName);
        return toJsonDataInfo(entities);
    }

    @Override
    public List<Entity> pageQuery(String tableName, Integer pageSize, Integer pageNo) {
        HashMap<String, Object> stringStringHashMap = new HashMap<>();
        stringStringHashMap.put("tableName", tableName);
        stringStringHashMap.put("limitStart", (pageNo - 1) * pageSize);
        stringStringHashMap.put("limitEnd", (pageNo - 1) * pageSize + pageSize);
        return this.queryDataList(StrUtil.format(PAGE_QUERY, stringStringHashMap));
    }

    @Override
    public List<JsonDataInfo> pageQueryToJson(String tableName, Integer pageSize, Integer pageNo) {
        List<Entity> entities = this.pageQuery(tableName, pageSize, pageNo);
        return toJsonDataInfo(entities);
    }

    @Override
    public List<JsonDataInfo> pageQueryToJson(String tableName, Integer pageSize, Integer pageNo, Group queryCondition) {
        if (ObjectUtil.isEmpty(queryCondition) || ObjectUtil.isEmpty(queryCondition.getFilters())) {
            return pageQueryToJson(tableName, pageSize, pageNo);
        }

        String whereSql = new QueryConditionBuilder().build(queryCondition);

        HashMap<String, Object> stringStringHashMap = new HashMap<>();
        stringStringHashMap.put("tableName", tableName);
        stringStringHashMap.put("limitStart", (pageNo - 1) * pageSize);
        stringStringHashMap.put("limitEnd", (pageNo - 1) * pageSize + pageSize);
        stringStringHashMap.put("condition", whereSql);
        List<Entity> entities = this.queryDataList(StrUtil.format(PAGE_QUERY_WITH_CONDITION, stringStringHashMap));

        return toJsonDataInfo(entities);
    }

    private Long commonQueryTotal(HashMap<String, Object> paramMap, String sqlTemplate) {
        String format = StrUtil.format(sqlTemplate, paramMap);

        List<Entity> entities = this.queryDataList(format);
        if (ObjectUtil.isEmpty(entities)) {
            return 0L;
        }

        Object totalCount = entities.get(0).get("totalCount");
        return Convert.toLong(totalCount);
    }
}
