package com.ag.redis;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.ag.base.DefaultBussniessImpl;
import com.ag.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.wb.common.KvBean;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 缓存表查询相关，只在此类处理
 * Created by yangxh on 2021/3/18.
 */
@Component
public class CodeSetTemplate {

    private Logger logger = Logger.getLogger(CodeSetTemplate.class);
    @Autowired
    private DefaultBussniessImpl bizDao;

    /**
     * 1.检查整个sql是否有异常
     * 1.2--异常分支，检查每个sql，有异常sql加入异常key集合，无异常继续UNION ALL拼接查询
     * 2.非s_code表查询（检查code_set中是否存在重复tableName）
     * 3.s_code表查询（检查code_set与s_code中是否有重复tableName）
     * 4。try。catch。捕获异常
     * @return
     */
    public List<KvBean> getKvBean(){
        List<KvBean> targets = new ArrayList<>();
        String codeSetSql = "select * from code_set";
        List<Map<String, String>> codeSets = bizDao.queryForList(codeSetSql);
        String kvSql = "";
        Map<String, String> scodeMap = null;
        //存储key集合
        Set<String> tabNames = new HashSet<>();
        //存储重复key
        List<String> duTabNames = new ArrayList<>();
        /**
         * code_set中的sql组合
         */
        for (Map<String, String> codeSet : codeSets){
            if (ObjectUtil.equal("S_CODE", codeSet.get("TABLE_NAME"))){
                scodeMap = codeSet;
                continue;
            }
            if(!tabNames.contains(codeSet.get("TABLE_NAME"))){
                tabNames.add(codeSet.get("TABLE_NAME"));
            }else {
                duTabNames.add(codeSet.get("TABLE_NAME"));
            }
            if (testSqlException(codeSet.get("COD_SQL")) == 0){
                targets.addAll(bizDao.list(codeSet.get("COD_SQL"), KvBean.class));
            }
            //kvSql = StrUtil.join(kvSql, "select * from (", codeSet.get("COD_SQL"), ") union all ");
        }
        Assert.isTrue(CollectionUtil.isEmpty(duTabNames), "code_set中缓存字典重复，请检查！【"+ JSON.toJSONString(duTabNames)+"】");
        //kvSql = kvSql.substring(0, kvSql.length() - 12);


        /**
         * s_code查询
         */
        List<KvBean> scodeBeans = null;
        if(scodeMap != null && scodeMap.get("COD_SQL") != null){
            scodeBeans = bizDao.list(scodeMap.get("COD_SQL"), KvBean.class);
            Map<String, List<KvBean>> scodeTabNames = scodeBeans.stream().collect(Collectors.groupingBy(KvBean::getKeyName));
            for (Map.Entry<String, List<KvBean>> entry : scodeTabNames.entrySet()){
                if(!tabNames.contains(entry.getKey())){
                    tabNames.add(entry.getKey());
                }else {
                    duTabNames.add(entry.getKey());
                }
            }
            Assert.isTrue(CollectionUtil.isEmpty(duTabNames), "code_set与s_code缓存字典重复，请检查！【"+ JSON.toJSONString(duTabNames)+"】");
            targets.addAll(scodeBeans);
        }



        /**
         * WB_KEY查询(keyName已存在则移除wb_key中数据)
         */
        /*String wbKeySql = "select KEY_NAME, K,V from  WB_KEY order  by  KEY_NAME ";
        List<KvBean> wbKeyBeans = bizDao.list(wbKeySql, KvBean.class);
        Iterator<KvBean> iter = wbKeyBeans.iterator();
        while (iter.hasNext()){
            KvBean kvBean = iter.next();
            for(String tabName : tabNames) {
                if (ObjectUtil.equal(kvBean.getKeyName(), tabName)){
                    iter.remove();
                    break;
                }
            }
        }*/

        /*if(kvSql.length() > 0 ){
            //出现sql异常，异常sql测试
            if (testSqlException(kvSql) == -1){
                List<String> exceptionKeys = new ArrayList<>();
                String msg = "";
                for (Map<String, String> codeSet : codeSets){
                    if (testSqlException(codeSet.get("COD_SQL")) == -1){
                        exceptionKeys.add(codeSet.get("TABLE_NAME"));
                    }
                }
                if (CollectionUtil.isEmpty(exceptionKeys)) {
                    msg = "sql异常，请检查！" + kvSql;
                }else {
                    msg = "sql异常，请检查这些TABLE_NAME：" + JSON.toJSONString(exceptionKeys);
                }
                throw new RuntimeException(msg);
            }
            kvSql = StrUtil.join("select * from (", kvSql, ") tal where k is not null and v is not null");
            List<KvBean> codeSetBeans = bizDao.list(kvSql, KvBean.class);
            targets.addAll(codeSetBeans);
        }*/
        return targets;

    }


    /**
     * sql异常返回-1
     * @param testSql
     * @param params
     * @return
     */
    private int testSqlException(String testSql, Object... params) {
        int num = 0;
        try {
            bizDao.count(StrUtil.join("select count(0) from (", testSql, ") a"), params);
            return num;
        }catch (Exception ex){
            num = -1;
            logger.error(ex.fillInStackTrace());
        }
        return num;
    }



    public List<KvBean> getKvBeanByTableName(String tableName){
        String codeSetSql = "select * from code_set where table_name=?";
        int num = bizDao.count("select count(0) from ("+codeSetSql+") tab", tableName);
        if (num > 0 && !"s_code".equalsIgnoreCase(tableName)){
            //code_set中存在tableName（不包含s_code）
            List<Map<String, String>> codeSets = bizDao.queryForList(codeSetSql, tableName);
            return bizDao.list(codeSets.get(0).get("COD_SQL"), KvBean.class);
        }else {
            //s_code中的字典
            String scodeSql = "select COD_SQL from code_set where table_name='S_CODE'";
            List<String> codSql = bizDao.listSingleColumn(scodeSql, String.class);
            scodeSql = StrUtil.join("select * from (", codSql.get(0), " ) a WHERE a.key_name=?");
            num = bizDao.count("select count(0) from ("+scodeSql+") tab", tableName);
            if (num > 0){
                return bizDao.list(scodeSql, KvBean.class, tableName);
            }
        }
        return null;

    }

    public boolean isContainsDefault(String tableName){
        String codeSetSql = "select * from code_set where table_name=? and table_name<>'S_CODE'";
        List<Map<String, String>> codeSets = bizDao.queryForList(codeSetSql, tableName);
        if (CollectionUtil.isEmpty(codeSets)){
            throw new RuntimeException("codeSet中【"+tableName+"】未维护");
        }
        return ObjectUtil.equal(codeSets.get(0).get("IS_DEFAULT"),"1");
    }

    public List<String> getDefaultTabNames() {
        String codeSetSql = "select TABLE_NAME from code_set where IS_DEFAULT=1";
        return bizDao.listSingleColumn(codeSetSql, String.class);
    }
}
