package com.storlead.framework.mybatis.interceptor;//package com.storlead.sales.config.mybatis.interceptor;
//
//import cn.hutool.core.util.StrUtil;
//import com.storlead.common.util.SpringContextUtils;
//import com.storlead.message.service.impl.MessageService;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.ibatis.cache.CacheKey;
//import org.apache.ibatis.executor.Executor;
//import org.apache.ibatis.executor.ResultExtractor;
//import org.apache.ibatis.mapping.BoundSql;
//import org.apache.ibatis.mapping.MappedStatement;
//import org.apache.ibatis.mapping.ParameterMapping;
//import org.apache.ibatis.plugin.*;
//import org.apache.ibatis.reflection.MetaObject;
//import org.apache.ibatis.session.Configuration;
//import org.apache.ibatis.session.ResultHandler;
//import org.apache.ibatis.session.RowBounds;
//import org.apache.ibatis.type.TypeHandlerRegistry;
//import org.springframework.core.annotation.Order;
//import org.springframework.util.CollectionUtils;
//
//import java.lang.reflect.InvocationTargetException;
//import java.text.DateFormat;
//import java.util.*;
//import java.util.regex.Matcher;
//import java.util.regex.Pattern;
//
///**
// * @program: sp-sales-platform
// * @description:
// * @author: chenkq
// * @create: 2024-04-17 17:32
// */
//@Slf4j
//@Order(Integer.MIN_VALUE)
//@Intercepts({
//        //type指定代理的是那个对象，method指定代理Executor中的那个方法,args指定Executor中的query方法都有哪些参数对象
//        //由于Executor中有两个query，因此需要两个@Signature
//        @Signature(type = ResultExtractor.class, method = "extractObjectFromList", args = {List.class, Class.class}),
//        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
//        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
//        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
//})
//public class MessageSqlInterceptor implements Interceptor {
//
//    @Override
//    public Object intercept(Invocation invocation) {
//        Object returnValue = null;
//        try {
//            MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
//            String sqlType = mappedStatement.getSqlCommandType().name();
//            log.debug("==> 执行sql类型: {}", sqlType);
//            //参数对象
//            Object parameter = null;
//            if (invocation.getArgs().length > 1) {
//                //获得查询方法的参数，比如selectById(Integer id,String name)，那么就可以获取到四个参数分别是：
//                //{id:1,name:"user1",param1:1,param2:"user1"}
//                parameter = invocation.getArgs()[1];
//            }
//            //获得mybatis的*mapper.xml文件中映射的方法，如：com.storlead.project.mapper.UserMapper.selectById
//            String sqlId = mappedStatement.getId();
//
//            // 获取旧参数，
//            // 获取模板，匹配业务规则
//            // 找到模板
//            // 组装参数
//
//            //将参数和映射文件组合在一起得到BoundSql对象
//            BoundSql boundSql = mappedStatement.getBoundSql(parameter);
//            //获取配置信息
//            Configuration configuration = mappedStatement.getConfiguration();
//
//            log.debug("==> 执行sql mapper: {}", sqlId);
//            //通过配置信息和BoundSql对象来生成带值得sql语句
//            //TODO geneSql中的replaceFirst() 方法会报错 需要修复
//
//            //先记录执行sql语句前的时间
//            long start = System.currentTimeMillis();
//            String sql = geneSql(configuration, boundSql);
//            //打印sql语句
//            String table = "";
//            if (sqlType.equalsIgnoreCase("UPDATE")) {
//                table = regexPatternSqlTable(sql);
//            } else if (sqlType.equalsIgnoreCase("INSERT")) {
//                table = regexPatternInsertSqlTable(sql);
//            }
//
//            if (!table.equals("customer")) {
//                return invocation.proceed();
//            }
//            Map<String, Object> mapData = parseSqlToWhereAndSet(sql);
//            if (sqlType.equalsIgnoreCase("UPDATE")) {
//                mapData = parseSqlToWhereAndSet(sql);
//            }
//
//            MessageService messageService = SpringContextUtils.getBean(MessageService.class);
//            Map beforeMap = new HashMap();
//            Map afterMap = new HashMap<>();
//            if(sqlType.equalsIgnoreCase("UPDATE")) {
//                beforeMap = messageService.getOldMapData(mapData,"*",table);
//                if (StrUtil.isNotBlank(table)) {
//                    if (!CollectionUtils.isEmpty(beforeMap)) {
//                        for (Map.Entry<String, Object> entry : mapData.entrySet()) {
//                            String camelCaseKey= StrUtil.toCamelCase(entry.getKey());
//                            afterMap.put(camelCaseKey,entry.getValue());
//                        }
//
//                    }
//                }
//            }
////            if(sqlType.equalsIgnoreCase("INSERT")) {
////                if (StrUtil.isNotBlank(table)) {
////                    for (Map.Entry<String, Object> entry : mapData.entrySet()) {
////                        String camelCaseKey= StrUtil.toCamelCase(entry.getKey());
////                        afterMap.put(camelCaseKey,entry.getValue());
////                    }
////                }
////            }
//            //开始执行sql语句
//            returnValue = invocation.proceed();
//            if (returnValue instanceof Integer) {
//                //如果返回值是list，那么将list中的每个bean对象都打印出来
//                Integer var1 = (Integer) returnValue;
//                if (var1 > 0) {
//                    if (sqlType.equalsIgnoreCase("INSERT")) {
//                        if (StrUtil.isNotBlank(table)) {
//                            BoundSql insertBoundSql = mappedStatement.getBoundSql(parameter);
//                            String insertSql = geneSql(configuration, insertBoundSql);
//                            mapData = parseInsertSqlToMap(insertSql);
//
//                            for (Map.Entry<String, Object> entry : mapData.entrySet()) {
//                                String camelCaseKey= StrUtil.toCamelCase(entry.getKey());
//                                afterMap.put(camelCaseKey,entry.getValue());
//                            }
//                        }
//                    }
//                    messageService.autoMatchEventSendMessage(beforeMap,afterMap,table);
//                }
//                log.debug("<== 执行sql返回值: {}", var1);
//            }
//            //记录执行sql语句后的时间
//            long end = System.currentTimeMillis();
//            //得到执行sql语句的用了多长时间
//            long time = (end - start);
//            //以毫秒为单位打印
////            log.debug("<== 执行sql耗时：{}毫秒", time);
////            //如果是更新 或者插入操作 拦截
////            log.debug("<== 执行messagesql {} 方式",sqlType);
//
////            log.debug("<== 整体耗时：{}毫秒 ---- ", System.currentTimeMillis() - start);
//            //返回值，如果是多条记录，那么此对象是一个list，如果是一个bean对象，那么此处就是一个对象，也有可能是一个map
//        }catch (Exception ex) {
//            log.error("intercept -- exception error-- ",ex);
//        }
//
//        if (returnValue == null) {
//            log.error("intercept -- returnValue --null");
//        }
//        return returnValue;
//
//    }
//
//
//    /**
//     * 生成对应的带有值得sql语句
//     *
//     * @param configuration
//     * @param boundSql
//     * @return
//     */
//    public static String geneSql(Configuration configuration, BoundSql boundSql) {
//
//        String sql = "";
//        try {
////获得参数对象，如{id:1,name:"user1",param1:1,param2:"user1"}
//            Object parameterObject = boundSql.getParameterObject();
//            //获得映射的对象参数
//            List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
//            //获得带问号的sql语句
//            sql = boundSql.getSql().replaceAll("[\\s]+", " ");
//            //如果参数个数大于0且参数对象不为空，说明该sql语句是带有条件的
//            if (parameterMappings.size() > 0 && parameterObject != null) {
//                TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
//                //检查该参数是否是一个参数
//                if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
//                    //getParameterValue用于返回是否带有单引号的字符串，如果是字符串则加上单引号
//                    //如果是一个参数则只替换一次，将问号直接替换成值
//                    sql = sql.replaceFirst("\\?", getParameterValue(parameterObject));
//
//                } else {
//                    //将映射文件的参数和对应的值返回，比如：id，name以及对应的值。
//                    MetaObject metaObject = configuration.newMetaObject(parameterObject);
//                    //遍历参数，如:id,name等
//                    for (ParameterMapping parameterMapping : parameterMappings) {
//                        //获得属性名，如id,name等字符串
//                        String propertyName = parameterMapping.getProperty();
//                        //检查该属性是否在metaObject中
//                        if (metaObject.hasGetter(propertyName)) {
//                            //如果在metaObject中，那么直接获取对应的值
//                            Object obj = metaObject.getValue(propertyName);
//                            //然后将问号?替换成对应的值。
//                            sql = sql.replaceFirst("\\?", getParameterValue(obj));
//                        } else if (boundSql.hasAdditionalParameter(propertyName)) {
//                            Object obj = boundSql.getAdditionalParameter(propertyName);
//                            sql = sql.replaceFirst("\\?", getParameterValue(obj));
//                        }
//                    }
//                }
//            }
//        } catch (Exception e) {
//
//            log.error("geneSql -- error",e);
//        }
//
//        //最后将sql语句返回
//        return sql;
//    }
//
//    /**
//     * 如果是字符串对象则加上单引号返回，如果是日期则也需要转换成字符串形式，如果是其他则直接转换成字符串返回。
//     *
//     * @param obj
//     * @return
//     */
//    private static String getParameterValue(Object obj) {
//        String value;
//        if (obj instanceof String) {
//            value = "'" + obj.toString() + "'";
//        } else if (obj instanceof Date) {
//            DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);
//            value = "'" + formatter.format(obj) + "'";
//        } else {
//            if (obj != null) {
//                value = obj.toString();
//            } else {
//                value = "";
//            }
//
//        }
//        return value;
//    }
//
//    @Override
//    public Object plugin(Object target) {
//        return Plugin.wrap(target, this);
//    }
//
//    @Override
//    public void setProperties(Properties properties) {
//
//    }
//
//    private Map parseSqlToWhereAndSet(String updateSql) {
//        Map updateMap = SqlToJsonParser.parseSqlToWhereAndSet(updateSql);
//        return updateMap; // 返回示例的JSON字符串
//    }
//
//    private Map parseInsertSqlToMap(String insertSql) {
//        Map updateMap = SqlToJsonParser.parseInsertSqlToMap(insertSql);
//        return updateMap; // 返回示例的JSON字符串
//    }
//
//    private String regexPatternSqlTable(String updateSql) {
//        String regexPattern = "^UPDATE\\s+(\\w+)\\s+SET.*";
//        Pattern pattern = Pattern.compile(regexPattern);
//        Matcher matcher = pattern.matcher(updateSql);
//        if (matcher.find()) {
//            String tableName = matcher.group(1);
//            return tableName;
//        } else {
//            return "";
//        }
//    }
//
//    private String regexPatternInsertSqlTable(String insertSql) {
//        Map<String, String> jsonMap = new HashMap<>();
//        // 匹配 INSERT INTO 语句的正则表达式
//        String regex = "INSERT INTO\\s+(\\w+)\\s*\\(([^)]+)\\)\\s*VALUES\\s*\\(([^)]+)\\)";
//        Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
//        Matcher matcher = pattern.matcher(insertSql);
//        if (matcher.find()) {
//            String tableName = matcher.group(1);
//            return tableName;
//        } else {
//            return "";
//        }
//    }
//}
